/* =============================================================
 * SeaLegs Tides — chart engine styles.
 *
 * Loaded by every tides shell:
 *   • tides_map_widget — composite map+chart at /tides/
 *   • chart/           — chart-only iframe at /tides/chart/
 *
 * Owns: :root tokens, page-level reset, the entire .sl-tides-* chart
 * panel (stationhead + dropdown + hero + SVG chart + daystrip), the
 * .sl-brand wordmark used by all shells, and the .poc-moon glyph
 * embedded inside the chart. The map widget loads tides_map_widget.css
 * on top for its map-shell selectors (.poc-topbar, .leaflet-*,
 * .sl-station-marker, .sl-spot-marker, .page-footer, .app grid).
 * ============================================================= */

/* Both `:root` (top-level shells: map widget, chart iframe) AND `:host`
   (Shadow DOM mounts via tides_chart_widget.js) — `:root` doesn't match
   anything inside a shadow tree, so the JS embed's adopted stylesheet
   needs `:host` to put the tokens on the host element where they cascade
   into the shadow naturally. */
:root,
:host {
  /* Marine palette */
  --tides-bg-deep:        #050d18;
  --tides-bg-mid:         #0a1929;
  --tides-bg-shallow:     #1e3a5f;
  --tides-glass-fill:     rgba(8, 18, 32, 0.72);
  --tides-glass-border:   rgba(255, 255, 255, 0.10);
  --tides-glass-shadow:   0 -20px 60px rgba(0, 0, 0, 0.55),
                          0 -2px 12px rgba(0, 0, 0, 0.3),
                          inset 0 1px 0 rgba(255, 255, 255, 0.06);

  --tides-text-primary:   #e6f4ff;
  --tides-text-secondary: rgba(230, 244, 255, 0.62);
  --tides-text-muted:     rgba(230, 244, 255, 0.38);
  --tides-text-faint:     rgba(230, 244, 255, 0.22);

  --tides-curve:          #7dd3fc;
  --tides-curve-glow:     rgba(125, 211, 252, 0.55);
  --tides-fill-top:       rgba(125, 211, 252, 0.35);
  --tides-fill-bottom:    rgba(125, 211, 252, 0.02);

  --tides-now:            #fb923c;
  --tides-now-glow:       rgba(251, 146, 60, 0.6);

  --tides-rising:         #34d399;
  --tides-rising-glow:    rgba(52, 211, 153, 0.55);
  --tides-falling:        #f87171;
  --tides-falling-glow:   rgba(248, 113, 113, 0.55);

  /* Match the rising/falling arrow palette: high (peak) = green,
     low (trough) = red. Reinforces the "rising → high" / "falling → low"
     story across hero arrow, chart pins, and extrema columns. */
  --tides-high:           #34d399;
  --tides-high-glow:      rgba(52, 211, 153, 0.55);
  --tides-low:            #f87171;
  --tides-low-glow:       rgba(248, 113, 113, 0.55);

  --tides-wave-back:      rgba(125, 211, 252, 0.07);
  --tides-wave-mid:       rgba(125, 211, 252, 0.12);
  --tides-wave-front:     rgba(125, 211, 252, 0.18);

  --tides-sky-top:        rgba(10, 25, 41, 0.0);
  --tides-sky-bottom:     rgba(10, 25, 41, 0.6);

  --tides-radius:         24px;
  --tides-pad:            28px;

  /* Mirrors TIMELINE_OVERLAY_H in tides_chart.js — the timeline strip
     occupies SVG y=0..28. CSS uses this token so the hero overlay,
     the floating tide-value badge, and the NOW edge indicators all
     stay aligned with the strip. Update both the JS constant AND this
     token together if you change the strip height. */
  --tides-timeline-h:     28px;

  /* Footer background — the ONE footer property embedders can theme.
     Override on the host element to match site theme:
        [data-sealegs-tides] { --tides-footer-bg: #fff; }
     Text colors, font sizes, brand wordmark colors, and structural
     properties (display, visibility, opacity, min-height) are all
     LOCKED with !important inside the shadow root so the SeaLegsAI
     attribution can't be hidden via CSS-variable abuse, inheritable
     property overrides, or zero-size tricks. The locked text colors
     use a white-with-dark-shadow combination that stays legible on
     both dark and light backgrounds — pick a dark bg for best
     contrast, but the attribution is visible either way. */
  --tides-footer-bg:     rgba(5, 11, 22, 0.96);
}

/* ---------------------- Light-mode palette --------------------------
 *
 * Activated by the widget JS setting data-theme="light" on the
 * shadow-root .sl-tides element. Triggered by the customer passing
 * data-theme="light" on the host element (JS embed) or ?theme=light
 * on the iframe URL.
 *
 * Same variable names as the dark default — anywhere the chart engine
 * reads var(--tides-X) gets the light value automatically. The shapes
 * of the gradients, opacities, and stroke widths all stay the same;
 * only the colors change.
 *
 * Design intent: the chart should feel like a calm daylit scene
 * (pale-blue sky, gentle water-blue waves) on white-ish embedder
 * pages, while preserving the visual hierarchy of the dark theme:
 *   - curve is the most prominent element
 *   - NOW orange marker pops against the cool blues
 *   - high/low extrema colors retain green=high, red=low semantics
 *   - day-strip cards float above water with a subtle shadow
 * ----------------------------------------------------------------- */
