/* ==========================================================================
   BiteWindow - public pages (landing, forecast, about).

   Extends base.css. It never redefines a base token; everything below either
   uses one or adds a NEW custom property.

   Mobile first, without exception. Every rule here is the phone rule and the
   only media queries are min-width. Wide content lives in .rail / .table-scroll
   so the body itself never scrolls sideways.

   Design notes
   ------------
   Voice: a tide table, not a dashboard. Three type roles, all from local font
   stacks so there is no webfont request on a phone on 4G:
     - var(--font-display)  old-style serif, for prose and the verdict
     - var(--font-cond)     narrow grotesque, for the label layer
     - var(--font-mono)     tabular figures, for every number
   Signature: the lit-hour ruler and the week ribbon - the same hourly data at
   two scales, drawn from measurements the pipeline already made.
   ========================================================================== */

/* ------------------------------------------------- added tokens (new) --- */
:root {
  /* Narrow grotesque, present on Android / macOS / Windows respectively.
     Falls back to the base sans, which is never wrong, only less characterful. */
  --font-cond: "Roboto Condensed", "Arial Narrow", "Liberation Sans Narrow",
               "Helvetica Neue", var(--font-sans);

  /* Inset surface for charts and data plates. */
  --plate: #F1F4F0;
  --plate-line: #D5DDD6;
  --day-band: rgba(166, 75, 10, 0.09);
  --ribbon-area: rgba(14, 107, 49, 0.09);

  /* ChartBars carry their fill as an SVG attribute, so payload-coloured marks
     are modulated rather than restyled. */
  --bar-lift: none;
  --idle-alpha: 0.5;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --plate: #101B16;
    --plate-line: #26332C;
    --day-band: rgba(224, 154, 78, 0.10);
    --ribbon-area: rgba(95, 190, 127, 0.10);
    --bar-lift: brightness(1.5) saturate(1.1);
    --idle-alpha: 0.34;
  }
}
:root[data-theme="dark"] {
  --plate: #101B16;
  --plate-line: #26332C;
  --day-band: rgba(224, 154, 78, 0.10);
  --ribbon-area: rgba(95, 190, 127, 0.10);
  --bar-lift: brightness(1.5) saturate(1.1);
  --idle-alpha: 0.34;
}

/* --------------------------------------------------- the rating accent --- */
/* A `.rated` element carries all four palette values inline (see rateVars() in
   routes/pages.js); this is the only place that decides which pair is live.
   The values themselves are the pipeline's $Palette verbatim - green prime,
   ORANGE worth a trip, red poor - so a day looks the same in the mail and here.
   Orange is not a warning colour in this system. Do not retune these. */
.rated {
  --rate: var(--ink-3);
  --rate-dark: var(--ink-3);
  --rate-tint: var(--tint);
  --rate-tint-dark: var(--tint);
  --rate-ink: var(--rate);
  --rate-wash: var(--rate-tint);
}
@media (prefers-color-scheme: dark) {
  /* The light accents fall below 4.5:1 on the dark ground. */
  :root:not([data-theme="light"]) .rated {
    --rate-ink: var(--rate-dark);
    --rate-wash: var(--rate-tint-dark);
  }
}
:root[data-theme="dark"] .rated {
  --rate-ink: var(--rate-dark);
  --rate-wash: var(--rate-tint-dark);
}

/* ------------------------------------------------------- page rhythm --- */
/* One rule owns the vertical gap between top-level blocks. Nothing else sets a
   margin-top on these, which is how two rules end up cancelling each other. */
.board, .sell, .alt,
.archived, .mast, .answer, .safety, .ribbon, .strip, .setup, .days, .tail,
.doc, .empty--page {
  margin-block: var(--sp-6) 0;
}
@media (min-width: 48rem) {
  .board, .sell, .alt,
  .archived, .mast, .answer, .safety, .ribbon, .strip, .setup, .days, .tail,
  .doc, .empty--page { margin-block: var(--sp-7) 0; }
}

.eyebrow-c {
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ==========================================================  spot tabs === */
.spots {
  border-bottom: 1px solid var(--line);
  background: var(--card-2);
  margin-block: calc(var(--sp-5) * -1) 0; /* sit tight under the sticky header */
  padding-block: var(--sp-2);
  position: sticky;
  top: 57px;               /* just below .site-head on a phone */
  z-index: 30;
}
@media (min-width: 48rem) { .spots { top: 67px; } }

.spots__rail { gap: var(--sp-1); padding-bottom: 0; }

.spot {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--sp-3);
  border-radius: var(--radius-s);
  border: 1px solid transparent;
  text-decoration: none;
  color: var(--ink-2);
  white-space: nowrap;
  font-family: var(--font-cond);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.spot:hover { background: var(--tint); color: var(--ink); }
.spot.is-here {
  background: var(--deep);
  border-color: var(--deep);
  color: #fff;
}
.spot.is-here:hover { color: #fff; }

/* =========================================================== masthead === */
.mast__eyebrow {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--amber);
}
.mast__h {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-cond);
  font-size: clamp(2.1rem, 1.2rem + 4.6vw, 4rem);
  font-weight: 700;
  line-height: 0.98;
  letter-spacing: -0.005em;
  text-transform: uppercase;
}
.mast--doc .mast__h { text-transform: none; font-family: var(--font-display); letter-spacing: -0.02em; }

