/* The destination page (rounds 120 + 122).
   Brand tokens only -- main.css owns every colour and radius here, so
   this page moves with the rest of the site rather than beside it. The
   founder's round-122 layout came as an SVG in green and orange; he
   chose to keep Seenary's colours, so the STRUCTURE is his and every
   value below resolves to a var() from main.css. Nothing here is a hex
   code that only this page knows. */

/* [hidden] WINS ON THIS PAGE, ALWAYS (round 122i).

   `[hidden] { display: none }` is a USER-AGENT rule, which every
   author-origin rule beats regardless of specificity. So any selector
   here that sets an explicit `display` silently makes `el.hidden = true`
   do nothing -- the JS believes it hid the element and the element is
   still on screen.

   That is what the founder photographed on /destination/Bengaluru:
   paint() correctly decided the page had nothing to say and set
   `dp-tabs.hidden = true`, `.dp-tabs { display: flex }` overrode it, and
   the tab row rendered directly above "We haven't written a guide for
   this place yet". `.dp-exp` had the same hole waiting.

   This page had been guarding it one class at a time (.dp-facts[hidden],
   .dp-weather[hidden], .dp-cta[hidden] ...) and two were missed, which
   is the argument against doing it that way: every new flex or grid rule
   is another chance to forget. One page-level rule ends the whole class
   of bug, and `!important` is correct rather than a smell here -- it is
   restoring the platform's own semantics against author rules that were
   never meant to outrank them.

   tests/test_round122i_destination_gaps.py asserts this rule exists. */
[hidden] { display: none !important; }

/* The reading column is narrow on purpose; the HERO is not part of it.
   A destination photograph boxed into 880px on a wide screen reads as a
   card about a place rather than the place itself. */
.dp-page {
  /* `width: 100%` is load-bearing, and the bug it fixes is subtle. This
     is a FLEX ITEM (.marketing-page-shell is display:flex/column), and
     `margin: 0 auto` on a flex item cancels the cross-axis stretch --
     so without an explicit width the column shrink-wraps to its
     CONTENT's max-content width and every tab gets a different one. The
     founder saw it as "when I click on the About tab, the whole panel
     resizes": Info measured 804px, Tips & FAQ and About 513px. It has
     been true since round 120 and only became visible once round 122c
     gave the panel a drawn edge. */
  width: 100%;
  max-width: 880px;
  margin: 0 auto;
  padding: 0 20px 64px;
}

/* No 100vw bleed here, deliberately: `100vw` counts the scrollbar, so on
   a page tall enough to scroll it is wider than the viewport and the
   whole site gains a horizontal scrollbar. Measured, not guessed. The
   hero is simply a SIBLING of the reading column instead, which is full
   width by default and needs no arithmetic at all. */

/* --- hero (round 122: split) --------------------------------------
   The round-120 hero was a photograph with the name burned into the
   bottom of it. A split puts the words on a readable surface and gives
   the photograph its own frame, which is also what lets the facts rail
   and the live weather chip exist at all -- neither is legible over an
   unknown Wikipedia image.

   Order matters on a phone: the words come FIRST and the picture second
   (`order` below), because a traveller who searched a place wants to
   know they landed on it before they want to look at it. */
.dp-hero {
  position: relative;
  margin: 0;
  overflow: hidden;
  /* The navy end of the brand gradient, so the section reads as
     Seenary's own surface rather than as whatever the photo is. */
  background:
    radial-gradient(120% 140% at 12% 0%, rgba(var(--accent-rgb), 0.42) 0%, rgba(var(--accent-rgb), 0) 62%),
    linear-gradient(135deg, var(--ink) 0%, #1B2A4E 58%, var(--accent-ink) 140%);
  color: #fff;
}

.dp-hero-inner {
  max-width: 1160px;
  margin: 0 auto;
  /* THE FIXED NAV'S HEIGHT IS RESERVED, NOT GUESSED (round 122j).
     .landing-nav is position:fixed and takes the top ~64px of the
     viewport. This padding used to be a bare 44px, so on a phone the
     hero's kicker sat at y26-40 -- entirely behind the logo -- and 14 of
     the H1's 35px sat behind it too. Measured identically at 320, 393
     and 430px, i.e. on every iPhone: the destination's own name was half
     hidden in the first three seconds.
     --dp-nav-h is measured from the live nav by destination.js and
     re-measured on scroll and resize, because the nav changes height
     when it takes its scrolled state. The fallback is the nav's
     desktop height, so this is right even before the script runs. */
  padding: calc(var(--dp-nav-h, 76px) + 20px) 20px 48px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  gap: 40px;
  align-items: center;
}

.dp-hero-text { min-width: 0; }

.dp-kicker {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-bright);
}