.sl-tides[data-theme="light"] {
  /* Sky/water background — pure light blue (Tailwind sky-* family,
     not blue-* which has a slight violet cast). Calm, lighter than
     dark mode's deep navy but still clearly "water," with no purple
     undertones. */
  --tides-bg-deep:        #e0f2fe;   /* sky-100 — pale water */
  --tides-bg-mid:         #bae6fd;   /* sky-200 — mid water */
  --tides-bg-shallow:     #7dd3fc;   /* sky-300 — shallow water */

  /* Day-strip cards — translucent white over the sky-blue, soft cyan border. */
  --tides-glass-fill:     rgba(255, 255, 255, 0.78);
  --tides-glass-border:   rgba(2, 132, 199, 0.15);
  --tides-glass-shadow:   0 -14px 36px rgba(2, 132, 199, 0.08),
                          0 -2px 10px rgba(2, 132, 199, 0.06),
                          inset 0 1px 0 rgba(255, 255, 255, 0.85);

  /* Text — dark navy hierarchy, sits on light sky-blue bg. */
  --tides-text-primary:   #0f172a;
  --tides-text-secondary: rgba(15, 23, 42, 0.7);
  --tides-text-muted:     rgba(15, 23, 42, 0.45);
  --tides-text-faint:     rgba(15, 23, 42, 0.22);

  /* Tide curve — deeper sky-600 cyan, pops against the pale sky water. */
  --tides-curve:          #0284c7;
  --tides-curve-glow:     rgba(2, 132, 199, 0.45);
  --tides-fill-top:       rgba(2, 132, 199, 0.28);
  --tides-fill-bottom:    rgba(2, 132, 199, 0.0);

  /* NOW marker — warm orange against cool sky-blue. */
  --tides-now:            #ea580c;
  --tides-now-glow:       rgba(234, 88, 12, 0.5);

  /* Rising/falling + high/low — saturated for legibility on light. */
  --tides-rising:         #15803d;
  --tides-rising-glow:    rgba(21, 128, 61, 0.45);
  --tides-falling:        #b91c1c;
  --tides-falling-glow:   rgba(185, 28, 28, 0.45);
  --tides-high:           #15803d;
  --tides-high-glow:      rgba(21, 128, 61, 0.45);
  --tides-low:            #b91c1c;
  --tides-low-glow:       rgba(185, 28, 28, 0.45);

  /* Wave layers — soft sky-blue ripples, daylight on calm water. */
  --tides-wave-back:      rgba(2, 132, 199, 0.08);
  --tides-wave-mid:       rgba(2, 132, 199, 0.12);
  --tides-wave-front:     rgba(2, 132, 199, 0.16);

  /* Sky tint overlay — daytime, gentle sky-blue (no purple). */
  --tides-sky-top:        rgba(224, 242, 254, 0.0);
  --tides-sky-bottom:     rgba(56, 189, 248, 0.25);

  /* Footer band — pale sky-blue, matches the water. */
  --tides-footer-bg:      rgba(224, 242, 254, 0.9);

  /* Glassy panel — translucent sky-blue with backdrop blur from the
     base rule. ~55% alpha so the embedder's page color is visible
     through the panel; the sky-blue tint reads as water without the
     violet cast that blue-* gives. */
  background: rgba(186, 230, 253, 0.55);    /* sky-200 @ 55% */
  background-image:
    linear-gradient(180deg, var(--tides-sky-top) 0%, var(--tides-sky-bottom) 100%),
    linear-gradient(180deg, rgba(224, 242, 254, 0.55), rgba(125, 211, 252, 0.65));
  border-top: 1px solid rgba(2, 132, 199, 0.18);
  box-shadow: 0 -16px 50px rgba(2, 132, 199, 0.10);
}

/* Footer attribution in light mode — flip the locked white-on-dark
   model to dark-on-light. The upstream rule pins
       color: rgba(255,255,255,0.92) !important
   on the assumption that "white + dark drop-shadow works on any bg,"
   which is false for the light theme: white text on
   rgba(241,245,249,0.92) is invisible no matter how strong the halo.
   These overrides have higher selector specificity AND !important so
   they beat the lock; theme switching is a SeaLegs-owned override,
   not a customer one, so the lock's intent (block customer tampering)
   is preserved. Subtle white drop-shadow ("light from above") gives
   the dark text a tiny lift off the slate bg without faking a halo. */
.sl-tides[data-theme="light"] .sl-tides-footer {
  color: rgba(15, 23, 42, 0.88) !important;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.55) !important;
  border-top: 1px solid rgba(148, 163, 184, 0.3);
}
.sl-tides[data-theme="light"] .sl-tides-footer .sl-brand-sea {
  color: #0f172a !important;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) !important;
}
.sl-tides[data-theme="light"] .sl-tides-footer .sl-brand-ai {
  /* Deeper orange (orange-700) reads against pale slate; keep a soft
     orange glow as a brand-mark cue, no dark halo. */
  color: #c2410c !important;
  text-shadow:
    0 1px 0 rgba(255, 255, 255, 0.5),
    0 0 6px rgba(251, 146, 60, 0.35) !important;
}

/* Day-strip cards in light mode — base / hover / today / active.
   Upstream rules hardcode dark-navy backgrounds (rgba(8,18,32,0.85)
   etc.) instead of using --tides-glass-fill; we override here so the
   cards read as light glass over the blue water bg. Selector
   specificity is higher than the upstream class-only selectors so
   no !important is needed. */
.sl-tides[data-theme="light"] .sl-tides-daystrip-card {
  background: rgba(255, 255, 255, 0.78);
  border-color: rgba(30, 58, 138, 0.15);
}
.sl-tides[data-theme="light"] .sl-tides-daystrip-card:hover {
  background: rgba(255, 255, 255, 0.95);
  border-color: rgba(2, 132, 199, 0.5);
}
.sl-tides[data-theme="light"] .sl-tides-daystrip-card--today {
  border-color: rgba(234, 88, 12, 0.5);
  box-shadow: 0 0 24px rgba(234, 88, 12, 0.10);
}
.sl-tides[data-theme="light"] .sl-tides-daystrip-card--active {
  /* Selected — stronger blue tint, soft sky-blue glow ring. */
  background: rgba(186, 230, 253, 0.92);  /* sky-200 */
  border-color: rgba(2, 132, 199, 0.7);
  box-shadow: 0 0 16px rgba(2, 132, 199, 0.22);
}

/* Sliding backlight under the active day-strip card. The dark-mode
   default uses a soft cyan radial-gradient at 18% alpha which reads
   well against deep navy but disappears against the pale-blue light
   bg. Boost saturation + alpha for the light theme so the moving
   glow stays visible as the user scrubs the chart. */
.sl-tides[data-theme="light"] .sl-tides-daystrip-glow {
  background: radial-gradient(ellipse 60% 100% at center,
                              rgba(2, 132, 199, 0.6) 0%,
                              rgba(2, 132, 199, 0.3) 35%,
                              rgba(2, 132, 199, 0.08) 65%,
                              transparent 85%);
}

/* Floating tide-value badge ("↗ 3.1 ft") in light mode. Upstream
   hardcodes a dark-navy bg (rgba(8,18,32,0.85)) that clashes with the
   light theme. Swap to an opaque white-with-blue-border glass look
   so the value reads cleanly against the pale-blue water bg. */
.sl-tides[data-theme="light"] .sl-tides-now-badge {
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid rgba(2, 132, 199, 0.35);
  box-shadow:
    0 6px 20px rgba(30, 58, 138, 0.15),
    0 0 28px rgba(2, 132, 199, 0.10);
}
.sl-tides[data-theme="light"] .sl-tides-now-badge .sl-tides-hero-value {
  text-shadow: none;
}

/* In-strip NOW pill (the SVG rect at the top of the timeline) — same
   problem: hardcoded dark-navy fill. Override to a near-white fill so
   the orange "NOW" text + orange chevron read as a light pill, not
   a dark island in a light strip. */
.sl-tides[data-theme="light"] .sl-tides-timeline-now-pill {
  fill: rgba(255, 255, 255, 0.92);
  stroke: rgba(234, 88, 12, 0.55);
}
.sl-tides[data-theme="light"] .sl-tides-timeline-now-chevron {
  stroke: rgba(15, 23, 42, 0.4);
}

