/* WorldHotels brand fonts, self-hosted from the approved brand-asset files
   (Brand Assets/Fonts) rather than a Google Fonts CDN copy, so we're
   exactly on the approved files — weights limited to what the app actually
   uses (400/500/600/700). Worldly Explorer is the brand's own secondary
   script font ("use as a small graphic accent only, such as a location
   callout, handwritten-style note" — precisely how the napkin illustration
   uses it), replacing the earlier Kalam stand-in now that the real file
   exists. */
@font-face { font-family: 'Inter'; src: url('./fonts/inter/Inter_18pt-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Inter'; src: url('./fonts/inter/Inter_18pt-Medium.ttf') format('truetype'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Inter'; src: url('./fonts/inter/Inter_18pt-SemiBold.ttf') format('truetype'); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Inter'; src: url('./fonts/inter/Inter_18pt-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Worldly Explorer'; src: url('./fonts/worldly-explorer/WorldlyExplorer-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Worldly Explorer'; src: url('./fonts/worldly-explorer/WorldlyExplorer-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; font-display: swap; }

:root {
  /* WorldHotels brand palette (WH_Brand Guidelines_July 2026.pdf, "Brand
     colors"): White/Black primary with Warm Red as the sole accent, Warm
     Gray/Medium Gray as the neutral pair. --coral/--coral-deep keep their
     existing names (set up during the prior red+white pass) rather than
     renaming every reference, but now hold the exact approved Warm Red.
     --coral-deep is a derived darker shade, not a named brand color: the
     guide's own contrast table shows Warm Red on White only passes WCAG AA
     for *large* text (3.27:1) and fails for normal text, matching "Do not
     set paragraphs of body copy in Warm Red" — this darker derivative
     (4.7:1, passes AA normal) is what small red text (labels, captions)
     already used even before this rebrand; only the hex values changed. */
  --paper: #ffffff;
  --paper-deep: #f8f7f3;
  --paper-light: #ffffff;
  --ink: #000000;
  --ink-soft: #796d67;
  --ink-faint: #b1aaa7;
  --coral: #fd4d3d;
  --coral-deep: #e61502;
  --line: rgba(0, 0, 0, .14);
  --shadow: 0 18px 45px rgba(0, 0, 0, .12);
  --display: 'Inter', 'Helvetica Neue', Arial, sans-serif;
  --body: 'Inter', 'Helvetica Neue', Arial, sans-serif;
  --mono: 'Inter', 'Helvetica Neue', Arial, sans-serif;
  --napkin-font: 'Worldly Explorer', 'Segoe Print', 'Bradley Hand', cursive;
  --stage-max: 1210px;
  --map-bg: #ffffff;
}

* { box-sizing: border-box; }

html { min-width: 320px; background: var(--paper); }

body {
  margin: 0;
  min-height: 100vh;
  color: var(--ink);
  background: var(--paper);
  font-family: var(--body);
  transition: background .45s ease, color .45s ease;
}

button, input { font: inherit; }
button { color: inherit; }
button:focus-visible, input:focus-visible { outline: 3px solid var(--coral); outline-offset: 3px; }

.paper-grain {
  position: fixed;
  inset: 0;
  pointer-events: none;
  opacity: .25;
  z-index: 10;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.75' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.08'/%3E%3C/svg%3E");
}

/* padding-bottom here (and at the two responsive overrides below) was
   clearance for the now-hidden .variant-dock — trimmed to a plain page
   margin to match; restore the larger values if the dock comes back. */
.app-shell { min-height: 100vh; overflow: hidden; padding-bottom: 40px; }

.topbar {
  width: min(var(--stage-max), calc(100% - 56px));
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 31px 0 15px;
  border-bottom: 1px solid var(--line);
}
/* Only ever holds the WorldHotels lockup now (contact step only) — see
   render()'s topbar handling in app.js. Hidden the rest of the time, since
   every step after "Start Chat" is meant to read as a plain conversation
   with no persistent brand header. */
.topbar.is-empty { display: none; }
.topbar.has-lockup { justify-content: flex-start; border-bottom: 0; }
/* The approved combined "Welcome to World Hotels" lockup (a single image,
   not our own "Welcome to" text + separate wordmark composition) — always
   left-aligned, per instruction, never centered regardless of viewport. */
.home-lockup { text-align: left; }
.home-lockup-img { display: block; height: clamp(44px, 7.5vw, 62px); width: auto; }

.map-live-dot { width: 7px; height: 7px; display: inline-block; vertical-align: 1px; margin-right: 6px; border-radius: 50%; background: var(--coral); box-shadow: 0 0 0 4px rgba(253, 77, 61, .15); }

.experience { width: min(var(--stage-max), calc(100% - 56px)); margin: 0 auto; }
.stage { min-height: 750px; display: grid; grid-template-columns: minmax(0, 1fr) 220px; gap: 80px; position: relative; padding: 74px 90px 90px 60px; }
.stage-copy { max-width: 760px; width: 100%; }
.back-home { display: inline-flex; align-items: center; gap: 9px; margin: 0 0 31px; padding: 0; border: 0; color: var(--ink-soft); background: transparent; font: 10px var(--mono); letter-spacing: .09em; text-transform: uppercase; cursor: pointer; transition: color .2s ease, transform .2s ease; }
.back-home:hover { color: var(--coral-deep); transform: translateX(-4px); }
.back-home-arrow { color: var(--coral); font-size: 18px; line-height: .6; }
.section-kicker { display: flex; align-items: center; gap: 11px; color: var(--coral-deep); font: 500 10px var(--mono); letter-spacing: .13em; text-transform: uppercase; }
.section-kicker > span:first-child { color: var(--ink); }
.kicker-rule { display: inline-block; width: 42px; height: 1px; background: currentColor; opacity: .45; }
.map-intro-row h1 { margin: 0; font: 600 clamp(48px, 7vw, 87px)/.91 var(--display); letter-spacing: -.07em; }
.lede { max-width: 440px; color: var(--ink-soft); font-size: 16px; line-height: 1.65; margin: 0 0 34px; }
.chat-thread { max-width: 500px; display: grid; gap: 17px; margin: 31px 0 31px 23px; }
.message { display: flex; align-items: flex-start; gap: 11px; }
.message p { margin: 0; }
.message-bot > div, .message-bot > p { max-width: 402px; padding: 15px 18px; border: 1px solid var(--line); border-radius: 3px 18px 18px 18px; background: rgba(248, 247, 243, .63); color: var(--ink); line-height: 1.52; }
/* A "typing…" placeholder shown in a chat bubble while the welcome
   message's weather fetch is still in flight — a bot "composing" moment,
   not a wrong answer that then changes (see welcomeMessageInnerMarkup). */
.typing-dots { display: flex; gap: 4px; padding: 3px 0; }
.typing-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-faint); animation: typing-bounce 1.1s ease-in-out infinite; }
.typing-dots i:nth-child(2) { animation-delay: .15s; }
.typing-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes typing-bounce { 0%, 60%, 100% { transform: translateY(0); opacity: .5; } 30% { transform: translateY(-4px); opacity: 1; } }
.message-small > p { color: var(--ink-soft); font-size: 13px; font-style: italic; background: transparent; border: 0; padding: 4px 1px; }
.message-user { justify-content: flex-end; margin-right: 20px; }
.message-user p { padding: 13px 17px; color: var(--paper-light); background: var(--ink); border-radius: 18px 3px 18px 18px; font-size: 14px; }
.avatar { flex: 0 0 auto; display: grid; place-items: center; width: 28px; height: 28px; margin-top: 3px; border-radius: 50%; color: var(--paper-light); background: var(--coral); font: 700 17px var(--display); }
.avatar-icon { width: 16px; height: 16px; object-fit: contain; }
.avatar-outline { color: var(--coral); background: transparent; border: 1px solid var(--coral); font-size: 13px; }
.message-meta { display: block; margin-bottom: 5px; color: var(--coral-deep); font: 500 9px var(--mono); letter-spacing: .1em; text-transform: uppercase; }
.message-meta span { color: var(--ink-faint); margin-left: 7px; letter-spacing: 0; text-transform: lowercase; }

.property-picker, .category-panel { max-width: 690px; padding: 24px; border: 1px solid var(--line); background: rgba(248, 247, 243, .45); box-shadow: var(--shadow); }
/* Both panels read as chat responses, not form panels — rounded corners on
   the panel itself and each card/field inside it, echoing the chat
   bubbles' own rounded-corner treatment. */
.property-picker, .category-panel { border-radius: 18px; }
.search-label { display: block; color: var(--ink-soft); font: 500 11px var(--mono); letter-spacing: .1em; text-transform: uppercase; }
.search-wrap { display: flex; align-items: center; height: 58px; gap: 11px; margin-top: 11px; padding: 0 15px; border: 1px solid var(--line); border-radius: 14px; background: var(--paper-light); }
.search-icon { color: var(--coral); font-size: 26px; line-height: 1; transform: rotate(-12deg); }
.search-wrap input { flex: 1; min-width: 0; border: 0; outline: 0; color: var(--ink); background: transparent; font-size: 16px; }
.search-wrap input::placeholder { color: var(--ink-faint); }
.search-key { color: var(--ink-faint); font: 10px var(--mono); }
.demo-label, .category-panel-head, .category-panel-foot, .map-card-topline, .map-card-foot, .list-heading, .poi-topline { display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.demo-label { margin: 24px 0 10px; color: var(--ink-faint); font: 10px var(--mono); letter-spacing: .05em; text-transform: uppercase; }
.demo-label span:last-child { color: var(--coral-deep); }
.property-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.property-card { min-height: 153px; padding: 16px 17px 14px; border: 1px solid var(--line); border-radius: 14px; color: var(--ink); background: var(--paper-light); text-align: left; cursor: pointer; transition: transform .2s ease, border-color .2s ease, box-shadow .2s ease; }
.property-card:hover { border-color: var(--coral); box-shadow: 4px 5px 0 rgba(253, 77, 61, .23); transform: translate(-2px, -2px) rotate(-.4deg); }
/* The contact form: a plain form, not styled as chat — "Start Chat" is the
   one moment the whole experience switches over to the chat-bubble
   treatment used everywhere after it. The submit button sits to the side
   (align-self: flex-end) rather than spanning the form, closer to a chat
   app's send button than a full-width form submit. */
.contact-form { display: flex; flex-direction: column; gap: 14px; max-width: 480px; margin-top: 24px; }
.contact-fields { display: flex; flex-wrap: wrap; gap: 11px; }
.contact-fields input { flex: 1 1 160px; }
.contact-form input { min-width: 0; width: 100%; height: 58px; padding: 0 18px; border: 1px solid var(--line); background: var(--paper-light); color: var(--ink); font-size: 16px; }
.contact-form input::placeholder { color: var(--ink-faint); }
.contact-form .primary-button { align-self: flex-end; width: auto; }
.property-card-topline, .property-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.tiny-label, .property-card-foot, .property-card-place { font: 10px var(--mono); letter-spacing: .06em; text-transform: uppercase; }
.tiny-label { color: var(--coral-deep); }
.arrow-mark { color: var(--coral); font-size: 18px; }
.property-card-name { display: block; margin-top: 23px; font: 500 22px var(--display); letter-spacing: -.04em; }
.property-card-place { display: block; margin-top: 4px; color: var(--ink-faint); }
.property-card-foot { margin-top: 27px; color: var(--ink-soft); font-size: 8px; letter-spacing: .04em; }
.no-results { padding: 22px 0; color: var(--ink-soft); font-size: 13px; }

.stage-note { align-self: start; margin-top: 117px; padding: 23px 12px 0 23px; border-top: 1px solid var(--line); color: var(--ink-soft); transform: rotate(2deg); }
.note-pin { position: absolute; width: 9px; height: 9px; left: 9px; top: -5px; border-radius: 50%; background: var(--coral); box-shadow: 0 0 0 5px rgba(253, 77, 61, .12); }
.note-index { color: var(--coral-deep); font: 10px var(--mono); letter-spacing: .08em; text-transform: uppercase; }
.stage-note p { margin: 18px 0 0; font: italic 21px/1.15 var(--display); letter-spacing: -.035em; }
.stage-note strong { color: var(--coral); font-weight: 500; }

.context-strip { display: flex; align-items: center; gap: 9px; margin-top: 35px; color: var(--ink-soft); font: 10px var(--mono); letter-spacing: .06em; text-transform: uppercase; }
.context-mode { margin-left: 5px; padding-left: 11px; border-left: 1px solid var(--line); color: var(--coral-deep); }
.category-lockup { margin-top: 30px; }
.category-panel { margin-top: 31px; }
.category-count { display: block; margin-top: 7px; color: var(--ink-faint); font-size: 12px; }
.category-count strong { color: var(--coral); font: 600 23px var(--display); }
.mode-stamp { padding: 7px 9px; border: 1px solid currentColor; border-radius: 99px; font: 9px var(--mono); letter-spacing: .08em; text-transform: uppercase; }
.stamp-warm { color: var(--coral-deep); }
.stamp-cool { color: #668466; }
.category-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; margin-top: 22px; }
.category-card { position: relative; min-height: 101px; display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; padding: 14px; border: 1px solid var(--line); border-radius: 14px; color: var(--ink); background: var(--paper-light); text-align: left; cursor: pointer; transition: background .2s ease, color .2s ease, transform .2s ease; }
.category-card:hover:not(:disabled) { transform: translateY(-3px) rotate(-.5deg); border-color: var(--coral); }
.category-card.is-selected { color: var(--paper-light); background: var(--ink); border-color: var(--ink); }
.category-card.is-disabled { opacity: .4; cursor: not-allowed; }
.category-icon { color: var(--coral); font-size: 20px; line-height: 1; }
/* var(--paper-light), not --coral, once selected: the card background is
   already --ink (black), and the brand guide explicitly says not to set
   Warm Red on a black background — white keeps the icon legible and
   matches the label text color it already inherits. */
.is-selected .category-icon { color: var(--paper-light); }
.category-name { font-size: 13px; line-height: 1.1; }
.category-check { position: absolute; top: 12px; right: 13px; color: var(--coral); font-size: 18px; }
.is-selected .category-check { color: var(--paper-light); }
.category-panel-foot { margin-top: 25px; color: var(--ink-faint); font: 10px var(--mono); letter-spacing: .03em; }
.primary-button, .secondary-button, .text-button { border: 0; cursor: pointer; transition: transform .2s ease, box-shadow .2s ease, background .2s ease; }
.primary-button { padding: 14px 18px; color: var(--paper-light); background: var(--coral); font-weight: 600; }
.primary-button:hover:not(:disabled) { box-shadow: 4px 4px 0 var(--ink); transform: translate(-2px, -2px); }
.primary-button span, .secondary-button span { margin-left: 12px; font-size: 17px; }
.primary-button.is-disabled, .primary-button:disabled { opacity: .45; cursor: not-allowed; }

.map-intro-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 30px; margin-top: 29px; }
.compact-context { margin-top: 0; margin-bottom: 25px; }
.result-lede { margin-top: 21px; }
.map-card { margin-top: 28px; border: 1px solid var(--line); background: var(--paper-light); box-shadow: var(--shadow); }
.map-card-topline, .map-card-foot { padding: 13px 16px; color: var(--ink-faint); font: 9px var(--mono); letter-spacing: .05em; text-transform: uppercase; }
.map-card-topline { color: var(--ink-soft); border-bottom: 1px solid var(--line); }
.map-card-topline span:last-child { color: var(--coral-deep); }
/*
 * A fixed 1:1 aspect ratio (not a per-breakpoint height) so the napkin is
 * always square, at every viewport width. The pin layout math positions POIs
 * by bearing/distance around a shared center assuming a square coordinate
 * space; a non-square box (e.g. much wider than tall on desktop) distorted
 * that layout differently per device, which also breaks reliably reproducing
 * the same look for print.
 */
.map-illustration { position: relative; aspect-ratio: 1 / 1; overflow: hidden; background: var(--map-bg); box-shadow: 0 1px 1px rgba(0, 0, 0, .05), 0 10px 24px rgba(0, 0, 0, .1); }
.map-illustration-bg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.real-map-shell { position: relative; aspect-ratio: 1 / 1; overflow: hidden; background: #d7e5e8; }
.google-map { position: absolute; inset: 0; }
.real-map-shell::after { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none; background: linear-gradient(112deg, rgba(255,255,255,.22), transparent 36%, rgba(0,59,92,.08)); mix-blend-mode: multiply; }
.real-map-overlay { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.real-map-title { position: absolute; top: 20px; left: 25px; color: var(--ink); font: italic 17px var(--display); text-shadow: 0 1px rgba(255,255,255,.65); transform: rotate(-3deg); }
.real-map-title em { color: var(--coral); }
.real-map-badge { position: absolute; top: 20px; right: 22px; padding: 8px 10px; color: var(--ink-soft); border: 1px solid rgba(0,59,92,.26); border-radius: 99px; background: rgba(251,253,253,.8); font: 9px var(--mono); letter-spacing: .04em; text-transform: uppercase; backdrop-filter: blur(5px); }
.real-map-badge .map-live-dot { width: 6px; height: 6px; margin-right: 5px; }
.real-map-shell .map-caption { color: var(--ink-soft); text-shadow: 0 1px rgba(255,255,255,.7); }
.real-map-status { position: absolute; z-index: 3; left: 50%; top: 50%; padding: 11px 14px; color: var(--ink-soft); border: 1px solid var(--line); background: rgba(251,253,253,.9); font: 10px var(--mono); letter-spacing: .05em; text-transform: uppercase; transform: translate(-50%, -50%); }
.real-map-shell.is-ready .real-map-status { display: none; }
.gm-hotel-marker, .gm-poi-marker { display: flex; align-items: center; gap: 7px; pointer-events: auto; filter: drop-shadow(0 2px 2px rgba(0, 45, 70, .18)); }
.gm-hotel-pin { width: 35px; height: 44px; display: block; overflow: visible; }
.gm-hotel-pin-shape { fill: var(--coral); stroke: rgba(255,255,255,.95); stroke-width: 1.5; }
.gm-hotel-pin-center { fill: #fbfdfd; }
.gm-poi-marker { max-width: 154px; transform: rotate(-2deg); }
.gm-poi-marker > span { flex: 0 0 auto; width: 27px; height: 27px; display: grid; place-items: center; border: 1px solid var(--ink); border-radius: 50% 50% 50% 3px; color: #fff; background: var(--ink); font: 10px var(--mono); }
.gm-poi-marker > b { padding: 5px 7px; color: var(--ink); background: rgba(251,253,253,.88); font: 600 12px/1.05 var(--display); letter-spacing: -.02em; }
.gm-poi-marker-1 > span { background: var(--coral); border-color: var(--coral); }
.gm-poi-marker-2 > span { background: #1d6d83; border-color: #1d6d83; }
.gm-poi-marker-3 > span { background: #c58b1e; border-color: #c58b1e; }
.gm-poi-marker-4 > span { background: #785b8b; border-color: #785b8b; }
.theme-night .real-map-shell { background: #d8e9ea; }
.theme-night .real-map-shell::after { background: linear-gradient(112deg, rgba(0,59,92,.12), transparent 36%, rgba(0,59,92,.16)); }
.theme-night .real-map-title, .theme-night .real-map-badge, .theme-night .gm-poi-marker > b { color: #003b5c; }
.theme-night .real-map-badge { border-color: rgba(0,59,92,.24); background: rgba(251,253,253,.86); }
.map-wash { position: absolute; border-radius: 50%; filter: blur(1px); opacity: .5; }
.wash-one { width: 280px; height: 185px; top: 50px; left: -45px; background: rgba(167, 188, 161, .22); transform: rotate(-18deg); }
.wash-two { width: 360px; height: 170px; right: -98px; bottom: 14px; background: rgba(239, 186, 100, .2); transform: rotate(31deg); }
/* Rounded caps/joins so a road's strokes read as one continuous ballpoint-pen
   line — the default (butt/miter) can look like short stacked rectangles
   wherever a rough.js stroke has a seam or the path bends. */
.map-lines, .map-routes { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; stroke-linecap: round; stroke-linejoin: round; }
.map-route-distance { font: 700 13px var(--napkin-font); fill: var(--coral-deep); stroke: var(--paper-light); stroke-width: 4px; paint-order: stroke; }
.contour { fill: none; stroke: rgba(24, 59, 66, .16); stroke-width: .42; stroke-dasharray: 2 2.4; }
.contour-two { stroke: rgba(189, 84, 72, .16); stroke-dasharray: 3 3; }
.map-route { stroke: rgba(24, 59, 66, .42); stroke-width: .32; stroke-dasharray: 1.4 1.6; }
.route-1 { stroke: var(--coral-deep); }
.route-2 { stroke: #668466; }
.route-3 { stroke: #b18548; }
.route-4 { stroke: #7d688e; }
/* Per feedback: the napkin heading ("Welcome to X, Y") is Inter Semibold — the only
   text on the napkin that isn't the hand-written stand-in font. */
.map-napkin-heading { position: absolute; top: 16px; left: 18px; right: 86px; color: var(--ink); font: 600 15px/1.35 var(--display); }
.map-napkin-heading-name { color: var(--coral-deep); }
/* The approved WorldHotels logo (thickened variant — drawn specifically for
   legibility at small sizes, per the brand guide's "small logo" guidance)
   in the napkin's bottom-right corner. */
.map-logo-lockup { position: absolute; right: 14px; bottom: 14px; width: 86px; height: 32px; }
.map-logo-lockup-img { display: block; width: 100%; height: 100%; object-fit: contain; object-position: right center; }
/* Napkin texture — the only "added design" the background should carry,
   per user feedback: a seamless embossed diamond/quilt pattern plus a
   fine paper-fiber grain (textures/napkin-grain.svg — one reusable file, an
   SVG pattern/filter so it stays crisp at any illustration size rather than
   tiling/stretching like a raster texture would), not just a flat
   background color. */
.map-illustration::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .32;
  mix-blend-mode: multiply;
  background-image: url("./textures/napkin-grain.svg");
  background-size: 100% 100%;
}
.hotel-marker { position: absolute; width: max-content; display: flex; align-items: center; gap: 8px; transform: translate(-15px, -50%); }
.hotel-marker-ring { width: 30px; height: 30px; display: grid; place-items: center; border: 2px solid var(--coral); border-radius: 50%; box-shadow: 0 0 0 7px rgba(253, 77, 61, .12); background: rgba(248, 247, 243, .7); }
.hotel-marker-icon { width: 17px; height: 17px; color: var(--coral); }
.hotel-marker-label { color: var(--ink-soft); font: 13px/1.15 var(--napkin-font); transform: rotate(-2deg); }
.hotel-marker-label strong { display: block; color: var(--coral); font: 700 17px var(--napkin-font); overflow-wrap: anywhere; }
/*
 * width: max-content is load-bearing here, not decorative: a position:absolute
 * flex box with only `left` set (no `right`/`width`) has its shrink-to-fit
 * width capped by the distance from that `left` point to the containing
 * block's right edge, regardless of max-width. A pin placed far enough right
 * gets squeezed into a tiny available width, and the label (overflow-wrap:
 * anywhere) would collapse to near-zero and wrap one letter per line. Forcing
 * width to the content's natural size (still bounded by max-width) prevents
 * that regardless of where the pin lands.
 */
.map-pin { position: absolute; display: flex; align-items: center; gap: 6px; width: max-content; max-width: 170px; transform: translate(-50%, -50%); }
/* mapMarkup() picks this when a pin's own road approaches from its right —
   the default right-side label would sit right where that road runs. */
.map-pin.label-below { flex-direction: column; }
.map-pin.label-below b { text-align: center; }
/* No more pin badge shape (circle/border/fill) — just the category icon
   itself, sized up now that it isn't being squeezed into a small circle.
   Numbered fallback badges (categories with no icon yet) lose the shape
   too, for one consistent look either way; the bare number is sized up to
   compensate for the missing circle around it. */
.map-pin > span { position: relative; flex: 0 0 auto; display: grid; place-items: center; width: 40px; height: 40px; color: var(--ink); font: 700 20px var(--mono); transform: rotate(-7deg); }
.pin-icon { width: 40px; height: 40px; object-fit: contain; }
.map-pin b { color: var(--ink); font: 700 15px/1.05 var(--napkin-font); transform: rotate(-2deg); overflow-wrap: anywhere; }
/* A liked POI (thumbs-up in review) gets a small heart badge on its final
   mapkin pin — thumbs-down already swaps the spot out entirely, so this is
   the only rating that needs to survive onto the printed/downloaded map. */
.pin-heart { position: absolute; top: -11px; right: -11px; width: 20px; height: 20px; display: grid; place-items: center; border-radius: 50%; color: var(--paper-light); background: var(--coral); font-size: 12px; font-style: normal; line-height: 1; box-shadow: 0 0 0 2px var(--paper-light); }
.compass { position: absolute; right: 27px; top: 22px; width: 32px; height: 49px; color: var(--ink-soft); text-align: center; }
.compass-n { font: 11px var(--mono); }
.compass-line { position: absolute; top: 20px; left: 15px; width: 1px; height: 26px; background: var(--coral); transform: rotate(29deg); transform-origin: top; }
.compass-dot { position: absolute; top: 19px; left: 12px; width: 7px; height: 7px; border-radius: 50%; background: var(--coral); }
.map-caption { position: absolute; bottom: 17px; left: 20px; color: var(--ink-soft); font: 14px var(--napkin-font); }
.map-location-note { position: absolute; right: 20px; bottom: 17px; color: var(--coral-deep); font: 9px var(--mono); letter-spacing: .06em; text-transform: uppercase; }
.map-card-foot { border-top: 1px solid var(--line); }
.poi-list { margin-top: 30px; }
.list-heading { margin: 0; padding-bottom: 10px; color: var(--ink-soft); font: 10px var(--mono); letter-spacing: .1em; text-transform: uppercase; }
.list-heading span:first-child { color: var(--coral-deep); }
.poi-card { display: grid; grid-template-columns: 36px 1fr; gap: 10px; align-items: start; padding: 18px 0; border-top: 1px solid var(--line); }
.poi-rate { display: flex; gap: 8px; margin-top: 14px; }
.poi-rate-button { width: 38px; height: 38px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 50%; background: var(--paper-light); font-size: 16px; line-height: 1; cursor: pointer; transition: transform .15s ease, border-color .15s ease, background .15s ease; }
.poi-rate-button:hover { border-color: var(--coral); transform: translateY(-2px); }
.poi-rate-button.is-active { background: var(--coral); border-color: var(--coral); }
.poi-number { color: var(--coral-deep); font: 17px var(--display); }
.poi-topline { color: var(--ink-faint); font: 9px var(--mono); letter-spacing: .06em; text-transform: uppercase; }
.poi-category { color: var(--coral-deep); }
.poi-direction { color: var(--ink-soft); }
.poi-card h3 { margin: 4px 0 4px; font: 500 22px var(--display); letter-spacing: -.035em; }
.poi-card p { max-width: 530px; margin: 0; color: var(--ink-soft); font-size: 13px; line-height: 1.5; }
/* "Local tip" signature element (brand guide, Signature elements): warm-gray
   background as the "calm, elevated canvas" the guide describes for
   grouping curated content, one small moment of red for the accent border,
   and the brand's own dedicated "Local tip" icon (Brand Assets/Icons —
   cropped directly from the approved icon sheet, not redrawn). */
.poi-tip { max-width: 530px; margin-top: 10px; padding: 10px 12px; border-left: 2px solid var(--coral); background: var(--paper-deep); border-radius: 0 3px 3px 0; }
.poi-tip-label { display: flex; align-items: center; gap: 5px; margin-bottom: 3px; color: var(--coral-deep); font: 600 9px var(--mono); letter-spacing: .08em; text-transform: uppercase; }
.poi-tip-icon { width: 12px; height: 12px; object-fit: contain; }
.poi-tip p { margin: 0; max-width: none; color: var(--ink); font: italic 500 13px/1.5 var(--display); }
.poi-arrow { color: var(--coral); font-size: 20px; }
.result-actions { display: flex; gap: 11px; margin-top: 22px; }
.secondary-button { padding: 14px 18px; border: 1px solid var(--ink); color: var(--ink); background: transparent; font-weight: 600; }
.secondary-button:hover { color: var(--paper-light); background: var(--ink); transform: translateY(-2px); }
.start-over { display: block; margin: 25px auto 0; border: 0; color: var(--ink-soft); background: transparent; font: 11px var(--mono); cursor: pointer; }
.start-over:hover, .text-button:hover { color: var(--coral-deep); }
.notice { margin-top: 17px; padding: 10px 13px; border-left: 2px solid var(--coral); color: var(--ink-soft); background: rgba(253, 77, 61, .08); font-size: 12px; }
.notice--success { border-left-color: #1f9254; background: rgba(31, 146, 84, .08); }
.notice--pending { border-left-color: var(--ink-faint); background: rgba(0, 0, 0, .04); }
.empty-map { min-height: 300px; display: grid; place-items: center; align-content: center; gap: 10px; color: var(--ink-soft); text-align: center; }
.empty-map > span { color: var(--coral); font-size: 28px; }
.empty-map p { margin: 0; font: italic 21px var(--display); }
.text-button { padding: 4px; color: var(--coral-deep); background: transparent; font: 11px var(--mono); }
.loading-state { min-height: 680px; display: grid; place-content: center; justify-items: center; color: var(--ink-soft); }
.loading-mark { color: var(--coral); font-size: 30px; animation: spin 1.6s linear infinite; }
.loading-state p { font: italic 20px var(--display); }

/* Hidden, not removed, per instruction — "field notes" (the default ink
   theme) is the only one in use; "roadside"/"after hours" aren't needed
   right now. Flip this back to `display: flex` (the rest of the rule,
   responsive overrides included, is untouched) to bring the picker back. */
.variant-dock { position: fixed; z-index: 20; bottom: 22px; left: 50%; display: none; align-items: center; gap: 18px; padding: 8px 10px 8px 17px; border: 1px solid var(--line); border-radius: 4px; color: var(--ink-soft); background: rgba(248, 247, 243, .88); box-shadow: 0 8px 28px rgba(0, 0, 0, .14); backdrop-filter: blur(15px); transform: translateX(-50%); }
.dock-label { font: 9px var(--mono); letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; }
.variant-buttons { display: flex; gap: 4px; }
.variant-button { display: inline-flex; align-items: center; gap: 7px; padding: 9px 10px; border: 0; border-radius: 2px; color: var(--ink-soft); background: transparent; font: 10px var(--mono); cursor: pointer; transition: background .2s ease, color .2s ease; }
.variant-button:hover, .variant-button.is-active { color: var(--ink); background: var(--paper-deep); }
.variant-swatch { width: 11px; height: 11px; display: inline-block; border-radius: 50%; border: 1px solid currentColor; }
.swatch-ink { background: var(--coral); }
.swatch-sunset { background: #ef9662; }
.swatch-night { background: #dcbb77; }

.message-enter { animation: enter .6s both; }
.message-enter-2 { animation-delay: .1s; }
.panel-enter { animation: panel-enter .75s both; animation-delay: .16s; }
@keyframes enter { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
@keyframes panel-enter { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
@keyframes spin { to { transform: rotate(360deg); } }

/* Art direction: roadside / sun-washed motel postcard. */
.theme-sunset { --paper: #fff3f1; --paper-deep: #f6c9c4; --paper-light: #fffdfc; --ink: #241f1f; --ink-soft: #5b5252; --ink-faint: #8a7f7f; --coral: #d9272e; --coral-deep: #a91e28; --line: rgba(169, 30, 40, .18); --shadow: 0 18px 45px rgba(120, 20, 20, .13); --map-bg: #fdfaf6; }
.theme-sunset .map-intro-row h1 { letter-spacing: -.085em; }
.theme-sunset .topbar { border-bottom-style: dashed; }
.theme-sunset .property-card:hover { box-shadow: 4px 5px 0 rgba(229, 163, 73, .32); }
.theme-sunset .wash-one { background: rgba(135, 170, 160, .25); }
.theme-sunset .wash-two { background: rgba(221, 101, 79, .16); }
.theme-sunset .variant-dock { background: rgba(255, 246, 233, .9); }

/* Art direction: after hours / a small, dark hotel lobby map. */
.theme-night { --paper: #260c0c; --paper-deep: #431515; --paper-light: #341010; --ink: #fbecec; --ink-soft: #dcb9b9; --ink-faint: #b99696; --coral: #f0444b; --coral-deep: #ff7a78; --line: rgba(251, 236, 236, .2); --shadow: 0 20px 50px rgba(0, 0, 0, .4); --map-bg: #2b1414; }
.theme-night .paper-grain { mix-blend-mode: screen; opacity: .09; }
.theme-night .message-bot > div, .theme-night .message-bot > p, .theme-night .property-picker, .theme-night .category-panel { background: rgba(33, 59, 63, .73); }
.theme-night .property-card, .theme-night .category-card, .theme-night .map-card { background: var(--paper-light); }
.theme-night .message-user p { color: var(--paper); background: var(--coral); }
.theme-night .wash-one { background: rgba(145, 177, 156, .18); }
.theme-night .wash-two { background: rgba(227, 155, 101, .18); }
.theme-night .hotel-marker-ring { background: rgba(33, 59, 63, .8); }
.theme-night .map-pin b, .theme-night .map-napkin-heading { color: var(--paper); }
.theme-night .map-card-topline, .theme-night .map-card-foot { color: var(--ink-soft); }
.theme-night .variant-dock { background: rgba(33, 59, 63, .92); }
.theme-night .variant-button:hover, .theme-night .variant-button.is-active { background: var(--paper-deep); }

/*
 * Mobile-first responsive layout.
 * Everything below (outside a media query) is the default/smallest-viewport
 * layout. `min-width: 681px` layers on the compact-tablet look, and
 * `min-width: 901px` layers on the full desktop look on top of that.
 */

.app-shell { padding-bottom: 40px; }
.topbar, .experience { width: min(100% - 32px, 560px); }
.topbar { padding-top: 21px; }
.stage { display: block; min-height: auto; padding: 49px 0 65px; }
.stage-note { display: none; }
.back-home { margin-bottom: 27px; }
.map-intro-row h1 { font-size: clamp(48px, 15vw, 75px); }
.chat-thread { margin-left: 0; }
.property-picker, .category-panel { padding: 17px; }
.property-grid { grid-template-columns: 1fr; }
.property-card { min-height: 138px; }
.property-card-name { margin-top: 18px; }
.property-card-foot { margin-top: 20px; }
.category-grid { grid-template-columns: 1fr 1fr; }
.category-card { min-height: 93px; }
.category-panel-foot { align-items: flex-end; }
.category-panel-foot > span { max-width: 115px; line-height: 1.4; }
.category-panel-foot .primary-button { padding: 12px 13px; }
.map-intro-row { margin-top: 22px; }
.map-pin { max-width: 130px; }
.map-pin b { font-size: 13px; }
.hotel-marker-label { max-width: 130px; font-size: 14px; }
.map-card-topline, .map-card-foot { align-items: flex-start; flex-direction: column; gap: 5px; }
.map-location-note { right: 20px; bottom: 39px; }
.result-actions { flex-direction: column; }
.primary-button, .secondary-button { width: 100%; }
.variant-dock { bottom: 14px; width: calc(100% - 28px); justify-content: space-between; padding: 8px; }
.dock-label { display: none; }
.variant-buttons { flex: 1; justify-content: space-between; }
.variant-button { flex: 1; justify-content: center; padding: 9px 5px; font-size: 9px; }

@media (min-width: 681px) {
  /* Compact tablet: two-column stage returns, but narrower than full desktop. */
  .app-shell { padding-bottom: 40px; }
  .topbar, .experience { width: min(var(--stage-max), calc(100% - 56px)); }
  .topbar { padding-top: 31px; }
  .stage { display: grid; min-height: 750px; grid-template-columns: minmax(0, 1fr) 150px; gap: 35px; padding: 64px 0 85px; }
  .stage-note { display: block; margin-top: 100px; }
  .back-home { margin-bottom: 31px; }
  .map-intro-row h1 { font-size: clamp(48px, 7vw, 87px); }
  .chat-thread { margin-left: 23px; }
  .property-picker, .category-panel { padding: 24px; }
  .property-grid { grid-template-columns: 1fr 1fr; }
  .property-card { min-height: 153px; }
  .property-card-name { margin-top: 23px; }
  .property-card-foot { margin-top: 27px; }
  .category-grid { grid-template-columns: repeat(3, 1fr); }
  .category-card { min-height: 101px; }
  .category-panel-foot { align-items: center; }
  .category-panel-foot > span { max-width: none; line-height: normal; }
  .category-panel-foot .primary-button { padding: 14px 18px; }
  .map-intro-row { margin-top: 29px; }
  .map-pin { max-width: 170px; }
  .map-pin b { font-size: 15px; }
  .hotel-marker-label { max-width: 170px; font-size: 14px; }
  .map-card-topline, .map-card-foot { align-items: center; flex-direction: row; gap: 20px; }
  .map-location-note { right: 20px; bottom: 17px; }
  .result-actions { flex-direction: row; }
  .primary-button, .secondary-button { width: auto; }
  .variant-dock { bottom: 22px; width: auto; justify-content: flex-start; padding: 8px 10px 8px 17px; }
  .dock-label { display: inline; }
  .variant-buttons { flex: initial; justify-content: flex-start; }
  .variant-button { flex: initial; justify-content: flex-start; padding: 9px 10px; font-size: 10px; }
}

@media (min-width: 901px) {
  /* Full desktop: wider aside column and roomier spacing. */
  .stage { grid-template-columns: minmax(0, 1fr) 220px; gap: 80px; padding: 74px 90px 90px 60px; }
  .stage-note { margin-top: 117px; }
}

@media print {
  * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; color-adjust: exact !important; }
  @page { margin: 0.4in; }
  body { background: white; }
  .paper-grain, .topbar, .variant-dock, .stage-note, .back-home, .section-kicker, .context-strip, .map-intro-row, .result-lede, .map-card-topline, .map-card-foot, .poi-list, .result-actions, .start-over, .notice { display: none !important; }
  .app-shell { padding-bottom: 0; }
  .experience { width: 100%; }
  .stage { display: block; min-height: auto; padding: 0; }
  .stage-copy { max-width: none; }
  .map-card { margin: 0; border: 0; box-shadow: none; }
  .map-illustration { page-break-inside: avoid; }
}