.dp-name {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(34px, 5.4vw, 60px);
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1.02;
}

.dp-tagline {
  margin: 14px 0 0;
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--on-ink-muted);
  max-width: 46ch;
}

/* The facts rail. Three tiles, each removing itself when the register
   has no answer -- so this is 1, 2 or 3 columns and never a gap. */
.dp-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 22px 0 0;
}
.dp-facts[hidden] { display: none; }

.dp-fact {
  flex: 1 1 150px;
  min-width: 0;
  padding: 12px 14px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.dp-fact[hidden] { display: none; }

.dp-fact dt {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent-bright);
}

.dp-fact dd {
  margin: 5px 0 0;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.45;
  color: #fff;
}

.dp-hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 26px;
}

.dp-ghost {
  padding: 11px 18px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  transition: background-color var(--duration-quick, 140ms) ease,
              border-color var(--duration-quick, 140ms) ease;
}
.dp-ghost:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.5);
}
.dp-ghost[hidden] { display: none; }

/* `[hidden]` alone loses to an explicit `display`, which is how round
   61's .tb-seg shipped a segment that would not hide. Same trap, same
   fix: the attribute gets its own rule. */
.dp-badge[hidden] { display: none; }
.dp-plan[hidden] { display: none; }

.dp-badge {
  display: inline-block;
  padding: 8px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  font-size: 12.5px;
  font-weight: 600;
}

/* --- hero photograph + weather ------------------------------------- */
.dp-hero-media-wrap {
  position: relative;
  min-width: 0;
  border-radius: 22px;
  overflow: hidden;
  /* A fixed ratio, so the hero's height does not jump when the image
     arrives (or never does). */
  aspect-ratio: 4 / 3;
  background: rgba(255, 255, 255, 0.06);
  box-shadow: 0 28px 60px -28px rgba(var(--shadow-ink), 0.85);
}

.dp-hero-media {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  /* Visible while (or instead of) the photograph: the brand gradient,
     never a grey box and never an alt-text apology. */
  background-image: linear-gradient(135deg, var(--accent) 0%, var(--pop) 62%, var(--sun) 130%);
  transform: scale(1.02);
  transition: transform 900ms var(--ease-warm, ease);
}
.dp-hero-media-wrap:hover .dp-hero-media { transform: scale(1.06); }

/* MET Norway, CC BY 4.0 -- hidden entirely when the forecast did not
   answer. A destination page that invents a temperature is worse than
   one that shows none. */
.dp-weather {
  position: absolute;
  left: 14px;
  bottom: 14px;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 9px 14px;
  border-radius: 999px;
  background: rgba(10, 14, 30, 0.58);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.16);
}
.dp-weather[hidden] { display: none; }

.dp-weather-temp {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 700;
  color: #fff;
}

.dp-weather-sky {
  font-size: 12.5px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.82);
}

/* --- tabs ---------------------------------------------------------- */
.dp-tabs {
  display: flex;
  gap: 8px;
  margin: 18px 0 0;
  padding-bottom: 4px;
  overflow-x: auto;
  scrollbar-width: none;
}
.dp-tabs::-webkit-scrollbar { display: none; }

/* A KEYBOARD USER HAS TO SEE WHERE THEY ARE (round 122j). The tabs had
   no :focus-visible treatment at all, so keyboard and switch-control
   users could tab through three controls with no indication of which
   one was focused. */
.dp-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.dp-tab {
  flex: 0 0 auto;
  padding: 9px 16px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--muted);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--duration-quick, 140ms) ease, color var(--duration-quick, 140ms) ease;
}

.dp-tab:hover { color: var(--ink); }

.dp-tab.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* --- panels -------------------------------------------------------- */
.dp-panel { padding-top: 6px; }
/* Round 228: the server writes every panel OPEN, because a crawler runs no
   JavaScript. With JavaScript (marked on <html> in the head, before the first
   paint) only the active panel shows, so the page is tabs from its first
   frame; without it the tab row, which could do nothing, steps aside. */
.dp-js .dp-panel:not(.is-active) { display: none; }
html:not(.dp-js) .dp-tabs { display: none; }

.dp-block {
  padding: 18px 0;
  border-bottom: 1px solid var(--border);
}
.dp-block:last-child { border-bottom: none; }