/* Edge-of-strip NOW snap-back button (visible when scrubbed off the
   current time). Same dark-navy override. */
.sl-tides[data-theme="light"] .sl-tides-now-indicator {
  background: rgba(255, 255, 255, 0.92);
  border-color: rgba(234, 88, 12, 0.5);
}

/* Vertical NOW marker line (the dashed orange line through the chart).
   Inline SVG attribute on the <line> hardcodes the dark-mode default
       stroke="rgba(251, 146, 60, 0.85)" stroke-width="1.75" stroke-dasharray="4 4"
   which reads cleanly on dark navy. In light mode the chart's water
   gradient runs through pale sky-blue at mid-height where saturated
   orange has lower perceptual contrast, so we shift to a deeper-orange
   hue (orange-700) at higher alpha. Presentation attributes have lower
   specificity than CSS rules, so this overrides the inline stroke. */
.sl-tides[data-theme="light"] .sl-tides-now > line {
  stroke: rgba(194, 65, 12, 0.9);
  stroke-width: 1.75;
}

/* Station-picker dropdown — opens when the user clicks the chevron
   next to the station name. Hardcoded dark-navy bg in the base rule;
   override to a solid white panel so the dropdown matches the rest of
   the light UI when the user interacts. Solid (not translucent) for
   the same backdrop-filter-flicker reason documented above. */
.sl-tides[data-theme="light"] .sl-tides-station-dropdown {
  background: #ffffff;
  border: 1px solid rgba(2, 132, 199, 0.25);
  box-shadow: 0 12px 40px rgba(2, 132, 199, 0.18);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--tides-bg-deep);
  color: var(--tides-text-primary);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ================ Tides panel ================ */

.sl-tides {
  position: relative;
  min-height: 0;
  z-index: 20;

  /* 3 rows: stationhead (auto, may be 0 when hideTitleBar is set),
     body (1fr — chart + overlays), footer (auto). The footer carries
     the SeaLegsAI attribution by default; embedders can override
     with a `footer` opt / `data-footer` attribute / `?footer=` URL
     param on the iframe shells. */
  display: grid;
  grid-template-rows: auto 1fr auto;
  /* Pin the column to the panel's own width. Without this, an overflowing
     child (the day strip's 7 × 200px cards) would expand the auto-sized
     column and push the stationhead, hero, and footer to the same wider
     width — the panel's overflow-x clips the right portion, hiding the
     station-name dropdown offscreen and stopping the strip from ever
     hitting its own overflow-x:auto threshold. */
  grid-template-columns: minmax(0, 1fr);

  /* Tide-chart text is presentational — never selectable. Prevents
     accidental text selection during chart-scrub drag and on simple
     interactions. Inputs + links override below to remain interactive. */
  user-select: none;
  -webkit-user-select: none;

  background: rgba(8, 18, 32, 0.92);
  border-top: 1px solid rgba(125, 211, 252, 0.18);
  box-shadow: 0 -16px 50px rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(28px) saturate(160%);
  -webkit-backdrop-filter: blur(28px) saturate(160%);
  overflow: hidden;
  isolation: isolate;
  background-image: linear-gradient(180deg, var(--tides-sky-top) 0%, var(--tides-sky-bottom) 100%), linear-gradient(180deg, rgba(8, 18, 32, 0.92), rgba(5, 13, 24, 0.96));
  transition: opacity 0.2s ease;
}

.sl-tides input,
.sl-tides a,
.sl-tides button {
  user-select: auto;
  -webkit-user-select: auto;
}

/* Subtle cyan reflection along the top edge — feels like the panel is
   sitting in moonlit water, with light catching the upper rim. */
.sl-tides::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(125, 211, 252, 0.5) 50%,
    transparent 100%
  );
  pointer-events: none;
  z-index: 10;
}

/* Body grid: chart on top spans full width, day-strip below. The
   chart-area `1fr` claims the available vertical room and the strip is
   `auto` (sized to its own height). `min-width: 0` is critical: without
   it, the body would inherit the default grid-item `min-width: auto`,
   letting an overflowing child (the day strip) expand the body past the
   panel width — which would in turn defeat the strip's own overflow-x
   scroll. */
.sl-tides-body {
  /* Always sit at row 2 of the parent grid — when the title bar is
     hidden via `hideTitleBar`, the body would otherwise auto-place at
     row 1 (the `auto` track) and size to its content, collapsing the
     chart to 0px. Explicit grid-row: 2 keeps it in the 1fr track
     regardless of sibling count.

     New (full-panel chart) layout: the chart SVG fills the entire body,
     and the hero + daystrip are absolute-positioned overlays on top.
     This lets the chart's sky bands extend up behind the hero and the
     water/waves extend down behind the daystrip cards — visually one
     continuous atmospheric scene with floating UI elements. */
  grid-row: 2;
  position: relative;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

/* body-main is the legacy grid wrapper. In the full-panel layout it's
   not used — the hero, chart, and daystrip are direct children of body
   and laid out via absolute positioning. Kept here as a no-op rule in
   case any future code re-renders it; safe to remove once we're sure
   nothing references it. */
.sl-tides-body-main { display: contents; }

/* Soft loading hint. Was 0.5 — too dim, especially on mobile where
   widgets below the fold finish loading after the user scrolls down,
   producing a visible "ghost panel" before the chart renders. */
.sl-tides.is-loading { opacity: 0.85; }

.sl-tides-skeleton {
  padding: 60px 32px;
  text-align: center;
  color: var(--tides-text-muted);
  font-weight: 300;
  letter-spacing: 0.05em;
}

/* ---------- Header (station name + dropdown trigger) ---------- */

.sl-tides-stationhead {
  position: relative;
  /* z-index + position: relative establishes a stacking context that
     outranks the body's siblings (.sl-tides-body, etc.). Without this,
     the dropdown — z-index: 100 within stationhead's context — gets
     visually obscured for the first ~1–2s after mount: the body's
     hero / daystrip / footer animate in via fade-in-up which uses
     `transform`, creating their own stacking contexts that paint on
     top of the dropdown until the animation ends. Matt observed
     this as "dropdown opens behind another panel initially." Bumping
     stationhead to z: 30 (well above .sl-tides-chart-container's z: 1)
     lifts the entire title-bar subtree, including the dropdown that
     extends below it, above the animating chart elements. */
  z-index: 30;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px var(--tides-pad);
  border-bottom: 1px solid var(--tides-glass-border);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  background: linear-gradient(180deg, rgba(125, 211, 252, 0.06) 0%, rgba(125, 211, 252, 0.025) 100%);
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.02);
}

.sl-tides-stationhead-name { color: var(--tides-text-primary); }
.sl-tides-stationhead-dist { color: var(--tides-text-muted); }

.sl-tides-stationhead-meta {
  position: absolute;
  right: var(--tides-pad);
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 10px;
  color: var(--tides-text-muted);
  letter-spacing: 0.04em;
}