.mast__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  margin: 0 0 var(--sp-3);
  font-size: var(--step--1);
}
.mast__geo { min-height: var(--tap); display: inline-flex; align-items: center; }
.mast__temp { color: var(--ink-2); font-weight: 700; }
.mast__src {
  font-family: var(--font-cond);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
  color: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 9px;
}
.mast__station { margin: 0; max-width: 60ch; }

/* ============================================================= answer === */
.answer__line {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 1.34;
  letter-spacing: -0.01em;
  max-width: 40ch;
}

/* The best-day callout: a plate ruled in the rating colour, with the number set
   large in mono. */
.pick {
  display: grid;
  gap: var(--sp-1) var(--sp-3);
  margin-top: var(--sp-4);
  padding: var(--sp-4);
  border: 1px solid var(--line);
  border-left: 5px solid var(--rate-ink);
  border-radius: var(--radius);
  background: var(--rate-wash);
  text-decoration: none;
  color: var(--ink);
  box-shadow: var(--shadow-1);
}
.pick:hover {
  color: var(--ink);
  background: color-mix(in srgb, var(--rate-ink) 12%, var(--rate-wash));
}

.pick { grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; }
.pick__k {
  grid-column: 1 / -1;
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--rate-ink);
}
.pick__day {
  font-family: var(--font-cond);
  font-size: var(--step-2);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1;
}
.pick__score {
  grid-row: 2;
  grid-column: 2;
  text-align: right;
  font-size: var(--step-3);
  font-weight: 700;
  line-height: 1;
  color: var(--rate-ink);
}
.pick__date { grid-column: 1; font-size: var(--step--1); color: var(--ink-3); }
.pick__rate {
  grid-column: 1 / -1;
  font-family: var(--font-cond);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--rate-ink);
}
.pick__win {
  grid-column: 1 / -1;
  font-size: var(--step-1);
  font-weight: 700;
}