.dp-block h2 {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.dp-para {
  margin: 0 0 8px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink);
}
.dp-para:last-child { margin-bottom: 0; }

.dp-rows { margin: 0; }

.dp-row {
  display: flex;
  gap: 14px;
  padding: 7px 0;
  font-size: 14.5px;
}

.dp-row dt {
  flex: 0 0 82px;
  color: var(--muted);
  font-weight: 600;
}

.dp-row dd {
  margin: 0;
  color: var(--ink);
}

.dp-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.dp-chips li {
  padding: 7px 12px;
  border-radius: 10px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  font-size: 13.5px;
  color: var(--ink);
}

/* --- faq ----------------------------------------------------------- */
.dp-faq {
  border-bottom: 1px solid var(--border);
}
.dp-faq:last-child { border-bottom: none; }

.dp-faq summary {
  padding: 12px 26px 12px 0;
  position: relative;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}
.dp-faq summary::-webkit-details-marker { display: none; }

.dp-faq summary::after {
  content: "";
  position: absolute;
  right: 6px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: translateY(-70%) rotate(45deg);
  transition: transform var(--duration-quick, 140ms) ease;
}
.dp-faq[open] summary::after { transform: translateY(-30%) rotate(-135deg); }

.dp-faq .dp-para { padding: 0 0 14px; color: var(--muted); }

/* --- the About panel (round 141) -------------------------------------
   Where it is, its history and its people read down the main column; what
   it is known for and the one fact worth knowing sit beside them as cards,
   and the setting chips head the whole panel. One column under 900px, in
   that same reading order. Every value is a main.css token. */
.dp-setting {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 20px;
  padding: 0;
  list-style: none;
}

.dp-setting li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 14px 5px 5px;
  border-radius: 999px;
  background: var(--accent-bg-soft);
  color: var(--accent-ink);
  font-size: 13px;
  font-weight: 700;
}

.dp-setting-icon {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--bg);
}
.dp-setting-icon svg { width: 15px; height: 15px; }

.dp-about-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(240px, 330px);
  gap: 24px 36px;
  align-items: start;
}

.dp-about-sec { padding: 0 0 18px; }
.dp-about-main .dp-about-sec + .dp-about-sec {
  padding-top: 18px;
  border-top: 1px solid var(--border);
}
.dp-about-main .dp-about-sec:last-child { padding-bottom: 0; }

.dp-about-sec h3 {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
}

.dp-about-icon {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 10px;
  background: var(--accent-bg-soft);
  color: var(--accent-ink);
}
.dp-about-icon svg { width: 16px; height: 16px; }

.dp-about-side {
  display: grid;
  gap: 14px;
}

.dp-about-side .dp-about-sec {
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: 16px;
  background: var(--bg);
}

.dp-known {
  margin: 0;
  padding: 0;
  list-style: none;
}

.dp-known li {
  position: relative;
  padding: 7px 0 7px 18px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--ink);
}
.dp-known li + li { border-top: 1px dashed var(--border); }

.dp-known li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 14px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.dp-about-side .dp-about-fact {
  border-color: transparent;
  background:
    radial-gradient(120% 140% at 100% 0%, var(--accent-bg-soft) 0%, rgba(243, 238, 255, 0) 70%),
    var(--bg-soft);
}
.dp-about-fact .dp-para { font-size: 14.5px; }

.dp-about .dp-source { margin: 14px 0 0; }

@media (max-width: 900px) {
  .dp-about-grid { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .dp-about-main .dp-about-sec:last-child { padding-bottom: 18px; }
}

.dp-empty {
  padding: 40px 0;
  text-align: center;
  color: var(--muted);
  font-size: 15px;
}

/* ==================================================================
   ROUND 122 SECTIONS
   Each of the four below is full-bleed (a sibling of .dp-page, never a
   child -- see the 100vw note at the top of this file) with its own
   centred inner column, so the reading measure stays narrow while the
   map and the rails use the whole window.
   ================================================================== */

.dp-explore,
.dp-next,
.dp-suits,
.dp-cta { padding: 0 20px; }

.dp-explore[hidden],
.dp-next[hidden],
.dp-suits[hidden],
.dp-cta[hidden] { display: none; }

.dp-explore-head,
.dp-next-head,
.dp-suits-head {
  max-width: 1160px;
  margin: 0 auto;
  padding: 52px 0 20px;
}

.dp-explore-head h2,
.dp-next-head h2,
.dp-suits-head h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(24px, 3.2vw, 34px);
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.dp-explore-sub,
.dp-next-sub,
.dp-suits-sub {
  margin: 8px 0 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--muted);
  max-width: 60ch;
}