/* Inline moon-phase glyph used inside the chart panel. */
.poc-moon {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  filter: drop-shadow(0 0 4px rgba(230, 244, 255, 0.35));
}
.poc-moon svg { display: block; }

.sl-tides-station-trigger {
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  padding: 4px 10px;
  border-radius: 8px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.sl-tides-station-trigger:hover,
.sl-tides-station-trigger.is-open {
  background: rgba(125, 211, 252, 0.08);
  border-color: rgba(125, 211, 252, 0.3);
}
.sl-tides-station-chevron {
  color: var(--tides-text-muted);
  transition: transform 0.15s ease, color 0.15s ease;
}
.sl-tides-station-trigger:hover .sl-tides-station-chevron,
.sl-tides-station-trigger.is-open .sl-tides-station-chevron {
  color: var(--tides-curve);
}
.sl-tides-station-trigger.is-open .sl-tides-station-chevron {
  transform: rotate(180deg);
}

.sl-tides-station-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  min-width: 280px;
  max-width: 90vw;
  max-height: 60vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* Fully opaque bg + no backdrop-filter. Earlier this used
     rgba(8,18,32,0.98) + backdrop-filter: blur(20px), but Safari (and
     occasionally Chrome) have a 1–2 frame rendering delay on
     backdrop-filter where the dropdown briefly shows the moving
     wave/sky animations bleeding through before the blur stabilizes —
     reads as the dropdown "fading in to opaque" over a second or two.
     Since the bg was already 98% opaque, the blur was barely doing
     visual work; replacing with solid fill kills the flicker. */
  background: #08121f;
  border: 1px solid rgba(125, 211, 252, 0.2);
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6);
  z-index: 100;
  letter-spacing: normal;
  text-transform: none;
}

.sl-tides-station-dropdown[hidden] { display: none; }

.sl-tides-station-tabs {
  display: flex;
  gap: 4px;
  padding: 6px;
  border-bottom: 1px solid rgba(125, 211, 252, 0.12);
}

.sl-tides-station-tab {
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  color: var(--tides-text-secondary);
  padding: 6px 12px;
  border-radius: 8px;
  font: inherit;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.sl-tides-station-tab:hover { color: var(--tides-text-primary); background: rgba(125, 211, 252, 0.06); }
.sl-tides-station-tab.is-active {
  background: rgba(125, 211, 252, 0.14);
  border-color: rgba(125, 211, 252, 0.3);
  color: var(--tides-curve);
}
.sl-tides-station-tab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: rgba(125, 211, 252, 0.18);
  color: var(--tides-curve);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.sl-tides-station-empty {
  padding: 20px 16px;
  font-size: 12px;
  color: var(--tides-text-muted);
  text-align: center;
  line-height: 1.4;
}

.sl-tides-stationhead-trigger-wrap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.sl-tides-favstar {
  appearance: none;
  background: transparent;
  border: none;
  color: var(--tides-text-muted);
  font-size: 16px;
  line-height: 1;
  padding: 4px 6px;
  border-radius: 6px;
  cursor: pointer;
  transition: color 0.12s ease, background 0.12s ease, transform 0.12s ease;
}
.sl-tides-favstar:hover {
  color: #fbbf24;
  background: rgba(251, 191, 36, 0.08);
}
.sl-tides-favstar.is-favorited { color: #fbbf24; text-shadow: 0 0 8px rgba(251, 191, 36, 0.6); }
.sl-tides-favstar.is-favorited:hover { transform: scale(1.1); }
.sl-tides-favstar--row { font-size: 14px; padding: 2px 4px; }

.sl-tides-station-dropdown-head {
  padding: 8px 12px 4px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--tides-text-muted);
  border-bottom: 1px solid rgba(125, 211, 252, 0.08);
}

.sl-tides-station-list {
  list-style: none;
  margin: 0;
  padding: 4px;
  overflow-y: auto;
}

.sl-tides-station-item {
  display: grid;
  grid-template-columns: 18px 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 500;
  color: var(--tides-text-primary);
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.12s ease;
}
.sl-tides-station-item:hover { background: rgba(125, 211, 252, 0.08); }
.sl-tides-station-item.is-selected { background: rgba(125, 211, 252, 0.16); }

.sl-tides-station-item-check { color: var(--tides-curve); font-size: 14px; line-height: 1; text-align: center; }
.sl-tides-station-item-name { letter-spacing: 0.01em; }
.sl-tides-station-item-state { color: var(--tides-text-muted); font-weight: 400; font-size: 11px; }
.sl-tides-station-item-dist { color: var(--tides-text-muted); font-size: 11px; font-weight: 400; }

/* ---------- Hero ---------- */

.sl-tides-hero {
  /* Absolute overlay sitting BELOW the timeline strip (at SVG
     y=0..var(--tides-timeline-h)). The hero only contains the
     next-extreme readout (HIGH/LOW countdown) on the right now —
     the floating tide-value badge anchored to the active NOW/scrub
     line is rendered as a sibling outside the hero. */
  position: absolute;
  top: var(--tides-timeline-h);
  left: 0;
  right: 0;
  z-index: 3;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 14px var(--tides-pad) 12px;
  background: transparent;
  /* Click-through so the user can scrub the chart by tapping in the
     hero's empty zones; interactive children re-enable pointer events
     below. */
  pointer-events: none;
}
.sl-tides-hero > * {
  pointer-events: auto;
}

/* Floating tide-value badge that anchors to the top of the current
   NOW or scrub vertical line in the chart. Its `left` is set by
   _updateHero / scroll listener as `xOf(displayTime) - scrollLeft`
   so it tracks both scrubbing AND horizontal chart scroll. */
.sl-tides-now-badge {
  position: absolute;
  /* Timeline strip height + 18px hero-internal offset, leaving the
     strip visible above the badge. */
  top: calc(var(--tides-timeline-h) + 18px);
  left: 0;
  z-index: 4;            /* above the hero overlay (z 3) */
  transform: translateX(-50%);
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 14px 5px;
  border-radius: 14px;
  background: rgba(8, 18, 32, 0.85);
  border: 1px solid rgba(125, 211, 252, 0.32);
  box-shadow:
    0 6px 20px rgba(0, 0, 0, 0.45),
    0 0 28px rgba(125, 211, 252, 0.12);
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  pointer-events: none;
  /* Smooth glide when scrubbing to a different time. Disabled during
     horizontal scroll so the badge tracks the line tightly without
     lagging. The JS toggles a `is-scrolling` class to suppress
     transitions while scrolling. */
  transition: left 0.25s ease;
  font-variant-numeric: tabular-nums;
  /* Hidden until the chart geometry is ready. JS reveals it after
     the first _updateHero call positions it. */
  visibility: hidden;
}
.sl-tides-now-badge.is-ready {
  visibility: visible;
}
.sl-tides-now-badge.is-scrolling {
  transition: none;
}
/* Scale the value/units/arrow down inside the badge — the original
   44px hero-value was sized for a centered-in-the-hero layout where
   the number was the focal point of the panel. As a floating badge
   anchored to the line, a smaller scale reads better. */
.sl-tides-now-badge .sl-tides-hero-value {
  font-size: 22px;
  text-shadow: 0 0 12px rgba(125, 211, 252, 0.4);
}
.sl-tides-now-badge .sl-tides-hero-units {
  font-size: 11px;
}
.sl-tides-now-badge .sl-tides-hero-arrow {
  font-size: 16px;
  margin-right: 0;
}

.sl-tides-hero-now {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  justify-self: center;
  font-variant-numeric: tabular-nums;
}

.sl-tides-hero-value {
  font-family: 'Outfit', 'Inter Tight', 'Inter', sans-serif;
  font-weight: 600;
  font-size: 44px;
  letter-spacing: -0.02em;
  color: var(--tides-text-primary);
  line-height: 1;
  text-shadow: 0 0 20px rgba(125, 211, 252, 0.35);
}

.sl-tides-hero-units {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--tides-text-secondary);
  text-transform: lowercase;
}

