:root {
  --navy: #12252d;
  --navy-deep: #0c1a20;
  --orange: #ff6614;
  --green: #08d100;
  --red: #ff1744;
  --muted: #989b9f;
  --bg-light: #f5f6f8;
}

body,
html {
  font-family: "Titillium Web", Arial, sans-serif;
  background: #fff;
  color: #25282b;
  margin: 0;
  padding: 0;
  height: 100%;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* ============ Shell layout ============ */

.app-shell {
  display: flex;
  flex-direction: row;
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
}

/* ============ Sidebar ============ */

.sidebar {
  width: 560px;
  min-width: 340px;
  flex: 0 0 auto;
  height: 100vh;
  position: relative;
  background-color: var(--navy);
  color: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px 0 32px;
  overflow: hidden;
}

.sidebar-bg {
  position: absolute;
  inset: 0;
  background: url("../img/coastline.svg") center bottom/cover no-repeat;
  opacity: 0.35;
  z-index: 0;
}

.sidebar-header {
  position: relative;
  z-index: 2;
  width: 100%;
  /* Grid (not flex space-between) so .site-title sits in a true centre
     column - space-between only centres it visually when the two side
     items happen to be equal width, which temp-badge and live-indicator
     aren't. */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 20px;
}

.sidebar-header .temp-badge {
  justify-self: start;
}

.sidebar-header .site-title {
  justify-self: center;
}

.sidebar-header .live-indicator {
  justify-self: end;
}

.temp-badge {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--orange);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.weather-icon {
  display: flex;
  align-items: center;
}

.weather-icon svg {
  width: 20px;
  height: 20px;
  display: block;
}

.temp-badge .unit {
  font-size: 0.85rem;
  font-weight: 400;
  margin-left: 2px;
  opacity: 0.8;
}

.site-title {
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: #fff;
}

.live-indicator {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

.live-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 0 rgba(8, 209, 0, 0.6);
  animation: live-pulse 2s infinite;
}

.live-indicator.stale .live-dot {
  background: var(--red);
  animation: none;
  box-shadow: none;
}

.live-indicator.stale .live-label {
  color: var(--red);
}

@keyframes live-pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(8, 209, 0, 0.55);
  }
  70% {
    box-shadow: 0 0 0 8px rgba(8, 209, 0, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(8, 209, 0, 0);
  }
}

.wind-rose-wrap {
  /* Deliberately NOT position:relative - #wind-rose-svg's absolute "top" needs
     to resolve against .sidebar (the nearest positioned ancestor) so it scales
     proportionally with the coastline background image (which is sized
     against the full sidebar) instead of against this flex slot's own
     variable height. That's what kept it "floating" out of alignment on resize. */
  z-index: 1;
  flex: 1 1 auto;
  width: 100%;
}

#wind-rose-svg {
  position: absolute;
  /* The background image is cover-scaled by .sidebar's height, so a native
     point in it always sits at the same FRACTION of .sidebar's height,
     regardless of window size. But this element itself has a half-height
     that does NOT scale with .sidebar's height (it's sized off WIDTH: 100%
     up to max-width 440px) - so positioning by a plain "top: X%" (which
     places the TOP EDGE, not the centre) made the centre's own
     fraction-of-height drift as the window resized. calc() cancels that
     out: solving centre/height = F for the top edge gives top = F% - half,
     which keeps the centre pinned to the same fraction of .sidebar's
     height (and therefore the same point in the background art).
     "half" itself has to mirror how this element's own size is computed
     (min(95%, 440px) wide, square, /2) - min(47.5vw, 220px) does that: on
     desktop .sidebar is a fixed 560px (ring capped at 440 -> half 220px,
     and 47.5vw is always bigger there so min() correctly picks 220px); in
     the narrow layout .sidebar is ~100vw (ring uncapped below ~464px
     wide), so min() correctly switches to tracking 47.5vw instead. Without
     this, the compass sat a bit high specifically on phones. */
  top: calc(49.7% - min(47.5vw, 220px));
  left: 50%;
  transform: translateX(-50%);
  /* 95% (not 100%) so the ring/compass still has a consistent margin on
     every side - the arrow needle overshoots the ring's own radius by a
     small but real amount when pointing east/west/north/south, and a ring
     that exactly filled its container left zero room for that overshoot,
     clipping the arrow tip against the sidebar edge in whichever direction
     it pointed. (The overshoot itself is now also fixed at the SVG level
     via the viewBox margin - see #wind-rose-svg's viewBox attribute - this
     container margin is a second, independent safety margin.) */
  width: 95%;
  max-width: 440px;
  height: auto;
  display: block;
}

.wind-rose-accent {
  stroke: #c3c8cc;
  fill: #c3c8cc;
}

#wind-arrow .wind-rose-accent {
  stroke: #3c9a4a;
  fill: #3c9a4a;
}

#wind-direction {
  fill: #c3c8cc;
  stroke: none;
}

/* Wind speed / Beaufort gauge */

#wind-speed-bar-fill {
  transition: width 0.6s ease, fill 0.6s ease;
}

#wind-gust-marker {
  transition: width 0.6s ease;
}

#wind-speed-bar {
  position: relative;
  z-index: 1;
  width: min(100%, 460px);
  padding: 0 20px;
}

.beaufort-boxes rect {
  fill: rgba(255, 255, 255, 0.07);
  stroke: rgba(255, 255, 255, 0.3);
  stroke-width: 1;
}