/* --- the map and the list ------------------------------------------
   ONE component. Hovering a row lifts its pin; clicking one flies the
   camera. The map is sticky on a wide screen so the list scrolls
   against it, which is the whole reason this is not two sections. */
.dp-explore-body {
  max-width: 1160px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 24px;
  align-items: start;
}

.dp-map-wrap {
  position: sticky;
  top: 20px;
  border-radius: 20px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg-soft);
}

.dp-map {
  height: clamp(320px, 52vh, 520px);
  width: 100%;
}

/* Honest, and the reason it exists: a sight with no coordinate has no
   pin, and a map quietly showing four of seven places is a lie of
   omission. destination.js unhides this and writes the count. */
.dp-map-note {
  margin: 0;
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  background: var(--bg);
  font-size: 12.5px;
  color: var(--muted);
}
.dp-map-note[hidden] { display: none; }

.dp-experiences {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* Scrolls against the sticky map rather than running the page on. */
  max-height: clamp(320px, 52vh, 520px);
  overflow-y: auto;
  padding-right: 4px;
}

.dp-exp {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 16px;
  background: var(--bg);
  cursor: pointer;
  text-align: left;
  width: 100%;
  font: inherit;
  transition: border-color var(--duration-quick, 140ms) ease,
              box-shadow var(--duration-quick, 140ms) ease,
              transform var(--duration-quick, 140ms) ease;
}

.dp-exp:hover,
.dp-exp.is-active {
  border-color: var(--accent);
  box-shadow: 0 10px 24px -14px rgba(var(--shadow-ink), 0.55);
  transform: translateY(-1px);
}

/* The number is the map's pin label -- the two must always read the
   same, which is why destination.js writes one index into both. */
.dp-exp-num {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--pop));
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* A sight with no coordinate gets a flat badge, so the list itself says
   which rows the map cannot show. */
.dp-exp.is-unmapped .dp-exp-num {
  background: var(--bg-soft);
  border: 1px solid var(--border);
  color: var(--muted);
}
.dp-exp.is-unmapped { cursor: default; }
.dp-exp.is-unmapped:hover {
  border-color: var(--border);
  box-shadow: none;
  transform: none;
}

.dp-exp-body { min-width: 0; }

.dp-exp-name {
  margin: 0;
  font-size: 15px;
  font-weight: 650;
  line-height: 1.35;
  color: var(--ink);
}

.dp-exp-meta {
  margin: 5px 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  font-size: 12.5px;
  color: var(--muted);
}

.dp-exp-meta span { display: inline-flex; align-items: center; gap: 5px; }
.dp-exp-meta span + span::before {
  content: "";
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--border);
}

/* The map's own pins, built as DOM elements (MapLibre markers) rather
   than an image sprite, so they carry the same number the list does.

   TWO elements, and the reason is worth keeping: MAPLIBRE OWNS THE
   MARKER ELEMENT'S `transform` -- it writes the translate that positions
   the marker on every frame. A `rotate(-45deg)` on .dp-pin is therefore
   overwritten, while the counter-rotation on the number is not, so the
   first version of this shipped four pins with their digits lying on
   their side. Anything transformed here goes on the INNER element. */
.dp-pin { cursor: pointer; }

.dp-pin-shape {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 50% 50% 50% 4px;
  transform: rotate(-45deg);
  background: linear-gradient(135deg, var(--accent), var(--pop));
  border: 2px solid #fff;
  box-shadow: 0 4px 10px -2px rgba(var(--shadow-ink), 0.7);
  transition: transform var(--duration-quick, 140ms) var(--ease-warm, ease);
}

.dp-pin-shape span {
  transform: rotate(45deg);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.dp-pin.is-active .dp-pin-shape { transform: rotate(-45deg) scale(1.25); }

/* --- up next -------------------------------------------------------- */
.dp-next-rail {
  max-width: 1160px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 16px;
  padding-bottom: 8px;
}

.dp-neighbour {
  position: relative;
  display: block;
  border-radius: 18px;
  overflow: hidden;
  min-height: 190px;
  text-decoration: none;
  color: #fff;
  background: linear-gradient(140deg, var(--accent-ink), var(--accent));
  transition: transform var(--duration-quick, 140ms) var(--ease-warm, ease),
              box-shadow var(--duration-quick, 140ms) ease;
}

.dp-neighbour:hover {
  transform: translateY(-3px);
  box-shadow: 0 18px 38px -20px rgba(var(--shadow-ink), 0.75);
}

.dp-neighbour-media {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  transition: transform 700ms var(--ease-warm, ease);
}
.dp-neighbour:hover .dp-neighbour-media { transform: scale(1.07); }

.dp-neighbour-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10, 14, 30, 0.1) 30%, rgba(10, 14, 30, 0.82) 100%);
}