.sl-tides-hero-arrow {
  font-size: 26px;
  font-weight: 600;
  margin-right: 4px;
  line-height: 1;
  color: var(--tides-text-muted);
  transition: color 0.3s ease, text-shadow 0.3s ease;
}
.sl-tides-hero-arrow.is-rising  { color: var(--tides-rising);  text-shadow: 0 0 8px var(--tides-rising-glow);  }
.sl-tides-hero-arrow.is-falling { color: var(--tides-falling); text-shadow: 0 0 8px var(--tides-falling-glow); }

.sl-tides-hero-next {
  font-size: 12px;
  font-weight: 500;
  color: var(--tides-text-muted);
  letter-spacing: 0.04em;
  justify-self: end;
  text-align: right;
}
.sl-tides-hero-next-label { color: var(--tides-text-primary); font-weight: 700; letter-spacing: 0.12em; }
.sl-tides-hero-next-time  { color: var(--tides-curve); font-weight: 700; }

.sl-tides-chart-container {
  /* Fills the whole body in the full-panel layout. The hero + daystrip
     overlay it via absolute positioning. */
  position: absolute;
  inset: 0;
  z-index: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

.sl-tides-chart-wrap {
  height: 100%;
  width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  cursor: grab;
  scrollbar-width: none;
  /* Lock the wrap so it never grows past its container — prevents the
     SVG's natural width from stretching the parent grid cell. */
  contain: size layout;
}
.sl-tides-chart-wrap::-webkit-scrollbar { display: none; }
.sl-tides-chart-wrap.is-grabbing { cursor: grabbing; }

.sl-tides-chart-svg {
  display: block;
  height: 100%;
  width: auto;     /* SVG keeps its native width (chartW) so we can scroll it */
}

.sl-tides-moon-arc {
  fill: none;
  stroke: rgba(230, 244, 255, 0.32);
  stroke-width: 1.2;
  stroke-dasharray: 3 3;
}

.sl-tides-moon-disc {
  fill: rgba(20, 28, 48, 0.85);
  stroke: rgba(230, 244, 255, 0.25);
  stroke-width: 0.7;
}

.sl-tides-moon-lit-base {
  fill: rgba(245, 240, 220, 0.82);
}

.sl-tides-moon-mare       { fill: rgba(160, 145, 110, 0.55); }
.sl-tides-moon-mare--faint { fill: rgba(170, 155, 120, 0.32); }

.sl-tides-moon-crater     { fill: rgba(110, 95, 70, 0.55); }
.sl-tides-moon-crater--rim { fill: none; stroke: rgba(245, 240, 220, 0.28); stroke-width: 0.005; }

.sl-tides-moon-halo {
  fill: rgba(230, 244, 255, 0.05);
}

.sl-tides-moon-lit {
  fill: rgba(230, 244, 255, 0.92);
  filter: drop-shadow(0 0 6px rgba(230, 244, 255, 0.55));
}

.sl-tides-sun-arc {
  fill: none;
  stroke: rgba(253, 224, 71, 0.32);
  stroke-width: 1.2;
  stroke-dasharray: 4 3;
}
.sl-tides-sun-halo {
  fill: rgba(253, 224, 71, 0.06);
}
.sl-tides-sun-disc {
  fill: rgba(253, 224, 71, 0.95);
  filter: drop-shadow(0 0 6px rgba(253, 224, 71, 0.6));
}
.sl-tides-sun-rays line {
  stroke: rgba(253, 224, 71, 0.85);
  stroke-width: 1.2;
  stroke-linecap: round;
}
.sl-tides-sun-rays {
  filter: drop-shadow(0 0 4px rgba(253, 224, 71, 0.55));
}

.sl-tides-curve {
  fill: none;
  stroke: var(--tides-curve);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 8px var(--tides-curve-glow));
}

.sl-tides-curve.is-revealing {
  stroke-dasharray: var(--curve-len, 4000);
  stroke-dashoffset: var(--curve-len, 4000);
  animation: curve-reveal 1.6s ease-out 0.2s forwards;
}

@keyframes curve-reveal {
  to { stroke-dashoffset: 0; }
}

.sl-tides-fill {
  /* Fill is set as a presentation attribute on the path so each chart
     instance can reference its own per-instance gradient id (e.g.
     `tides-gradient-fill-c5`). Defining `fill: url(...)` here would beat
     the presentation attribute and point at a stale id. */
  pointer-events: none;
}

.sl-tides-dotted-baseline {
  stroke: rgba(230, 244, 255, 0.15);
  stroke-width: 1;
  stroke-dasharray: 1 4;
  stroke-linecap: round;
}

.sl-tides-y-grid {
  stroke: rgba(230, 244, 255, 0.04);
  stroke-width: 1;
  stroke-dasharray: 1 5;
}

.sl-tides-y-axis {
  position: absolute;
  top: 0;
  height: 100%;
  width: 36px;
  pointer-events: none;
  font-size: 10px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--tides-text-muted);
}
.sl-tides-y-axis--left  { left: 0; }
.sl-tides-y-axis--right { right: 0; }

.sl-tides-y-tick {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  white-space: nowrap;
}

.sl-tides-y-axis--left .sl-tides-y-tick  { left: 6px; }
.sl-tides-y-axis--right .sl-tides-y-tick { right: 6px; flex-direction: row-reverse; }

.sl-tides-y-num {
  color: var(--tides-text-secondary);
  letter-spacing: 0.02em;
}

.sl-tides-y-unit {
  color: var(--tides-text-faint);
  font-size: 8px;
  letter-spacing: 0.1em;
  text-transform: lowercase;
}