.beaufort-labels {
  fill: rgba(255, 255, 255, 0.55);
  font-size: 11px;
  font-family: "Titillium Web", Arial, sans-serif;
  font-weight: 600;
}

.beaufort-unit {
  fill: rgba(255, 255, 255, 0.4);
  font-size: 10px;
}

.ws-ticks {
  stroke: #b9c6d6;
  opacity: 0.72;
}

.ws-labels {
  fill: #e7ecf5;
  font-size: 14px;
  font-family: "Titillium Web", Arial, sans-serif;
  font-weight: 600;
  opacity: 0.9;
}

.ws-unit {
  opacity: 0.7;
}

/* ============ Main content ============ */

.main-content {
  flex: 1 1 0;
  height: 100vh;
  overflow-y: auto;
  padding: 16px;
  background: var(--bg-light);
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: center;
}

.main-content > .block {
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
}

.block {
  background: #fff;
  border: 1px solid rgba(37, 40, 43, 0.08);
  box-shadow: 0 10px 30px rgba(18, 38, 63, 0.08);
  border-radius: 4px;
  padding: 16px 18px;
  color: #1f252f;
}

.block h2 {
  margin: 0 0 12px 0;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: #0f172a;
}

/* Webcam */

.webcam-frame {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%;
  height: 0;
  overflow: hidden;
  border-radius: 4px;
}

.webcam-frame iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Graphs */

.graphs-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 12px;
}

.graphs-header h2 {
  margin: 0;
}

.range-tabs {
  display: flex;
  gap: 4px;
  background: var(--bg-light);
  border-radius: 4px;
  padding: 4px;
}

.range-tab {
  border: none;
  background: transparent;
  padding: 6px 14px;
  border-radius: 3px;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.85rem;
  color: #334155;
  cursor: pointer;
  transition: all 0.15s ease;
}

.range-tab:hover {
  background: rgba(37, 40, 43, 0.06);
}

.range-tab.active {
  background: var(--navy);
  color: #fff;
}

#graphs {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}

.graph-card {
  border: 1px solid rgba(37, 40, 43, 0.08);
  border-radius: 4px;
  padding: 8px 8px 2px;
  background: #fbfcfe;
}

.graph-title {
  display: block;
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.01em;
  color: #334155;
  margin-bottom: 4px;
}

.chart {
  width: 100%;
  min-height: 260px;
}

/* Data grid */

.data-grid {
  display: grid;
  width: 100%;
  max-width: 1080px;
  /* 240px (not 280px) so 3 boxes fit per row at this section's typical
     widths - at 280px the 3rd box (Sun) had just enough combined min-width
     + gaps to overflow, so auto-fit dropped to 2 columns and stranded it
     alone on its own row. */
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px;
  margin: 0 auto;
}

.data-block p {
  margin: 6px 0;
  font-size: 0.95rem;
  color: #334155;
}

.sun-block {
  display: flex;
  flex-direction: column;
}

.sun-rows {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 48px;
}

.sun-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  font-size: 1.3rem;
  margin: 0;
}

.sun-icon {
  display: flex;
  align-items: center;
  color: var(--orange);
}

.sun-icon svg {
  width: 52px;
  height: 52px;
  display: block;
}

.tide-graphic {
  width: 100%;
  margin: 4px 0 2px;
}

.tide-graphic svg {
  width: 100%;
  height: auto;
  display: block;
}

/* Sponsors */

.sponsors-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}

.sponsor-banner {
  display: block;
  border-radius: 4px;
  overflow: hidden;
  border: 1px solid rgba(37, 40, 43, 0.08);
  line-height: 0;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.sponsor-banner:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(18, 38, 63, 0.12);
}

.sponsor-banner img {
  width: 100%;
  height: auto;
  display: block;
}

/* Responsive */

@media (max-width: 900px) {
  .app-shell {
    flex-direction: column;
    height: auto;
    min-height: 100vh;
  }

  .sidebar {
    width: 100%;
    /* Explicit (not auto) so #wind-rose-svg's percentage-based "top" has a
       real height to resolve against - percentages on an absolutely
       positioned child are meaningless against an auto-height containing
       block, which is what made the compass render clipped near the top
       at narrow widths regardless of "top" value. */
    height: 660px;
    padding-bottom: 24px;
  }

  .main-content {
    height: auto;
    overflow-y: visible;
    padding: 8px;
    gap: 10px;
  }

  /* Blocks and graph cards have their own padding on top of
     .main-content's, which on a narrow phone viewport adds up to a lot of
     unused margin on either side of the actual chart - trim both down
     just on mobile so the chart plot gets more real width. */
  .block {
    padding: 12px 10px;
  }

  #graphs {
    grid-template-columns: 1fr;
  }

  .graph-card {
    padding: 6px 4px 2px;
  }

  /* Sea (first box) spans the full row; Weather and Sun share the row below. */
  .data-grid {
    grid-template-columns: 1fr 1fr;
  }

  .data-grid > .data-block:first-child {
    grid-column: 1 / -1;
  }

  /* Sea spanning the full row (above) makes this width:100% container much
     wider than on desktop, which blew up the tide graphic along with it -
     capping it keeps the same visual size/proportions as desktop. */
  .tide-graphic {
    max-width: 300px;
    margin-left: auto;
    margin-right: auto;
  }

  /* Side-by-side left the narrower Weather/Sun column mostly empty above
     two small floating icons - stacked, Sunrise/Sunset fill the box height
     the same way Weather's list of rows does. */
  .sun-rows {
    flex-direction: column;
    gap: 20px;
  }
}