.dp-neighbour-body {
  position: relative;
  padding: 16px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 190px;
}

.dp-neighbour-dist {
  align-self: flex-start;
  margin: 0 0 auto;
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(10, 14, 30, 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.dp-neighbour-name {
  margin: 10px 0 0;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.dp-neighbour-sub {
  margin: 4px 0 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.82);
  /* Two lines, then ellipsis -- a register tagline is one sentence but
     not a short one, and a card that grows to fit breaks the rail. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* --- good for (the style cards) ------------------------------------- */
.dp-suits-grid {
  max-width: 1160px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
}

.dp-suit {
  padding: 20px;
  border-radius: 18px;
  border: 1px solid var(--border);
  background: var(--bg);
  transition: border-color var(--duration-quick, 140ms) ease,
              box-shadow var(--duration-quick, 140ms) ease;
}

.dp-suit:hover {
  border-color: var(--accent);
  box-shadow: 0 14px 30px -18px rgba(var(--shadow-ink), 0.55);
}

.dp-suit-icon {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: var(--accent-bg-soft);
  color: var(--accent-ink);
  margin-bottom: 14px;
}
.dp-suit-icon svg { width: 20px; height: 20px; }

.dp-suit h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 750;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.dp-suit-list {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.dp-suit-list li {
  position: relative;
  padding-left: 16px;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--muted);
}

.dp-suit-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

/* --- closing invitation --------------------------------------------- */
.dp-cta { padding: 56px 20px 72px; }

.dp-cta-inner {
  max-width: 1160px;
  margin: 0 auto;
  padding: 48px 32px 52px;
  border-radius: 26px;
  text-align: center;
  color: #fff;
  background:
    radial-gradient(90% 120% at 50% 0%, rgba(236, 72, 153, 0.34) 0%, rgba(236, 72, 153, 0) 60%),
    linear-gradient(135deg, var(--accent-ink) 0%, var(--accent) 55%, #3B1F8F 130%);
}

.dp-cta-kicker {
  margin: 0;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sun);
}

.dp-cta-title {
  margin: 12px 0 0;
  font-family: var(--font-display);
  font-size: clamp(26px, 4vw, 40px);
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1.1;
}

.dp-cta-sub {
  margin: 14px auto 0;
  max-width: 52ch;
  font-size: 15.5px;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.86);
}

/* INVERSE on the coloured panel. .btn-vivid is the brand violet, and the
   panel it sits on is the same violet -- measured, not guessed: the
   button rendered as bare white text on the first pass because both were
   rgb(124, 58, 237). A button has to be able to be seen. */
.dp-cta-btn {
  margin-top: 26px;
  background: #fff;
  background-image: none;
  color: var(--accent-ink);
  box-shadow: 0 12px 28px -12px rgba(10, 14, 30, 0.55);
}
.dp-cta-btn:hover {
  background: #fff;
  color: var(--accent-dark);
  transform: translateY(-1px);
}

/* ==================================================================
   Narrow screens. Every grid above collapses to one column; the hero's
   words come before its photograph.
   ================================================================== */
@media (max-width: 900px) {
  .dp-hero-inner {
    grid-template-columns: 1fr;
    gap: 26px;
    padding: calc(var(--dp-nav-h, 64px) + 16px) 20px 38px;
  }
  .dp-hero-text { order: 1; }
  .dp-hero-media-wrap { order: 2; aspect-ratio: 16 / 10; }
  .dp-explore-body { grid-template-columns: 1fr; }
  /* Not sticky in one column: a map that follows the list it is above
     covers the list. */
  .dp-map-wrap { position: static; }
  .dp-experiences { max-height: none; overflow: visible; }
}

@media (max-width: 560px) {
  .dp-page { padding: 0 16px 56px; }
  .dp-hero-inner { padding: calc(var(--dp-nav-h, 64px) + 14px) 16px 30px; }
  .dp-explore, .dp-next, .dp-suits { padding: 0 16px; }
  .dp-cta { padding: 40px 16px 56px; }
  .dp-cta-inner { padding: 36px 20px 40px; border-radius: 20px; }
  .dp-explore-head, .dp-next-head, .dp-suits-head { padding: 40px 0 16px; }
  /* W-09: one card per row for a single bullet meant ~330px of height
     for one line of text. Two per row at a lower minimum, with the
     padding and icon tile brought in, gets the same content into a
     third of the scroll. */
  .dp-suits-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .dp-suit { padding: 14px; }
  .dp-suit-icon { width: 30px; height: 30px; }
  /* W-08: THREE "Plan this trip" CONTROLS, TWO ON ONE SCREEN.
     The hero button (y=111) and the location band's CTA (y=655) were
     both inside the first 852px on a phone, saying the same words in
     the same colour. Repetition reads as a bug or a hard sell, and it
     splits click intent so no funnel number means anything.
     The BAND keeps its CTA on a phone, because the band is where a
     reader has just learned what the place is; the hero's is the one
     that goes. Both survive on a wide screen, where they are a full
     viewport apart. The closing card keeps its own -- it is 3000px
     down and is the natural end-of-page ask. */
  .dp-plan { display: none; }
  .dp-row { flex-direction: column; gap: 2px; }
  .dp-row dt { flex: none; }
  .dp-facts { gap: 8px; }
  .dp-fact { flex: 1 1 130px; padding: 10px 12px; }
  .dp-map { height: 300px; }
  .dp-next-rail { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
}

/* Respect a reader who has asked for less motion: the zooms and lifts
   above are decoration, and none of them carries information. */
@media (prefers-reduced-motion: reduce) {
  .dp-hero-media,
  .dp-neighbour-media,
  .dp-neighbour,
  .dp-exp,
  .dp-pin-shape { transition: none; }
  .dp-hero-media-wrap:hover .dp-hero-media,
  .dp-neighbour:hover .dp-neighbour-media { transform: none; }
  .dp-neighbour:hover, .dp-exp:hover { transform: none; }
}

/* ==================================================================
   THE INFO PANEL (round 122b)

   The founder's second SVG was dark navy (#090d16) with slate cards,
   and his instruction with it was "background color on the svg section
   can be white" -- so the STRUCTURE below is his and the surface is the
   site's own. That is the same decision as round 122's palette answer,
   one level down: every value here resolves to a var() from main.css,
   so this panel moves with the rest of Seenary rather than beside it.
   ================================================================== */

.dp-info { padding-top: 14px; }

/* The operational status, and it is a REAL fact -- round 119's resolver
   answers SUPPORTED / COMING_SOON / DISCOVERY_ONLY for every place, and
   `supported` is that answer. It is never drawn for a place Seenary
   cannot plan; that page shows the honest badge in the hero instead. */
.dp-status {
  /* Pushed to the right end of the tab row. */
  margin-left: auto;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px 7px 12px;
  border-radius: 999px;
  background: var(--success-bg);
  color: var(--success);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.dp-status i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--success);
}

/* --- the location band --------------------------------------------- */
.dp-band {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin: 14px 0 6px;
  padding: 22px 24px;
  border-radius: 18px;
  border: 1px solid var(--border);
  background:
    radial-gradient(90% 180% at 0% 0%, var(--accent-bg-soft) 0%, rgba(243, 238, 255, 0) 70%),
    var(--bg);
}

.dp-band-text { min-width: 0; }

.dp-band-kicker {
  margin: 0 0 6px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-ink);
}

.dp-band h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(20px, 2.6vw, 26px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--ink);
}