.sl-tides-y-tick--datum {
  color: var(--tides-curve);
  font-weight: 700;
}
.sl-tides-y-tick--datum .sl-tides-y-num   { color: var(--tides-curve); }
.sl-tides-y-tick--datum .sl-tides-y-mllw  { color: var(--tides-curve); font-size: 8px; letter-spacing: 0.1em; }

.sl-tides-y-dot {
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--tides-curve);
  box-shadow: 0 0 6px var(--tides-curve-glow);
}

.sl-tides-now-dot {
  fill: var(--tides-now);
  filter: drop-shadow(0 0 8px var(--tides-now-glow));
  animation: now-pulse 2.5s ease-in-out infinite;
  /* Without these two, SVG `transform: scale()` runs from the (0,0)
     SVG origin instead of the circle's own center — pulsing the dot
     diagonally toward the bottom-right of the chart at the same rate
     as the wave undulation. fill-box pins origin to the circle. */
  transform-origin: center;
  transform-box: fill-box;
}

@keyframes now-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.08); }
}

.sl-tides-now-ring {
  fill: none;
  stroke: var(--tides-now);
  stroke-width: 1.5;
  opacity: 0.45;
  animation: now-ring-expand 2.5s ease-out infinite;
  transform-origin: center;
  transform-box: fill-box;
}

@keyframes now-ring-expand {
  0%   { transform: scale(0.6); opacity: 0.6; }
  100% { transform: scale(2.6); opacity: 0; }
}

.sl-tides-scrub-time-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  fill: rgba(230, 244, 255, 0.95);
  paint-order: stroke fill;
  stroke: rgba(8, 18, 32, 0.9);
  stroke-width: 3;
  stroke-linejoin: round;
}

.sl-tides-pin {
  animation: pin-fade-in 0.5s ease both;
}

@keyframes pin-fade-in {
  from { opacity: 0; transform: translateY(2px); }
  to   { opacity: 1; transform: translateY(0); }
}

.sl-tides-pin-circle-high { fill: var(--tides-high); filter: drop-shadow(0 0 6px var(--tides-high-glow)); }
.sl-tides-pin-circle-low  { fill: var(--tides-low);  filter: drop-shadow(0 0 6px var(--tides-low-glow)); }

.sl-tides-pin-label {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  fill: rgba(230, 244, 255, 0.85);
  paint-order: stroke fill;
  stroke: rgba(8, 18, 32, 0.85);
  stroke-width: 2;
  stroke-linejoin: round;
}

.sl-tides-day-divider {
  stroke: rgba(230, 244, 255, 0.06);
  stroke-width: 1;
}

/* ---------- Timeline strip ---------- */
/* A horizontal ruler at the top of the chart drawing area showing
   day labels (DOW M/D), hour ticks (every hour, major every 6h with
   labels), a permanent NOW chevron, and (when scrubbing) a scrub
   chevron. Replaces the day-label and hour-label text that used to
   render inside the chart drawing zone. */

.sl-tides-timeline-bg {
  fill: rgba(0, 0, 0, 0.32);
}
.sl-tides-timeline-tick {
  stroke: rgba(230, 244, 255, 0.32);
  stroke-width: 1;
  stroke-linecap: round;
}
.sl-tides-timeline-tick.is-major {
  stroke: rgba(230, 244, 255, 0.6);
  stroke-width: 1.5;
}
.sl-tides-timeline-hour-label {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.04em;
  fill: rgba(230, 244, 255, 0.7);
  font-variant-numeric: tabular-nums;
}
.sl-tides-timeline-day-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  fill: rgba(230, 244, 255, 0.95);
  text-transform: uppercase;
  paint-order: stroke fill;
  stroke: rgba(8, 18, 32, 0.85);
  stroke-width: 2.5;
  stroke-linejoin: round;
}

/* NOW chevron — orange, sits in the strip above the curve's NOW line. */
.sl-tides-timeline-now-chevron {
  fill: var(--tides-now);
  stroke: rgba(8, 18, 32, 0.6);
  stroke-width: 1;
  filter: drop-shadow(0 0 6px var(--tides-now-glow));
}
/* Subtle pill behind the NOW text — reads as a small button on the
   timeline, occludes any hour/day label sharing the same x. */
.sl-tides-timeline-now-pill {
  fill: rgba(5, 11, 22, 0.85);
  stroke: rgba(251, 146, 60, 0.45);
  stroke-width: 1;
  filter: drop-shadow(0 0 4px var(--tides-now-glow));
}
.sl-tides-timeline-now-text {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.18em;
  fill: var(--tides-now);
}

/* Scrub chevron — cyan/light, hidden until scrubbing. */
.sl-tides-timeline-scrub-chevron {
  fill: rgba(230, 244, 255, 0.95);
  stroke: rgba(8, 18, 32, 0.6);
  stroke-width: 1;
  filter: drop-shadow(0 0 6px rgba(230, 244, 255, 0.55));
}

/* Edge "‹ NOW" / "NOW ›" indicators that appear at the left or right
   end of the timeline strip when the NOW vertical line has scrolled
   offscreen. Clicking either snaps the chart back to center NOW.
   Anchored to the same y range as the timeline (y=0..28) and inset
   slightly so they don't cover the chart's corners. */
.sl-tides-now-indicator {
  /* Same pill styling as the in-strip NOW marker — dark rounded bg,
     thin orange border, soft glow, orange "NOW" text. Reads as a
     small button at the strip edge so the user understands they can
     tap to snap back to the current time. */
  position: absolute;
  top: 4px;
  height: 16px;
  z-index: 5;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0 10px;
  appearance: none;
  border: 1px solid rgba(251, 146, 60, 0.45);
  border-radius: 999px;
  background: rgba(5, 11, 22, 0.85);
  color: var(--tides-now);
  font: inherit;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  filter: drop-shadow(0 0 4px var(--tides-now-glow));
  transition: filter 0.15s ease, transform 0.15s ease;
}
.sl-tides-now-indicator:hover {
  filter: drop-shadow(0 0 6px var(--tides-now-glow)) brightness(1.1);
  transform: translateY(-0.5px);
}
.sl-tides-now-indicator--left  { left: 8px; }
.sl-tides-now-indicator--right { right: 8px; }
.sl-tides-now-indicator-text { letter-spacing: 0.18em; }

.sl-tides-wave        { fill: var(--tides-wave-back);  }
.sl-tides-wave--mid   { fill: var(--tides-wave-mid);   }
.sl-tides-wave--front { fill: var(--tides-wave-front); }

/* Animation strategy:
   • An outer wrapper translates the wave horizontally (no anchor jitter).
   • The polygon inside undulates vertically + scales subtly so the
     wave breathes. Both run simultaneously for organic motion. */
.sl-tides-wave-flow {
  animation: wave-flow var(--flow-dur, 12s) linear infinite;
  will-change: transform;
}
@keyframes wave-flow {
  0%   { transform: translateX(0); }
  100% { transform: translateX(var(--flow-end, -200px)); }
}