/* ================================================== landing: the hero === */
/*
   Night water with the bite window cut into it.

   The panel is dark in BOTH themes on purpose - this page is read at 5:40 AM in
   a truck, and a full-width white slab at that hour is the wrong first thing.
   That means its colours cannot read through the site tokens, which flip; they
   are local to this block and every pairing below is checked against the fixed
   dark ground rather than against --paper.

   The lit band is the signature. Its left and right edges come from the day's
   actual window hours (buildHeroArt() in routes/pages.js) mapped through the
   same x-scale as the tide line, so the light falls on the water where the
   window falls on the day. It is measurement, not decoration - if the window
   cannot be parsed, no band is drawn rather than one placed by eye.

   One slide per spot, all stacked in a single grid cell so the panel is as tall
   as its tallest slide and nothing jumps as they cross-fade. Only .is-current is
   visible; the server marks the first slide, so the panel is a working static
   hero before hero.js runs at all.
*/
.hero {
  --h-night: #05130D;   /* water before sunrise */
  --h-deep:  #0B3A24;
  --h-line:  #74D3A4;   /* the tide stroke */
  --h-dawn:  #F3C673;   /* first light - the only warm thing on the panel */
  --h-ink:   #EDF4EE;
  --h-dim:   #9BB4A6;   /* 5.3:1 on --h-deep */

  /* On a phone the water is a ribbon BELOW the copy, not behind it: there is no
     horizontal room to keep a sweeping curve off the words, and a tide line
     crossing a sentence is just noise. The bottom padding reserves exactly the
     ribbon's height, so the two never meet. The wide layout has the room and
     puts the copy on the water properly. */
  --h-water: clamp(96px, 24vw, 150px);
  --h-hours: 1.5rem;   /* clear row under the ribbon for the hour marks */

  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* Full bleed, and up under the sticky header: .site-main's top padding is
     exactly --sp-5, so this cancels it rather than guessing at a value. */
  margin-block: calc(var(--sp-5) * -1) 0;
  /* The bottom padding belongs to the slide, which is what reserves room for
     its own water; the panel only owns the space above the stack. */
  padding-block: var(--sp-6) 0;
  /* On the dark theme the page ground is nearly the panel's own night, so
     without this the panel has no bottom edge and the board floats. */
  border-bottom: 1px solid rgba(237, 244, 238, 0.09);
  background:
    radial-gradient(120% 90% at 12% -10%, #114A2C 0%, transparent 62%),
    linear-gradient(180deg, var(--h-deep) 0%, var(--h-night) 100%);
  color: var(--h-ink);
}

/* ---------------------------------------------------------- the coast --- */
/*
   NOAA CUSP shoreline, reduced to one file by scripts/coastline-to-svg.js.

   Hidden below 62rem and the background-image declared only inside that query,
   so a phone never downloads the artwork - a background in a rule that does not
   match is not fetched. A narrow screen has no room for a map beside the copy
   anyway, and the tide ribbon is already doing the work down there.

   The box carries the artwork's own aspect ratio and stretches the image to
   fill it exactly, which is what lets the stars be placed by percentage and
   land on the right water. Do not switch this to cover or contain.
*/
.hero__map { display: none; }

@media (min-width: 62rem) {
  .hero__map {
    display: block;
    position: absolute;
    z-index: 0;
    top: -14%;
    right: -3%;
    width: 47%;
    aspect-ratio: 1000 / 826;
    pointer-events: none;
  }
  /* The wash is a pseudo-element, not opacity on the box: opacity on the box
     dims its children, and the stars are children. They have to stay bright -
     they are the part that carries meaning. */
  .hero__map::before {
    content: '';
    position: absolute;
    inset: 0;
    background: url('/static/img/coast.svg') center / 100% 100% no-repeat;
    /* Enough to read as land under the panel, not enough to compete with the
       tide line - which is the drawing that actually answers the question. */
    opacity: 0.3;
    /* Fades towards the copy so the shoreline never runs behind the headline.
       On the box it would fade the stars too, and Matagorda sits far enough
       west to be masked out entirely. */
    mask-image: linear-gradient(100deg, transparent 4%, #000 40%);
  }
}

.hero__star {
  position: absolute;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: var(--h-line);
  opacity: 0.55;
  transition: opacity 0.4s ease, box-shadow 0.4s ease, background 0.4s ease;
}
/* The spot the panel is showing. This is the whole reason the map is worth its
   bytes: it says where the place you are reading about actually is. */
.hero__star.is-here {
  background: var(--h-dawn);
  opacity: 1;
  box-shadow: 0 0 0 3px rgba(243, 198, 115, 0.25), 0 0 12px 3px rgba(243, 198, 115, 0.5);
}

/* Every slide in the same cell: the stack is as tall as the tallest spot, so
   moving between them never resizes the panel. */
.hero__stack { display: grid; }
.hero__slide {
  grid-area: 1 / 1;
  position: relative;
  padding-bottom: calc(var(--h-water) + var(--h-hours) + var(--sp-3));
  opacity: 0;
  visibility: hidden;
  /* visibility flips only after the fade, so an outgoing slide stays readable
     while it goes and is out of the tab order the moment it is gone. */
  transition: opacity 0.55s ease, visibility 0s linear 0.55s;
}
.hero__slide.is-current {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.55s ease, visibility 0s linear 0s;
}
/* base.css zeroes transition DURATION under reduce but not the delay, which
   would leave the outgoing slide sitting there for half a second. */
@media (prefers-reduced-motion: reduce) {
  .hero__slide { transition-delay: 0s !important; }
}

.hero__water {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  width: 100%;
  /* base.css sets svg height:auto; the panel governs it here. The box runs to
     the floor and carries the hour marks inside its own lower margin - lifting
     it off the floor instead left a hard seam where the water wash stopped. */
  height: calc(var(--h-water) + var(--h-hours));
}
/* Scrim. The copy never sits over the water, so this is only settling the top
   of the gradient rather than rescuing contrast. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg,
    rgba(5, 19, 13, 0.55) 0%, rgba(5, 19, 13, 0.2) 60%, rgba(5, 19, 13, 0) 100%);
}

.hero__fill { fill: rgba(116, 211, 164, 0.11); }
.hero__line {
  fill: none;
  stroke: var(--h-line);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 7px rgba(116, 211, 164, 0.45));
}

/* The window, lit on the water. It occupies exactly the water's box - never the
   copy's - so it can be as bright as it needs to be without fighting anything.
   Stacked above the scrim, below the copy. */
.hero__light {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 0;
  width: 100%;
  height: calc(var(--h-water) + var(--h-hours));
  pointer-events: none;
  /* Screen, not alpha: amber laid over dark green with plain opacity goes
     olive, which reads as a stain. Blended this way it adds light. */
  mix-blend-mode: screen;
  /* Light falls from above and dies as it goes down into the water. Without
     this the band is a flat rectangle and reads as a UI selection. */
  mask-image: linear-gradient(180deg,
    transparent 0%, #000 14%, rgba(0, 0, 0, 0.5) 62%, rgba(0, 0, 0, 0.06) 100%);
}
/* Near-white, not amber: a saturated amber screened over dark green comes back
   olive. Light is warm but it is mostly light. */
.hero__band { fill: rgba(255, 238, 202, 0.24); }
.hero__edge { stroke: rgba(255, 226, 160, 0.6); stroke-width: 1; stroke-dasharray: 3 5; }

/* A zero-height rail pinned above the panel floor; each mark hangs its own
   bottom edge on it, so nothing is clipped by the panel's overflow. */
.hero__hours { position: absolute; left: 0; right: 0; bottom: var(--sp-3); height: 0; margin: 0; padding: 0; list-style: none; }
.hero__hour {
  position: absolute;
  bottom: 0;
  transform: translateX(-50%);
  font-size: var(--step--1);
  line-height: 1;
  color: rgba(155, 180, 166, 0.85);
}

.hero__inner { position: relative; z-index: 1; }

/* ---- panel chrome: what the page is, and which spot you are looking at ---- */
.hero__head { position: relative; z-index: 1; margin-bottom: var(--sp-4); }
.hero__kicker {
  margin: 0 0 var(--sp-2);
  font-size: var(--step--1);
  color: var(--h-dim);
}
.hero__lede, .hero__say {
  max-width: 46ch;
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: rgba(237, 244, 238, 0.84);
}
.hero__say { margin-bottom: var(--sp-5); }

/* The spot list is the position indicator as well as the control - six named
   places read better than six dots, and it is the idiom the forecast page's
   spot tabs already use. Wraps rather than scrolls: a control set you might
   have to hunt sideways for is worse than one on two lines. */
/* nowrap: the rail shrinks and scrolls instead of pushing the control onto a
   line of its own, which on a phone cost more height than it was worth. */
.hero__nav {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}
/* An author display beats the UA's [hidden] rule, so it has to be said here. */
.hero__nav[hidden] { display: none; }
/* One line that scrolls, not three that wrap: six spot names wrapped took more
   vertical room on a phone than the slide they were introducing. */
.hero__tabs {
  position: relative;   /* the offsetParent the travelling highlight measures against */
  display: flex;
  gap: var(--sp-2);
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  padding-bottom: 2px;
}
.hero__tabs::-webkit-scrollbar { height: 4px; }
.hero__tabs::-webkit-scrollbar-thumb { background: rgba(237, 244, 238, 0.2); border-radius: 2px; }
/* One pill that slides between chips. Absolutely positioned inside the scroll
   box, so it is part of the scrollable content and tracks the rail on a phone
   as well as travelling on a wide screen. Sized and placed by hero.js; it stays
   at zero width until then, which is why the nav ships hidden. */
.hero__ink {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 100%;
  border-radius: 999px;
  background: var(--h-ink);
  pointer-events: none;
}
/* Transitions are switched on only after the first placement, or the pill would
   fly in from the left edge on load. */
.hero__tabs.is-live .hero__ink {
  transition: transform 0.38s cubic-bezier(0.4, 0, 0.2, 1),
              width 0.38s cubic-bezier(0.4, 0, 0.2, 1);
}

.hero__tab {
  position: relative;   /* above the pill */
  z-index: 1;
  display: inline-flex;
  align-items: center;
  flex: none;
  scroll-snap-align: start;
  min-height: var(--tap);
  padding: 0 var(--sp-3);
  border: 1px solid rgba(237, 244, 238, 0.16);
  border-radius: 999px;
  background: rgba(237, 244, 238, 0.05);
  color: var(--h-dim);
  font: inherit;
  font-family: var(--font-cond);
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.hero__tab:hover { background: rgba(237, 244, 238, 0.13); color: var(--h-ink); }
/* The pill behind it supplies the fill, so the chip only flips its ink. */
.hero__tab[aria-current="true"] {
  background: transparent;
  border-color: transparent;
  color: #0A1A12;
}
.hero__tab[aria-current="true"]:hover { background: transparent; color: #0A1A12; }
/* Icon-sized, so it rides on the same line as the tab rail at every width
   instead of taking a line of its own on a phone. */
.hero__pause {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: var(--tap);
  height: var(--tap);
  padding: 0;
  border: 1px solid rgba(237, 244, 238, 0.24);
  border-radius: 999px;
  background: none;
  color: var(--h-dim);
  cursor: pointer;
}
.hero__pause:hover { color: var(--h-ink); border-color: rgba(237, 244, 238, 0.45); }
.hero__spot {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-cond);
  font-size: clamp(2.2rem, 1.2rem + 5vw, 4.2rem);
  font-weight: 700;
  line-height: 0.94;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  color: var(--h-ink);
}

/* Day, date, verdict, score, clarity. Spacing separates them; there is no
   middot chain, because five items joined that way stop being readable. */
.hero__when {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  margin: 0 0 var(--sp-5);
  font-family: var(--font-cond);
  font-size: var(--step-1);
  font-weight: 600;
}
.hero__date { font-size: var(--step-0); font-weight: 400; color: var(--h-dim); }
.hero__rate { font-weight: 700; }
.hero__score { font-family: var(--font-mono); font-weight: 700; }
.hero__score i { font-style: normal; font-size: var(--step--1); font-weight: 400; color: var(--h-dim); }
.hero__clarity { display: inline-flex; align-items: center; gap: var(--sp-2); font-weight: 500; color: var(--h-ink); }
.hero__sw { width: 13px; height: 13px; border-radius: 3px; flex: none; border: 1px solid rgba(255, 255, 255, 0.25); }

/* The window, lit the same way the band on the water is. Ruled top and bottom
   rather than boxed, so it reads as a band of light and not another card. */
.hero__win {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  margin: 0 0 var(--sp-5);
  padding: var(--sp-3) var(--sp-5) var(--sp-3) var(--sp-4);
  border-top: 1px solid rgba(243, 198, 115, 0.45);
  border-bottom: 1px solid rgba(243, 198, 115, 0.45);
  background: linear-gradient(180deg, rgba(243, 198, 115, 0.17), rgba(243, 198, 115, 0.03));
}
.hero__wink { font-family: var(--font-cond); font-size: var(--step--1); font-weight: 600; color: var(--h-dim); }
.hero__winv {
  font-family: var(--font-mono);
  font-size: clamp(1.5rem, 1rem + 2.4vw, 2.3rem);
  font-weight: 700;
  line-height: 1.05;
  color: var(--h-dawn);
}

/* The site buttons are keyed to --deep, which is dark green on a light theme
   and unreadable here. These are the same shape with the panel's own values. */
.hero__go { display: grid; gap: var(--sp-3); margin: 0; }
.hero__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  padding: 0 var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--radius-s);
  background: var(--h-dawn);
  color: #0A1A12;
  font-weight: 700;
  text-decoration: none;
  transition: background 0.15s ease, transform 0.06s ease;
}
.hero__btn:hover { background: #FFDA92; color: #0A1A12; }
.hero__btn:active { transform: translateY(1px); }
.hero__btn--quiet { background: transparent; color: var(--h-ink); border-color: rgba(237, 244, 238, 0.32); }
.hero__btn--quiet:hover { background: rgba(237, 244, 238, 0.1); color: var(--h-ink); }
.hero :focus-visible { outline: 3px solid var(--h-dawn); outline-offset: 3px; }

@media (min-width: 34rem) {
  .hero__go { display: flex; flex-wrap: wrap; }
}
@media (min-width: 62rem) {
  .hero { --h-water: 160px; }
  .hero__lede, .hero__say { font-size: var(--step-2); }
}

/* One moment on the page: the tide draws in, then the window lights. It runs on
   the lead slide only - a redraw on every rotation would turn one opening into
   motion every seven seconds, and the fade is the transition the rest of the
   time. pathLength normalises the dash maths so the draw reads the same at any
   panel width. */
@media (prefers-reduced-motion: no-preference) {
  .hero__slide:first-child .hero__line {
    stroke-dasharray: 1000;
    stroke-dashoffset: 1000;
    animation: hero-draw 1.4s cubic-bezier(0.32, 0.9, 0.38, 1) 0.1s forwards;
  }
  .hero__slide:first-child .hero__fill { opacity: 0; animation: hero-lift 1s ease 0.8s forwards; }
  .hero__slide:first-child .hero__band,
  .hero__slide:first-child .hero__edge { opacity: 0; animation: hero-lift 0.8s ease 1.2s forwards; }
}
@keyframes hero-draw { to { stroke-dashoffset: 0; } }
@keyframes hero-lift { to { opacity: 1; } }

/* -------------------------------------------------------- scoreboard --- */
.board__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
  padding-bottom: var(--sp-2);
  border-bottom: 2px solid var(--ink);
}
.board__h {
  margin: 0;
  font-family: var(--font-cond);
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.board__note { margin: 0; }

.board__list { list-style: none; margin: 0; padding: 0; }
.board__row { padding: var(--sp-4) 0; border-bottom: 1px solid var(--line); }

.board__spot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: var(--tap);
  text-decoration: none;
  color: var(--ink);
}
.board__spot:hover .board__name { color: var(--deep); text-decoration: underline; text-underline-offset: 4px; }
.board__name {
  font-family: var(--font-cond);
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.board__temp { font-size: var(--step--1); color: var(--ink-3); }
.board__none { margin: var(--sp-2) 0 0; }
.board__rail { margin-top: var(--sp-3); gap: var(--sp-2); }
.board__best { margin: var(--sp-2) 0 0; color: var(--ink-2); }

/* Day chip. 56px wide by 58px tall - a comfortable thumb target, and seven of
   them scroll inside the rail rather than widening the page. */
.chip {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 1px;
  min-width: 3.6rem;
  min-height: 58px;
  padding: var(--sp-2) var(--sp-1);
  border: 1px solid var(--line);
  border-top: 3px solid var(--rate-ink);
  border-radius: var(--radius-s);
  background: var(--rate-wash);
  text-decoration: none;
  color: var(--ink);
}
.chip:hover { background: color-mix(in srgb, var(--rate-ink) 14%, var(--rate-wash)); color: var(--ink); }
.chip__wd {
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.chip__s { font-size: var(--step-1); font-weight: 700; line-height: 1; color: var(--rate-ink); }
.chip__r {
  font-family: var(--font-cond);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}

/* ------------------------------------------------------------- sell ---- */
.sell {
  padding: var(--sp-5) var(--sp-4);
  border-radius: var(--radius-l);
  background: var(--deep);
  color: #fff;
}
.sell__h { margin: 0 0 var(--sp-3); color: #fff; font-size: var(--step-2); }
.sell__b { margin: 0 0 var(--sp-4); color: rgba(255,255,255,0.86); max-width: 46ch; }
.sell__days {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  list-style: none;
  margin: 0 0 var(--sp-5);
  padding: 0;
}
.sell__days li {
  font-family: var(--font-cond);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: var(--step--1);
  padding: 5px 12px;
  border: 1px solid rgba(255,255,255,0.4);
  border-radius: 999px;
}
.sell__a { margin: 0 0 var(--sp-3); }
.sell .btn { background: #fff; color: var(--deep); }
.sell .btn:hover { background: rgba(255,255,255,0.88); color: var(--deep); }
.sell__fine { margin: 0; color: rgba(255,255,255,0.72); }
/* The sell block paints its own ground, so the focus ring needs to survive it. */
.sell :focus-visible { outline-color: #fff; }

.alt { display: grid; gap: var(--sp-4); }
@media (min-width: 44rem) { .alt { grid-template-columns: 1fr 1fr; } }
.alt__i { padding: var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); }
.alt__h { margin: 0 0 var(--sp-2); font-size: var(--step-1); }
.alt__b { color: var(--ink-2); }

/* =========================================================== archived === */
.archived {
  padding: var(--sp-4);
  border: 1px solid var(--amber);
  border-left: 5px solid var(--amber);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--amber) 12%, var(--card));
}
.archived__h {
  margin: 0 0 var(--sp-1);
  font-family: var(--font-cond);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--amber);
}
.archived__b { margin: 0 0 var(--sp-3); }
.archived__a { margin: 0; }

/* ============================================================= safety === */
/* San Luis Pass drowns people. This block is loud on purpose. */
.safety {
  padding: var(--sp-4);
  border: 1px solid var(--rust);
  border-left: 5px solid var(--rust);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--rust) 10%, var(--card));
}
.safety__h {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-cond);
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--rust);
}
.safety__b { margin: 0; font-size: var(--step-0); font-weight: 500; max-width: 62ch; }