.dp-band-sub {
  margin: 8px 0 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--muted);
}

.dp-band-cta {
  flex: 0 0 auto;
  padding: 12px 20px;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  color: #fff;
  font-size: 13.5px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 10px 24px -12px rgba(var(--accent-rgb), 0.75);
  transition: transform var(--duration-quick, 140ms) var(--ease-warm, ease);
}
.dp-band-cta:hover { transform: translateY(-1px); }

/* --- section headings ----------------------------------------------- */
.dp-sec {
  margin: 30px 0 12px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}

/* --- transit cards --------------------------------------------------- */
.dp-transit {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
}

.dp-transit-card {
  padding: 16px;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: var(--bg);
}

.dp-transit-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: var(--accent-bg-soft);
  color: var(--accent-ink);
  margin-bottom: 12px;
}
.dp-transit-icon svg { width: 17px; height: 17px; }

.dp-transit-card h3 {
  margin: 0 0 4px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--ink);
}

.dp-transit-card p {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
}

/* --- the season ribbon ------------------------------------------------ */
.dp-season {
  padding: 18px;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: var(--bg);
}

.dp-months {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 5px;
  margin: 0 0 14px;
  padding: 0;
  list-style: none;
}

.dp-months li {
  padding: 7px 2px;
  border-radius: 7px;
  background: var(--bg-soft);
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
}

