/* Color tokens originally sampled from unlinked_assets/robot_logo.jpg
   and social_banner.jpg - the palette stuck even though the banner
   image itself isn't used on the site (it read as generic AI-generated
   stock art; the small circular logo is the only brand image left).
   The glow those images use is deliberately treated as an ACCENT here
   (the hero headline, the primary CTA), not applied everywhere - a
   restrained dark layout with glow used sparingly reads as a real
   product; glow on every card, badge, and hover state reads as
   decoration for its own sake. */
:root {
  --bg: #021631;
  --surface: #0a2443;
  --surface-2: #0f2c49;
  --border: #2d4864;
  --text: #e7eef5;
  --text-muted: #9db3c6;
  --accent: #60b9d3;
  --accent-bright: #81dce6;
  --accent-mint: #6de1e1;
  --warn: #dc8649;
  --white: #ffffff;

  --status-operating: #6de1e1;
  --status-down: #dc8649;
  --status-closed: #6a7f93;

  --glow-soft: rgba(96, 185, 211, 0.22);
  --glow-bright: rgba(129, 220, 230, 0.35);

  /* Type scale - a small, deliberate set of steps rather than ad hoc
     sizes per element, so size jumps down the page look intentional. */
  --fs-xs: 0.78rem;
  --fs-sm: 0.88rem;
  --fs-base: 1rem;
  --fs-md: 1.05rem;
  --fs-lg: 1.25rem;
  --fs-xl: 1.5rem;
  --fs-2xl: 1.875rem;
  --fs-hero: clamp(2rem, 5vw, 2.875rem);
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
}

body {
  /* A faint ambient glow in the corners - present, but subtle enough to
     read as depth rather than decoration. */
  background:
    radial-gradient(ellipse 900px 560px at 12% -12%, rgba(96, 185, 211, 0.09), transparent 60%),
    radial-gradient(ellipse 800px 520px at 108% 8%, rgba(109, 225, 225, 0.06), transparent 60%),
    var(--bg);
  background-attachment: fixed;
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: var(--fs-base);
  line-height: 1.55;
}

a {
  color: var(--accent-bright);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

.wrap {
  max-width: 1040px;
  margin: 0 auto;
  padding-inline: 16px;
}

/* Header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(10, 36, 67, 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.site-header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: 12px;
  flex-wrap: wrap;
  gap: 12px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--accent-mint);
}

.brand:hover {
  text-decoration: none;
}

.brand-logo {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: block;
  box-shadow: 0 0 0 2px var(--surface-2);
}

.site-nav {
  display: flex;
  gap: 20px;
  font-weight: 600;
  font-size: var(--fs-sm);
}

.site-nav a {
  color: var(--text);
}

.site-nav a:hover {
  color: var(--accent-bright);
  text-decoration: none;
}

/* Main content */

main.wrap {
  padding-block: 40px;
  min-height: 60vh;
}

h1, h2, h3 {
  color: var(--accent-mint);
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin-top: 0;
}

h2 {
  font-size: var(--fs-2xl);
}

h3 {
  font-size: var(--fs-lg);
}

.subtitle {
  color: var(--text-muted);
  font-size: var(--fs-md);
}

/* A confidently-sampled "best time to ride" fact, right below the
   heatmap's own subtitle - accent-colored rather than muted since it's
   a specific, actionable recommendation, not just a caption. */
.best-hour-callout {
  color: var(--accent-mint);
  font-weight: 600;
}

/* A plain in-page jump nav for the park/attraction detail pages, which
   have grown enough sections to be worth linking into directly rather
   than always scrolling past everything - a flat row of anchor links,
   not a sticky bar, so it stays in keeping with the rest of the site's
   restrained chrome. */
.section-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  margin-top: 12px;
  font-size: var(--fs-sm);
}

.section-nav .sep {
  color: var(--text-muted);
}

section + section {
  margin-top: 56px;
}

/* Hero (landing page) */

.hero {
  text-align: center;
  padding-block: 20px 8px;
}