/* ======================================================= week ribbon ==== */
/* The whole run as one tide line, each day stroked in its own rating colour.
   preserveAspectRatio="none" lets it fill any width; non-scaling-stroke keeps
   the line weight honest while it does. */
.ribbon {
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--plate);
}
.ribbon__h {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.ribbon__svg { display: block; width: 100%; height: 96px; overflow: visible; }
@media (min-width: 48rem) { .ribbon__svg { height: 132px; } }
.ribbon__area { fill: var(--ribbon-area); stroke: none; }
.ribbon__tick { stroke: var(--plate-line); stroke-width: 1; }
/* Each day is stroked in its own rating colour, carried inline as --seg /
   --seg-dark so the dark accent can be swapped in the same way .rated does. */
.ribbon__seg {
  fill: none;
  stroke: var(--seg, var(--ink-3));
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.55;
}
.ribbon__seg.is-hot { stroke-width: 3.5; opacity: 1; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ribbon__seg { stroke: var(--seg-dark, var(--ink-3)); }
}
:root[data-theme="dark"] .ribbon__seg { stroke: var(--seg-dark, var(--ink-3)); }
.ribbon__scale { margin: var(--sp-2) 0 0; }

/* One orchestrated moment on the page: the week draws itself in. */
@media (prefers-reduced-motion: no-preference) {
  .ribbon__seg {
    stroke-dasharray: 900;
    stroke-dashoffset: 900;
    animation: ribbon-draw 1.1s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
  }
  @keyframes ribbon-draw { to { stroke-dashoffset: 0; } }
}

/* ========================================================== day strip === */
.strip__rail { gap: var(--sp-2); }
.strip__d {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 1px;
  min-width: 4.2rem;
  min-height: 72px;
  padding: var(--sp-2) var(--sp-1);
  border: 1px solid var(--line);
  border-top: 4px solid var(--rate-ink);
  border-radius: var(--radius-s);
  background: var(--rate-wash);
  text-decoration: none;
  color: var(--ink);
}
.strip__d:hover { background: color-mix(in srgb, var(--rate-ink) 14%, var(--rate-wash)); color: var(--ink); }
.strip__wd {
  font-family: var(--font-cond);
  font-size: var(--step-0);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.strip__n { font-size: var(--step--1); color: var(--ink-3); }
.strip__s { font-size: var(--step-1); font-weight: 700; line-height: 1.05; color: var(--rate-ink); }
.strip__r {
  font-family: var(--font-cond);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
@media (min-width: 60rem) {
  /* Enough room for seven: let them share the width instead of scrolling. */
  .strip__rail { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; overflow: visible; }
  .strip__d { min-width: 0; }
}

/* ============================================================== setup === */
.setup__h, .days__h, .doc__h {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-cond);
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding-bottom: var(--sp-2);
  border-bottom: 2px solid var(--ink);
}
.setup__p {
  font-family: var(--font-display);
  font-size: var(--step-0);
  line-height: 1.62;
  max-width: 66ch;
}
/* The setup is background reading; give it display size only once there is
   room for it beside everything else. */
@media (min-width: 48rem) { .setup__p { font-size: var(--step-1); } }
.setup__obs {
  list-style: none;
  margin: var(--sp-4) 0 0;
  padding: var(--sp-3) var(--sp-4);
  border-left: 3px solid var(--amber);
  background: var(--plate);
  border-radius: 0 var(--radius-s) var(--radius-s) 0;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.7;
  color: var(--ink-2);
}
.setup__obs li + li { margin-top: var(--sp-2); }

/* ========================================================== day cards === */
/* minmax(0,1fr) rather than a bare auto column: a grid item defaults to
   min-width:auto, so the card would refuse to shrink below the hour chart's
   min-width and push the page sideways on a 320px handset. */
.days__grid { display: grid; gap: var(--sp-5); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 60rem) {
  .days__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
}

.day {
  border: 1px solid var(--line);
  border-top: 4px solid var(--rate-ink);
  border-radius: var(--radius);
  background: var(--card);
  padding: var(--sp-4);
  box-shadow: var(--shadow-1);
  scroll-margin-top: 110px;  /* clear the sticky header + spot tabs on a jump */
}

.day__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.day__name {
  margin: 0;
  font-family: var(--font-cond);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 0.95;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.day__date { margin: var(--sp-1) 0 0; font-size: var(--step--1); color: var(--ink-3); }
.day__verdict { display: flex; flex-direction: column; align-items: flex-end; gap: var(--sp-1); }
.day__badge {
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--rate-ink);
  border: 1px solid var(--rate-ink);
  border-radius: 3px;
  padding: 3px 8px;
  white-space: nowrap;
}
.day__score { font-size: var(--step-3); font-weight: 700; line-height: 1; color: var(--rate-ink); }
.day__scoreof { font-size: var(--step--1); color: var(--ink-3); font-weight: 400; }

.day__window {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-1) var(--sp-3);
  margin: var(--sp-4) 0 0;
  padding: var(--sp-3);
  border-radius: var(--radius-s);
  background: var(--rate-wash);
}
.day__windowk {
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.day__windowv { font-size: var(--step-1); font-weight: 700; color: var(--rate-ink); }

.day__clarity { display: flex; align-items: flex-start; gap: var(--sp-3); margin-top: var(--sp-4); }
.day__swatch {
  width: 30px; height: 30px; flex: none;
  border-radius: 4px;
  border: 1px solid rgba(0,0,0,0.22);
}
.day__claritytext { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.day__clarityname {
  font-family: var(--font-cond);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.day__clarityline { font-size: var(--step--1); color: var(--ink-2); }

/* --------------------------------------------------- lure against bait --- */
.vs { margin-top: var(--sp-4); }
.vs__h, .wins__h {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.vs__row {
  display: grid;
  grid-template-columns: 5.4rem minmax(0, 1fr) 2.4rem;
  align-items: center;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-2);
}
.vs__k {
  font-family: var(--font-cond);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.vs__row.is-win .vs__k { color: var(--ink); }
.vs__flag {
  display: inline-block;
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  padding: 1px 5px;
  border-radius: 3px;
  background: var(--deep);
  color: #fff;
  vertical-align: 2px;
}
.vs__track, .subs__track {
  height: 8px;
  border-radius: 999px;
  background: var(--plate);
  border: 1px solid var(--plate-line);
  overflow: hidden;
}
/* Both techniques are viable unless the pipeline picks one; grey would read
   as disabled on an EITHER day. */
.vs__fill { display: block; height: 100%; background: var(--trout); }
.vs__row.is-win .vs__fill { background: var(--deep); }
.vs__n { text-align: right; font-weight: 700; }
.vs__tie, .vs__note {
  margin: var(--sp-2) 0 0;
  font-size: var(--step--1);
  color: var(--ink-2);
}
.vs__tie { font-weight: 600; color: var(--ink); }

/* ---------------------------------------------------------- subscores --- */
.subs {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-2) var(--sp-4);
  margin: var(--sp-4) 0 0;
  padding: var(--sp-3);
  border-radius: var(--radius-s);
  background: var(--plate);
}
@media (min-width: 30rem) { .subs { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.subs__i { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px var(--sp-2); }
.subs__k {
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.subs__n { font-weight: 700; font-size: var(--step--1); }
.subs__track { grid-column: 1 / -1; height: 5px; background: var(--card); }
.subs__fill { display: block; height: 100%; background: var(--trout); }

/* -------------------------------------------------------------- facts --- */
.facts { margin: var(--sp-4) 0 0; }
.facts__row {
  display: grid;
  grid-template-columns: 4.8rem minmax(0, 1fr);
  gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-2) 0;
  border-top: 1px solid var(--line-2);
}
.facts dt {
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-top: 2px;
}
.facts dd { margin: 0; font-size: var(--step--1); min-width: 0; }
.facts dd strong { font-family: var(--font-mono); font-weight: 700; }
.facts__sub { display: block; color: var(--ink-3); }

/* ------------------------------------------------------------ windows --- */
.wins { margin-top: var(--sp-4); }
.wins__list { list-style: none; margin: 0; padding: 0; }
.wins__i {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1px var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-left: 3px solid var(--line);
  margin-bottom: var(--sp-2);
  background: var(--card-2);
  border-radius: 0 var(--radius-s) var(--radius-s) 0;
}
.wins__i.is-prime { border-left-color: var(--deep); background: var(--tint); }
.wins__time { font-weight: 700; font-size: var(--step--1); }
.wins__scores { font-size: var(--step--1); color: var(--ink-3); text-align: right; white-space: nowrap; }
.wins__note { grid-column: 1 / -1; font-size: var(--step--1); color: var(--ink-2); }

/* -------------------------------------------- progressive disclosure --- */
.dz { margin-top: var(--sp-4); border-top: 1px solid var(--line); }
.dz__d { border-bottom: 1px solid var(--line-2); }
.dz__s {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  padding: var(--sp-2) 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-cond);
  font-size: var(--step-0);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.dz__s::-webkit-details-marker { display: none; }
.dz__s::before {
  content: '';
  width: 10px; height: 10px; flex: none;
  border-right: 2px solid var(--deep);
  border-bottom: 2px solid var(--deep);
  transform: rotate(-45deg) translate(-2px, -2px);
  transition: transform 0.16s ease;
}
.dz__d[open] > .dz__s::before { transform: rotate(45deg) translate(-1px, -1px); }
.dz__d[open] > .dz__s { color: var(--ink); }
.dz__b { padding-bottom: var(--sp-3); }
.dz__b p {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-0);
  line-height: 1.62;
  color: var(--ink-2);
  max-width: 62ch;
}

/* ========================================================= hour chart === */
.hc { margin: var(--sp-4) 0 0; }
.hc__cap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-1) var(--sp-3);
  margin-bottom: var(--sp-2);
}
.hc__capk {
  font-family: var(--font-cond);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.hc__capv { font-size: var(--step--1); font-weight: 700; color: var(--ink); }

.hc__scroll {
  background: var(--plate);
  border: 1px solid var(--plate-line);
  border-radius: var(--radius-s);
  padding: var(--sp-2);
}
/* Below ~20rem of usable width the chart scrolls inside its own box rather
   than squashing. The page body still never moves. */
.hc__svg { display: block; width: 100%; min-width: 17rem; height: auto; }

.hc__day { fill: var(--day-band); }
.hc__base { stroke: var(--plate-line); stroke-width: 1; }
.hc__bar--fish { filter: var(--bar-lift); }
.hc__bar--idle { opacity: var(--idle-alpha); }
.hc__curve { fill: none; stroke: var(--ink-3); stroke-width: 1.1; opacity: 0.7; stroke-linejoin: round; }
.hc__peak { stroke: var(--ink-3); stroke-width: 0.8; stroke-dasharray: 2 2; opacity: 0.8; }
.hc__peaklbl, .hc__peaktime {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  fill: var(--ink-2);
}
.hc__peaktime { font-weight: 400; fill: var(--ink-3); }
.hc__lit { filter: var(--bar-lift); }
.hc__dark { fill: var(--ink-3); opacity: var(--idle-alpha); }
.hc__wind { opacity: 0.42; filter: var(--bar-lift); }
.hc__ax {
  font-family: var(--font-cond);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  fill: var(--ink-3);
}

.hc__key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  margin: var(--sp-2) 0 0;
  font-size: var(--step--1);
  color: var(--ink-3);
}
.hc__keyitem { display: inline-flex; align-items: center; gap: var(--sp-2); }
.hc__chip { width: 12px; height: 8px; border-radius: 2px; flex: none; }
.hc__chip--lit { background: var(--deep); }
.hc__chip--dark { background: var(--ink-3); opacity: var(--idle-alpha); }
.hc__chip--wind { background: var(--trout); opacity: 0.42; }

/* =============================================================== tail === */
.tail { display: grid; gap: var(--sp-4); }
.tail__cta {
  padding: var(--sp-5) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card-2);
}
.tail__h { margin: 0 0 var(--sp-2); font-size: var(--step-2); }
.tail__b { color: var(--ink-2); max-width: 50ch; }
.tail__alt { margin: var(--sp-3) 0 0; font-size: var(--step--1); color: var(--ink-3); }

.tail__box { border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--card); }
.tail__sum {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--sp-4);
  cursor: pointer;
  font-family: var(--font-cond);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.tail__list { margin: 0; padding: 0 var(--sp-4) var(--sp-4) calc(var(--sp-4) + 1.1em); }
.tail__list li { margin-bottom: var(--sp-2); font-size: var(--step--1); color: var(--ink-2); }
.tail__list--links { list-style: none; padding-left: var(--sp-4); }
.tail__list--links a { display: inline-flex; align-items: center; min-height: var(--tap); }
.tail__stamp { margin: 0; }

/* =============================================================== docs === */
.doc > p, .doc > ul { max-width: 68ch; }
.doc--warn { padding: var(--sp-4); border-radius: var(--radius); border: 1px solid var(--line); background: var(--card-2); }

.inputs { display: grid; gap: var(--sp-4); }
@media (min-width: 44rem) { .inputs { grid-template-columns: 1fr 1fr; } }
.inputs__i {
  padding: var(--sp-4);
  border: 1px solid var(--line);
  border-left: 3px solid var(--trout);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--card);
}
.inputs__h {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-cond);
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.inputs__i p { font-size: var(--step--1); color: var(--ink-2); }
.inputs__note { margin-bottom: 0; color: var(--ink-3) !important; font-style: italic; }