.dp-months li.is-peak {
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  color: #fff;
}

.dp-season-line {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
}

/* --- don't miss -------------------------------------------------------- */
.dp-sights {
  display: grid;
  /* 230px so a four-sight register fills one row on a wide screen,
     which is the shape the founder's design has. */
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
}

.dp-sight {
  padding: 16px;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: var(--bg);
  border-left: 3px solid var(--accent);
  transition: box-shadow var(--duration-quick, 140ms) ease;
}
.dp-sight:hover { box-shadow: 0 10px 22px -14px rgba(var(--shadow-ink), 0.5); }

.dp-sight h3 {
  margin: 0;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--ink);
}

/* The kind and the duration, from the sightseeing register. His design
   had two lines of prose here; nothing holds that, so this is what the
   card says instead of what it would have made up. */
.dp-sight-meta {
  margin: 6px 0 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent-ink);
}

/* --- things to do ------------------------------------------------------ */
.dp-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 10px;
}

.dp-tile {
  padding: 14px 16px;
  border-radius: 12px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}

/* --- where to eat ------------------------------------------------------ */
.dp-dining {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
}

.dp-dine {
  padding: 16px;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: var(--bg);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--ink);
}

@media (max-width: 640px) {
  /* THE PILL GOES ABOVE THE TABS, NOT AFTER THEM (round 122j).
     It used to simply wrap: the row became 95px tall at 320 and 393px
     but stayed 61px at 430px, so the same page had two layouts across
     common iPhones, and a 48px hole opened between the wrapped pill and
     the content. Worse, the identical arrangement on iOS put the pill
     ON TOP OF the About tab -- a visible tab that did nothing when
     tapped. `order: -1` with a full-width basis puts the pill on its
     own first line at every narrow width, which is what the iOS build
     now does; this is that decision ported back. */
  .dp-tabs { flex-wrap: wrap; row-gap: 10px; }
  .dp-status { order: -1; flex-basis: 100%; margin-left: 0; }
  .dp-band { flex-direction: column; align-items: flex-start; padding: 18px; }
  .dp-band-cta { width: 100%; text-align: center; }
  /* Twelve months do not fit a phone in one row. */
  .dp-months { grid-template-columns: repeat(6, 1fr); }
}

/* ==================================================================
   THE SHELL (rounds 122c/122e)

   The tab row and all three panels live in ONE card, exactly as the
   founder's SVG draws it. His SVG was dark navy; he was shown it built
   both ways, chose the dark, then chose white ("lets change the
   background colour to white") -- so the STRUCTURE is his and the
   surface is the site's.

   Everything below resolves to a var() from main.css. The named tokens
   are declared once here so the whole surface is one edit away from
   changing again: nothing in this section hard-codes a colour.
   ================================================================== */
.dp-shell {
  --dp-surface: var(--bg);
  --dp-card: var(--bg);
  --dp-tile: var(--bg-soft);
  --dp-edge: var(--border);
  --dp-edge-soft: var(--border);
  --dp-text: var(--ink);
  --dp-text-dim: var(--muted);
  --dp-text-faint: var(--muted);

  margin: 18px 0 0;
  padding: 24px;
  border-radius: 20px;
  background: var(--dp-surface);
  border: 1px solid var(--dp-edge);
  box-shadow: 0 18px 44px -30px rgba(var(--shadow-ink), 0.45);
}

.dp-shell[hidden] { display: none; }

/* --- the tab row, inside the shell ---------------------------------- */
.dp-shell .dp-tabs {
  margin: 0 0 4px;
  align-items: center;
}

.dp-shell .dp-tab {
  background: var(--dp-tile);
  border-color: var(--dp-edge);
  color: var(--dp-text-dim);
}
.dp-shell .dp-tab:hover { color: var(--dp-text); }

.dp-shell .dp-tab.is-active {
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  border-color: transparent;
  color: #fff;
  box-shadow: 0 4px 16px -6px rgba(var(--accent-rgb), 0.7);
}