.hero h1 {
  font-size: var(--fs-hero);
  font-weight: 800;
  margin-bottom: 12px;
  /* The one place gradient text is used - a single focal accent, not a
     pattern repeated on every heading. */
  background: linear-gradient(120deg, var(--accent-mint), var(--accent-bright) 55%, var(--accent));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero p {
  color: var(--text-muted);
  font-size: var(--fs-md);
  max-width: 620px;
  margin: 0 auto 28px;
}

.cta-row {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

.btn {
  display: inline-block;
  padding: 12px 22px;
  border-radius: 8px;
  font-weight: 700;
  font-size: var(--fs-sm);
  border: 1px solid transparent;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

/* The other accent moment - the primary call to action gets the glow
   treatment; nothing else on the page competes with it for attention. */
.btn-primary {
  background: linear-gradient(135deg, var(--accent), var(--accent-bright));
  color: var(--bg);
  box-shadow: 0 6px 20px var(--glow-soft);
}

.btn-primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 26px var(--glow-bright);
  text-decoration: none;
}

.btn-secondary {
  border-color: var(--border);
  color: var(--text);
}

.btn-secondary:hover {
  border-color: var(--accent);
  color: var(--accent-bright);
  text-decoration: none;
}

/* Stats strip */

.stats-strip {
  display: flex;
  justify-content: center;
  gap: 32px;
  flex-wrap: wrap;
  padding-block: 24px;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.stat-pill {
  text-align: center;
}

.stat-pill strong {
  display: block;
  font-size: var(--fs-xl);
  font-weight: 800;
  color: var(--accent-mint);
}

.stat-pill span {
  display: block;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 2px;
}

/* Feature grid */

.features h2 {
  text-align: center;
  margin-bottom: 24px;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
}

.feature {
  text-align: center;
  padding: 8px;
}

.feature-icon {
  width: 52px;
  height: 52px;
  margin: 0 auto 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--accent);
}

.feature h3 {
  margin-bottom: 6px;
}

.feature p {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  margin: 0;
}

/* Showcase (landing page - live feed callout) */

.showcase {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
  align-items: center;
}

@media (min-width: 720px) {
  .showcase {
    grid-template-columns: 1fr 1fr;
  }
}

.showcase-text .subtitle {
  margin-bottom: 18px;
}

.showcase-board {
  margin-top: 0;
}

/* Cards / grids */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
  margin-top: 20px;
}

.card {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  color: var(--text);
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.card:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
  box-shadow: 0 10px 24px rgba(2, 22, 49, 0.5);
  text-decoration: none;
}

.card h3 {
  margin: 0 0 4px;
  font-size: var(--fs-md);
}

.card .meta {
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

.card .card-stat {
  color: var(--accent-mint);
  font-size: var(--fs-sm);
  font-weight: 700;
  margin-top: 8px;
}

.resort-heading {
  font-size: var(--fs-lg);
  margin-bottom: 12px;
}

/* Attraction board (table-ish list) */

.board {
  margin-top: 20px;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.board-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 6px 12px;
  padding: 13px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  transition: background 0.15s ease;
}

.board-row:hover {
  background: var(--surface-2);
}

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

/* The name (a link on most boards, plain text on the landing page's
   preview) needs to actually shrink and wrap on a long attraction name
   ("Twilight Zone Tower of Terror," say) instead of overflowing the
   row - and the status+wait group on the other side needs to stay
   intact as a unit, wrapping onto its own line as a whole rather than
   splitting the badge from the number, if it doesn't fit alongside a
   long name. */
.board-row > :first-child {
  flex: 1 1 160px;
  min-width: 0;
  overflow-wrap: break-word;
}

.board-row > :last-child {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* Side-by-side most-reliable/least-reliable leaderboard columns -
   stacks to one column on narrow screens via the same wrap the rest
   of the site's flex layouts already use. */
.reliability-columns {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  margin-top: 20px;
}

.reliability-columns > div {
  flex: 1 1 260px;
  min-width: 0;
}

.reliability-columns h3 {
  font-size: var(--fs-md);
  margin-bottom: 4px;
}

.reliability-columns .board {
  margin-top: 8px;
}

.board-row a {
  color: var(--text);
  font-weight: 600;
}

.board-row a:hover {
  color: var(--accent-bright);
}

.wait-value {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  min-width: 64px;
  text-align: right;
}

.status-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.status-operating {
  background: rgba(109, 225, 225, 0.13);
  color: var(--status-operating);
}

.status-operating::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin-right: 6px;
  background: var(--status-operating);
  animation: pulse 1.8s ease-in-out infinite;
}

.status-down {
  background: rgba(220, 134, 73, 0.16);
  color: var(--status-down);
}

.status-closed {
  background: rgba(106, 127, 147, 0.18);
  color: var(--status-closed);
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}

@media (prefers-reduced-motion: reduce) {
  .status-operating::before {
    animation: none;
  }
}

/* Ticketed-event/special-event callout (park detail page) and the
   "this ride is currently down" banner (attraction detail page) - the
   one place on the site color is used to mean "heads up" rather than
   as a brand accent, so it borrows --warn rather than --accent. */

.event-banner,
.status-alert-banner {
  margin-top: 16px;
  padding: 12px 16px;
  background: rgba(220, 134, 73, 0.12);
  border: 1px solid rgba(220, 134, 73, 0.4);
  border-radius: 10px;
  color: var(--text);
}

.event-banner p,
.status-alert-banner p {
  margin: 4px 0;
}

.event-banner p:first-child,
.status-alert-banner p:first-child {
  margin-top: 0;
}

.event-banner p:last-child,
.status-alert-banner p:last-child {
  margin-bottom: 0;
}

/* Stat blocks (attraction detail page) */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-top: 20px;
}

.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 16px;
  /* Grid items default to min-width: auto, which lets long unbroken
     content (the OpenStreetMap link text, in particular) push the box
     wider than its track instead of wrapping inside it. */
  min-width: 0;
}