.bands { list-style: none; margin: 0 0 var(--sp-4); padding: 0; display: grid; gap: var(--sp-2); }
.bands__i {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: var(--tap);
  padding: var(--sp-2) var(--sp-3);
  border-left: 5px solid var(--rate-ink);
  border-radius: 0 var(--radius-s) var(--radius-s) 0;
  background: var(--rate-wash);
}
.bands__name {
  font-family: var(--font-cond);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--rate-ink);
}
.bands__range { font-size: var(--step--1); color: var(--ink-2); }

.spots-doc { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4); }
.spots-doc__i { padding-bottom: var(--sp-4); border-bottom: 1px solid var(--line); }
.spots-doc__h { margin: 0 0 var(--sp-2); font-size: var(--step-1); }
.spots-doc__geo { color: var(--ink-2); font-size: var(--step--1); }
.spots-doc__safety {
  font-size: var(--step--1);
  padding: var(--sp-2) var(--sp-3);
  border-left: 3px solid var(--rust);
  background: color-mix(in srgb, var(--rust) 8%, var(--card));
  border-radius: 0 var(--radius-s) var(--radius-s) 0;
}
.spots-doc__meta { margin-bottom: 0; }

.limits, .srcs { padding-left: 1.15em; }
.limits li, .srcs li { margin-bottom: var(--sp-2); color: var(--ink-2); }
.srcs a { display: inline-flex; align-items: center; min-height: var(--tap); }