.sl-tides-wave-undulate {
  animation: wave-undulate var(--undul-dur, 3s) ease-in-out infinite alternate;
  transform-origin: 50% 50%;
  will-change: transform;
}
@keyframes wave-undulate {
  0%   { transform: translateY(calc(var(--undul-amp, 8px) * -1)) scaleY(0.96); }
  100% { transform: translateY(var(--undul-amp, 8px))            scaleY(1.04); }
}

.sl-tides-wave--anim-back  {}
.sl-tides-wave--anim-mid   {}
.sl-tides-wave--anim-front {}

/* ---------- Day strip ---------- */

.sl-tides-daystrip {
  /* Absolute overlay at the bottom of the body so the chart SVG
     behind it renders its wave layers all the way down to y=panelH.
     The cards float over water — their translucent fill lets the
     wave animation show through. Background is transparent. */
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  display: flex;
  align-items: stretch;
  gap: 10px;
  padding: 12px var(--tides-pad) 14px;
  background: transparent;
  overflow-x: auto;
  scrollbar-width: thin;
  scroll-snap-type: x proximity;
  cursor: grab;
}
.sl-tides-daystrip.is-grabbing {
  cursor: grabbing;
  /* Avoid mid-drag text selection when the user dragS through card text. */
  user-select: none;
  -webkit-user-select: none;
}
.sl-tides-daystrip::-webkit-scrollbar { height: 4px; }
.sl-tides-daystrip::-webkit-scrollbar-thumb {
  background: rgba(125, 211, 252, 0.22);
  border-radius: 2px;
}

/* Sliding back-light glow positioned via JS to follow the chart's
   focus time. Doesn't intercept clicks. */
.sl-tides-daystrip-glow {
  position: absolute;
  top: 4px; bottom: 4px;
  width: var(--daystrip-glow-w, 200px);
  border-radius: 14px;
  background: radial-gradient(ellipse 60% 100% at center, rgba(125, 211, 252, 0.18) 0%, transparent 75%);
  pointer-events: none;
  transition: transform 0.35s ease, opacity 0.35s ease;
  will-change: transform, opacity;
  z-index: 0;
}

.sl-tides-daystrip-card {
  /* `min-width` floor so cards never shrink small enough to clip event
     text or bleed into the next card. Empirically 192px fits a
     two-column event row ("▲ 9:04A  3.4'" × 2) at 75px per col + 12px
     column gap + 12px side padding × 2 + a few pixels of slack —
     the scrollWidth was overflowing 156px by ~18px so this is the
     correct floor. Wider chart embeds get extra width via `flex: 1 1 0`;
     narrower ones (multi-instance pages, half-height test) trigger the
     strip's `overflow-x: auto` and become a horizontal carousel —
     same behavior the mobile breakpoint already used. */
  flex: 1 1 0;
  min-width: 192px;
  position: relative;
  appearance: none;
  /* Force top-aligned column layout — `<button>` defaults to centered
     content in some browsers, which made shorter cards (one event row)
     center the date header vertically while taller cards (two rows)
     anchored it to the top. Now the date sits at the same y on every
     card regardless of how many event rows it has. */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  /* Mostly opaque so the event text is comfortably legible against
     the animated water + wave layers behind. The remaining ~15%
     transparency keeps a subtle hint of water visible at the card
     edges so the cards read as glass panels above the surface, not
     as solid plates pasted onto the strip. */
  background: rgba(8, 18, 32, 0.85);
  border: 1px solid rgba(125, 211, 252, 0.12);
  border-radius: 14px;
  padding: 8px 12px 10px;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: border-color 0.18s ease, background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
  z-index: 1;
}
.sl-tides-daystrip-card:hover {
  /* Hover/active need solid bases now that the chart's water + wave
     animation render behind the strip. The previous translucent
     cyan-on-cyan tints (0.06 / 0.08 alpha) were invisible against
     the moving water. Hover bumps to a cyan-tinted near-opaque
     surface with a brighter border. */
  border-color: rgba(125, 211, 252, 0.5);
  background: rgba(22, 50, 90, 0.92);
  transform: translateY(-1px);
}
.sl-tides-daystrip-card:active { transform: translateY(0); }
.sl-tides-daystrip-card:focus-visible {
  outline: 2px solid var(--tides-curve);
  outline-offset: 2px;
}

.sl-tides-daystrip-card--today {
  border-color: rgba(251, 146, 60, 0.4);
  box-shadow: 0 0 24px rgba(251, 146, 60, 0.12);
}

.sl-tides-daystrip-card--active {
  /* Selected card — most prominent. Stronger cyan tint than hover,
     a soft glow ring, and a fully readable opacity. */
  border-color: rgba(125, 211, 252, 0.75);
  background: rgba(30, 70, 120, 0.95);
  box-shadow: 0 0 16px rgba(125, 211, 252, 0.22);
}

.sl-tides-daystrip-day {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--tides-text-secondary);
  text-transform: uppercase;
  margin-bottom: 6px;
}

.sl-tides-daystrip-events {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 12px;
  row-gap: 4px;
}