/* --- every card on the surface --------------------------------------- */
.dp-shell .dp-transit-card,
.dp-shell .dp-season,
.dp-shell .dp-sight,
.dp-shell .dp-dine {
  background: var(--dp-card);
  border-color: var(--dp-edge);
}

/* `border-color` above is a SHORTHAND and sets all four sides, so it
   wiped the accent edge .dp-sight is identified by. Restated after it. */
.dp-shell .dp-sight { border-left-color: var(--accent); }

.dp-shell .dp-transit-card h3,
.dp-shell .dp-sight h3,
.dp-shell .dp-dine { color: var(--dp-text); }

.dp-shell .dp-transit-card p,
.dp-shell .dp-season-line { color: var(--dp-text-dim); }

.dp-shell .dp-sec { color: var(--dp-text-faint); }

.dp-shell .dp-months li {
  background: var(--dp-tile);
  color: var(--dp-text-faint);
}

/* The peak months, restated INSIDE the shell. The base rule
   `.dp-months li.is-peak` and `.dp-shell .dp-months li` have identical
   specificity (0,2,1), so the later one wins on source order alone --
   and flipping the shell to white silently un-lit the whole ribbon. */
.dp-shell .dp-months li.is-peak {
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  color: #fff;
}

.dp-shell .dp-tile {
  background: var(--dp-tile);
  border-color: var(--dp-edge-soft);
  color: var(--dp-text);
}

/* --- Tips & FAQ and About, on the same surface ----------------------- */
.dp-shell .dp-block { border-bottom-color: var(--dp-edge); }
.dp-shell .dp-block h2 { color: var(--dp-text-faint); }
.dp-shell .dp-para { color: var(--dp-text-dim); }

.dp-shell .dp-row dt { color: var(--dp-text-faint); }
.dp-shell .dp-row dd { color: var(--dp-text); }

.dp-shell .dp-chips li {
  background: var(--dp-tile);
  border-color: var(--dp-edge-soft);
  color: var(--dp-text);
}

.dp-shell .dp-faq { border-bottom-color: var(--dp-edge); }
.dp-shell .dp-faq summary { color: var(--dp-text); }
.dp-shell .dp-faq .dp-para { color: var(--dp-text-dim); }

@media (max-width: 560px) {
  .dp-shell { padding: 16px; border-radius: 16px; }
}

/* The tab row stays put while a panel scrolls past it (round 122d).
   `top` clears the fixed marketing nav, which measures 76px. The
   negative margins pull the sticky row out to the shell's edges so the
   surface behind it covers the shell's 24px padding -- without them the
   panel's content shows through the gap on either side as it scrolls
   under. destination.js holds the row's viewport position across a tab
   change as well; neither half is sufficient alone (see selectTab). */
.dp-shell .dp-tabs {
  position: sticky;
  /* Flush against the fixed marketing nav, whose height destination.js
     measures into --dp-nav-h (it changes with the nav's scrolled state
     and would be a magic number otherwise). A GAP here is not cosmetic:
     panel content scrolls up through it in the strip between the nav and
     the row, which is exactly what a 12px guess produced. */
  top: var(--dp-nav-h, 76px);
  z-index: 3;
  margin: -24px -24px 4px;
  padding: 24px 24px 10px;
  background: var(--dp-surface);
  border-radius: 20px 20px 0 0;
}

@media (max-width: 560px) {
  .dp-shell .dp-tabs {
    margin: -16px -16px 4px;
    padding: 16px 16px 10px;
    border-radius: 16px 16px 0 0;
  }
}

/* --- ingested content (round 122h) ---------------------------------- */
/* The link a CC BY-SA extract is shown with. Quiet, but never hidden:
   the licence obliges the credit and a reader deserves the source. */
.dp-source {
  margin: 8px 0 0;
  font-size: 13px;
}
.dp-source a { color: var(--accent-ink); font-weight: 600; }

.dp-facts-rows { margin-top: 0; }

/* The credits line at the foot of the Info panel. Every source named
   here requires attribution -- CC0 sources are filtered out server-side
   so this line stays short enough to actually be read. */
.dp-attribution {
  margin: 28px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--dp-edge, var(--border));
  font-size: 12px;
  line-height: 1.6;
  color: var(--dp-text-faint, var(--muted));
}
.dp-attribution a { color: inherit; text-decoration: underline; }
.dp-attribution a:hover { color: var(--accent-ink); }

/* The register's hand-written note, under a MEASURED season range. */
.dp-season-note {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--dp-text-faint, var(--muted));
}