.stat .label {
  color: var(--text-muted);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.stat .value {
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--accent-mint);
  overflow-wrap: break-word;
}

/* A stat whose value is a link (e.g. "View on OpenStreetMap") reads as
   a giant, awkwardly-wrapping headline at the numeric-stat size above -
   scale it back down to normal link proportions instead. */
.stat .value a {
  font-size: var(--fs-base);
  font-weight: 600;
}

/* A secondary number tacked onto a stat's main value (e.g. "10-60 min
   (avg 32)") - smaller and muted so it reads as supplementary detail,
   not a second headline competing with the main figure. */
.stat .value .stat-detail {
  font-size: var(--fs-sm);
  font-weight: 400;
  color: var(--text-muted);
}

/* Wait-history line chart (attraction detail page) */

.wait-chart-wrap {
  margin-top: 16px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.wait-chart {
  display: block;
  width: 100%;
  height: 160px;
}

.wait-chart-line {
  fill: none;
  stroke: var(--accent-bright);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Bridges the visual gap left by a closure (see build_wait_chart()'s
   docstring) - dashed and muted specifically so it never reads as a
   real data trend the way .wait-chart-line does, just a "no data here"
   connector that keeps the overall shape followable. */
.wait-chart-gap {
  fill: none;
  stroke: var(--border);
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
  stroke-linecap: round;
}

/* A single real reading stranded between two closures - too few points
   for .wait-chart-line to draw, shown as a dot instead of vanishing. */
.wait-chart-point {
  fill: var(--accent-bright);
}

/* Shared y-axis-label + chart layout, used by both the wait-history
   line chart above and the hour-of-day outage bar chart below - a
   fixed-width label column beside the chart itself, with the
   corresponding x-axis labels (.hour-labels.chart-xaxis-offset)
   indented to line up under the chart rather than the label column. */

.chart-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin-top: 20px;
}

.wait-chart-wrap .chart-row {
  /* .wait-chart-wrap already supplies its own top margin/padding. */
  margin-top: 0;
}

.chart-yaxis {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  flex-shrink: 0;
  width: 44px;
  padding-block: 6px;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  text-align: right;
  white-space: nowrap;
}

.chart-gridline {
  stroke: var(--border);
  stroke-width: 1;
}

.chart-xaxis-offset {
  margin-left: 52px;
}

/* Day/hour wait heatmap (attraction detail + park detail pages) */

.heatmap-wrap {
  margin-top: 16px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow-x: auto;
}

.heatmap-inner {
  min-width: 480px;
}

.heatmap-row {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-bottom: 2px;
}

.heatmap-row:last-child {
  margin-bottom: 0;
}

.heatmap-day-label {
  width: 30px;
  flex-shrink: 0;
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.heatmap-cell {
  flex: 1;
  min-width: 10px;
  aspect-ratio: 1;
  border-radius: 2px;
  background: var(--surface-2);
}

.heatmap-cell-empty {
  opacity: 0.4;
}

.heatmap-hour-labels {
  margin-left: 32px;
}

.heatmap-legend {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 10px;
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.heatmap-legend-gradient {
  width: 60px;
  height: 10px;
  border-radius: 5px;
  background: linear-gradient(90deg, rgba(220, 134, 73, 0.12), rgba(220, 134, 73, 1));
}

/* Hour-of-day outage chart (attraction detail page) */

.hour-chart {
  display: flex;
  align-items: flex-end;
  flex: 1 1 auto;
  min-width: 0;
  gap: 3px;
  height: 100px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.hour-bar {
  flex: 1;
  height: 100%;
  display: flex;
  align-items: flex-end;
}

.hour-bar-fill {
  width: 100%;
  min-height: 2px;
  background: var(--accent);
  border-radius: 2px 2px 0 0;
}

.hour-labels {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  padding-inline: 12px;
  color: var(--text-muted);
  font-size: var(--fs-xs);
}

/* Feed */

.feed-list {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.feed-post {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 16px;
}

.feed-post .meta {
  color: var(--text-muted);
  font-size: var(--fs-xs);
  margin-top: 8px;
}

.empty-state {
  color: var(--text-muted);
  padding: 24px 0;
}

/* Footer */

.site-footer {
  background: var(--surface-2);
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  padding-block: 20px;
  margin-top: 56px;
}

.site-footer a {
  color: var(--text-muted);
  text-decoration: underline;
}

/* Cookie banner */

.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(15, 44, 73, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid var(--border);
  z-index: 50;
}

.cookie-banner-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-block: 12px;
  flex-wrap: wrap;
  font-size: var(--fs-sm);
}

.cookie-banner button {
  background: var(--accent);
  color: var(--bg);
  border: none;
  border-radius: 6px;
  padding: 8px 16px;
  font-weight: 700;
  font-size: var(--fs-sm);
  cursor: pointer;
}

/* Small screens */

@media (max-width: 480px) {
  .board-row {
    flex-wrap: wrap;
  }
}