.sl-tides-daystrip-col {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.sl-tides-daystrip-event {
  display: grid;
  grid-template-columns: 12px auto 1fr;
  align-items: baseline;
  gap: 6px;
}

.sl-tides-daystrip-event-arrow {
  font-size: 9px;
  line-height: 1;
}

.sl-tides-daystrip-event-time {
  font-size: 11px;
  font-weight: 500;
  color: var(--tides-text-secondary);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.sl-tides-daystrip-event-height {
  justify-self: end;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

.sl-tides-daystrip-event-unit {
  font-size: 9px;
  font-weight: 500;
  margin-left: 1px;
  opacity: 0.7;
}

.sl-tides-daystrip-event--high .sl-tides-daystrip-event-arrow { color: var(--tides-high); text-shadow: 0 0 6px var(--tides-high-glow); }
.sl-tides-daystrip-event--high .sl-tides-daystrip-event-time   { color: var(--tides-text-secondary); }
.sl-tides-daystrip-event--high .sl-tides-daystrip-event-height { color: var(--tides-high); }
.sl-tides-daystrip-event--low  .sl-tides-daystrip-event-arrow { color: var(--tides-low);  text-shadow: 0 0 6px var(--tides-low-glow);  }
.sl-tides-daystrip-event--low  .sl-tides-daystrip-event-time   { color: var(--tides-text-secondary); }
.sl-tides-daystrip-event--low  .sl-tides-daystrip-event-height { color: var(--tides-low);  }

.sl-tides-daystrip-empty {
  font-size: 11px;
  color: var(--tides-text-muted);
  font-style: italic;
}

.sl-tides-footer {
  /* Bottom row of the panel grid — sits below the body (chart +
     daystrip). Holds the SeaLegsAI attribution by default, or a
     custom string if `footer` is set on the embed.

     Hardened against tampering: the only customizable property is
     `--tides-footer-bg`. Everything else (text color, font size,
     letter-spacing, brand wordmark colors, structural display) is
     pinned with !important so external CSS — even via inheritable
     properties or custom-property abuse — can't shrink, hide, or
     erase the attribution. Shadow DOM also blocks direct selector
     access from the host page. Combined, these defenses mean a
     customer would have to go out of their way (e.g. JS into the
     open shadowRoot) to remove the footer; CSS alone cannot. */
  grid-row: 3;
  background: var(--tides-footer-bg);

  /* Locked structural properties */
  display: flex !important;
  visibility: visible !important;
  opacity: 1 !important;
  min-height: 30px !important;

  /* Locked text rendering — white with a dark drop-shadow stays
     legible on both dark and light backgrounds; pinned font-size /
     letter-spacing so a customer can't shrink the text into oblivion.
     letter-spacing: normal for the 13px size — the 0.04em that worked at
     10px makes "Powered by" look spaced/gappy at the larger size. */
  color: rgba(255, 255, 255, 0.92) !important;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55) !important;
  font-size: 13px !important;
  letter-spacing: normal !important;

  justify-content: center;
  align-items: center;
  padding: 6px var(--tides-pad);
  border-top: 1px solid rgba(125, 211, 252, 0.16);
  user-select: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* SeaLegsAI logo glyph immediately before the "Powered by" text. Same
   anti-tampering posture as the wordmark below — visibility pinned and
   sized via !important so external CSS can't shrink it to 0 or hide it. */
.sl-tides-footer-logo {
  display: block !important;
  width: 18px !important;
  height: 18px !important;
  margin-right: 6px !important;
  object-fit: contain !important;
  flex-shrink: 0 !important;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55)) !important;
  visibility: visible !important;
  opacity: 1 !important;
}
.sl-tides[data-theme="light"] .sl-tides-footer-logo {
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.45))
          drop-shadow(0 1px 1px rgba(0, 0, 0, 0.25)) !important;
}

/* Brand wordmark inside the footer — colors PINNED to fixed values
   (not derived from CSS vars) so they survive --tides-now or
   --tides-text-* overrides. Both halves keep their signature glow
   so the wordmark reads as a brand mark even if a customer chose a
   bg that clashes with the text colors. */
.sl-tides-footer .sl-brand {
  /* font-weight 700 matches the partner page footers (.page-footer
     a.brand). 600 reads as a lighter, slightly different wordmark
     side-by-side; 700 unifies them. !important kept here so customer
     CSS can't shrink the brand text into oblivion. */
  font-size: 14px !important;
  font-weight: 700 !important;
  letter-spacing: -0.01em !important;
  visibility: visible !important;
  opacity: 1 !important;
}
.sl-tides-footer .sl-brand-sea {
  color: #ffffff !important;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.6),
    0 0 8px rgba(251, 146, 60, 0.55),
    0 0 18px rgba(251, 146, 60, 0.3) !important;
}
.sl-tides-footer .sl-brand-ai {
  color: #fb923c !important;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.6),
    0 0 6px rgba(251, 146, 60, 0.85) !important;
}

/* SeaLegsAI wordmark — white "SeaLegs" with orange glow + orange "AI".
   Plain Inter (not Inter Tight) so the wordmark renders identically on
   the chart widget footer + the parent page footers. Inter Tight reads
   denser/squatter — visible mismatch when both footers are on the same
   page. */
.sl-brand {
  display: inline-flex;
  align-items: baseline;
  font-family: 'Inter', sans-serif;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: -0.01em;
  text-decoration: none;
  border: none !important;
  transition: filter 0.2s ease, transform 0.15s ease;
}

.sl-brand-sea {
  color: #ffffff;
  text-shadow:
    0 0 8px rgba(251, 146, 60, 0.55),
    0 0 18px rgba(251, 146, 60, 0.35),
    0 0 32px rgba(251, 146, 60, 0.18);
}

.sl-brand-ai {
  color: var(--tides-now);
  text-shadow:
    0 0 6px rgba(251, 146, 60, 0.85),
    0 0 14px rgba(251, 146, 60, 0.55);
  margin-left: 1px;
}

.sl-brand:hover {
  filter: brightness(1.1);
  transform: translateY(-1px);
}

/* ---------- Reveal sequence ---------- */

.sl-tides[data-revealing="true"] .sl-tides-stationhead { animation: fade-in-up 0.6s ease 0.0s both; }
.sl-tides[data-revealing="true"] .sl-tides-hero        { animation: fade-in-up 0.6s ease 0.4s both; }
.sl-tides[data-revealing="true"] .sl-tides-daystrip    { animation: fade-in-up 0.7s ease 1.2s both; }
/* Footer fades in (no upward slide) — the visible "slide up" of the
   brand mark on initial load read as a glitch rather than polish. */
.sl-tides[data-revealing="true"] .sl-tides-footer      { animation: fade-in 0.5s ease 1.5s both; }

@keyframes fade-in-up {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ---------- Reduced motion override ---------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Mobile responsive ---------- */

@media (max-width: 720px) {
  /* Tighter horizontal padding inside the chart panel; smaller corner
     radius. Both used by various .sl-tides-* rules above. */
  :root, :host { --tides-pad: 18px; --tides-radius: 18px; }

  /* Hide the verbose tail of the next-extreme readout
     (" — 0.2 ft at 4:46 PM") so the countdown reads at a glance on
     narrow viewports. */
  .sl-tides-hero-next-detail { display: none; }

  /* Daystrip becomes a fixed-width-card horizontal carousel on mobile
     so each card has enough room for the two-column event layout even
     when the panel itself is narrow. The strip's overflow-x: auto
     (set in the desktop rule) handles the resulting horizontal
     scroll; touch-action: pan-x lets iOS keep the gesture native. */
  .sl-tides-daystrip {
    padding: 8px 12px 10px;
    gap: 6px;
    touch-action: pan-x;
    overscroll-behavior-x: contain;
  }
  .sl-tides-daystrip-card {
    flex: 0 0 200px;
    min-width: 0;
    padding: 8px 10px 9px;
  }
  .sl-tides-daystrip-events { column-gap: 8px; }

  /* Note: legacy mobile rules for .sl-tides-hero (grid-template-areas
     with a "pill" row), .sl-tides-hero-value/units/arrow font sizes,
     .sl-tides { overflow-y: auto }, .sl-tides-body { display: block },
     and .sl-tides-body-main { min-height: ... } were removed in the
     full-panel SVG redesign. They targeted elements/layout that no
     longer exist (.sl-tides-hero-now is now the floating badge,
     .sl-tides-body uses position: relative + overflow: hidden, and
     .sl-tides-body-main is `display: contents` with no box). */
}