/* ======================================================= empty states === */
.empty--page { text-align: left; padding: var(--sp-6) var(--sp-4); }
.empty__h {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-cond);
  font-size: var(--step-2);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink);
}
.empty__b { margin: 0 0 var(--sp-4); color: var(--ink-2); max-width: 52ch; }
.empty__a { margin: 0; display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* ============================================================== print === */
@media print {
  .spots, .strip, .sell, .alt, .tail__cta { display: none !important; }
  /* The hero is a night panel. On paper it is just the headline. */
  .hero__water, .hero__hours, .hero__go, .hero__nav { display: none !important; }
  .hero { background: none; color: var(--ink); padding-block: 0; margin-block: 0; border: 0; }
  .hero::after { display: none; }
  /* Only the slide on screen prints; the other five are not what was being read. */
  .hero__slide { display: none; padding-bottom: 0; }
  .hero__slide.is-current { display: block; opacity: 1; visibility: visible; }
  .hero__spot, .hero__when, .hero__lede, .hero__say, .hero__winv { color: var(--ink); }
  .hero__kicker { color: var(--ink-3); }
  .hero__win { background: none; border-color: var(--line); }
  .day, .ribbon, .hc__scroll { break-inside: avoid; box-shadow: none; }
  .dz__d { display: block; }
  .dz__b { display: block !important; }
}

/* Staleness. A spot whose pipeline stopped running should look wrong on the
   board rather than quietly showing two chips and letting the reader assume
   that is all the forecast has. */
.board__stale {
  display: inline-block;
  font-family: var(--font-cond);
  font-size: .68rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  padding: .1rem .4rem; margin-right: .4rem; border-radius: 3px;
  background: color-mix(in srgb, var(--amber) 18%, var(--card));
  color: var(--amber);
  border: 1px solid color-mix(in srgb, var(--amber) 40%, transparent);
}
