/* ==========================================================================
   HHI App Prototype — Shared Styles
   Fidelity: REAL BRAND PASS. Tokens below are pulled from the live
   hiltonheadisland.org theme (see css/tokens-hiltonheadisland.css for full
   provenance/frequency counts) — this replaced the earlier lo-fi grayscale
   placeholder set in a one-file swap, exactly as this file's structure was
   always meant to allow. Every component still reads through these
   variables, never a hardcoded value, so any future retune is this section
   only.

   Fonts: Meta Serif Pro and Noah are licensed by the client and installed
   locally via Font Book on the machines actively designing this — they're
   referenced BY NAME ONLY below, never embedded as files or data URIs in
   this repo (that would redistribute a licensed commercial font through
   git). Rendered correctly wherever those fonts are installed; falls back
   to the named system stack everywhere else, same as any web font
   fallback. Faustine (the brand's script accent) is deliberately NOT
   referenced anywhere in this file for the same licensing reason — it's
   only ever shown as a labeled Google-Fonts stand-in on the token/comps
   artifacts, never inside the actual prototype. ---- */

:root {
  --font-heading: "Meta Serif Pro", Georgia, "Times New Roman", serif;
  --font-body: "Noah", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --font-button: "Noah", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --tracking-button: 0.15em;

  /* ---- Colors — real Hilton Head Island brand palette ---- */
  --color-black: #0A1618;      /* Ink — replaces pure black as the brand's near-black */
  --color-white: #FFFFFF;
  --color-gray-100: #F2F2F2;
  --color-gray-200: #E6E6E6;
  --color-gray-300: #E0E0E0;
  --color-gray-500: #9A9A9A;
  --color-gray-700: #757575;
  --color-gray-800: #585858;
  --color-gray-900: #1A3827;   /* Pine — deep brand green, replaces near-black neutral gray */
  --color-text: #0A1618;       /* Ink */
  --color-text-muted: #585858;
  --color-placeholder-fill: #C9E1BD;      /* Palmetto Pale */
  --color-placeholder-fill-dark: #468663; /* Palmetto */

  --color-paper: #F9F8F7;      /* warm off-white ground, used in place of pure white on real surfaces */
  --color-accent: #468663;     /* Palmetto — primary brand accent (links, active icons) */
  --color-accent-dark: #1A3827;/* Pine */
  --color-dune: #F4DAA6;
  --color-gold: #E09600;
  --color-ember: #E62600;
  --color-lagoon: #0094F0;
  --color-lagoon-dark: #007ECC;

  /* ---- Status accent (dev/QA views only, not real UI) ---- */
  --color-flag: #0A1618;
  --color-flag-bg: #F4DAA6;    /* Dune — reads as an annotation, not an error */

  /* ---- Type scale ---- */
  --text-heading-xl: 34px;
  --text-heading-l: 26px;
  --text-heading-m: 22px;
  --text-heading-s: 20px;
  --text-body: 16px;
  --text-body-tight: 15px;
  --text-label: 13px;
  --text-caption: 11px;

  /* ---- Spacing scale ---- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 16px;
  --space-4: 24px;
  --space-5: 32px;
  --space-6: 40px;

  /* ---- Device frame ---- */
  --device-width: 390px;
  --device-height: 844px;
  --nav-height: 56px;

  /* ---- Misc — radii now match the real site's own scale (a near-flat 3px
     default corner, 10px medium, 20px on cards) instead of the tighter
     wireframe-era values ---- */
  --radius-s: 3px;
  --radius-m: 10px;
  --radius-l: 20px;
  --radius-pill: 9999px;

  /* ---- Shadows — new; the wireframe had none ---- */
  --shadow-card: 0 4px 8px rgba(10, 22, 24, 0.12);
  --shadow-overlay: 0 0 10px rgba(0, 0, 0, 0.5);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: #d8d8d8; /* outer canvas behind the phone frame, so multiple screens tile nicely when opened side by side */
  font-family: var(--font-body);
  color: var(--color-text);
}
html {
  /* Without a viewport meta tag AND this, mobile browsers silently boost
     font size in narrow flex/nowrap elements (their "readability" auto-zoom)
     — that's what was squashing/overlapping the chip labels on a phone.
     Both this and the <meta name="viewport"> tag in every <head> are needed;
     this is the CSS half of that fix. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* ---- Dev-only index/QA chrome (not part of the app itself) ---- */
.dev-bar {
  max-width: var(--device-width);
  margin: 0 auto;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--color-gray-700);
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.dev-bar a { color: var(--color-gray-800); text-decoration: none; }
.dev-bar a:hover { text-decoration: underline; }

/* ---- Responsive phone-frame scaling ----
   Every screen except the hub list (index.html, flagged with the
   .hub-index body class below) wraps its content in the fixed 390x844
   .device mockup, with its own 8px border and 24px top/bottom margin,
   under a dev-bar and above a caption paragraph. On a laptop-height
   browser window — or anything narrower/shorter than that whole fixed
   stack — the page used to run off the bottom or side, forcing a scroll
   just to see the whole phone: exactly the "I can't see all of it"
   reaction this is meant to head off, without the client ever clocking
   that it's a deliberate device-width mock rather than a bug.
   `zoom` (not `transform: scale`) is used on purpose: it reflows the box
   model, so the page's rendered height actually shrinks to match —
   dev-bar, phone, and caption all scale down together and the layout
   collapses accordingly, instead of only the pixels scaling visually
   while the old, larger blank space stays reserved underneath.
   The 32px/90px budgets below are generous, worst-case estimates for the
   browser's own scrollbar plus the dev-bar above the phone (which varies
   per screen and can't be measured from CSS) — not a precise fit, but
   comfortably safe across every real screen in this prototype. The
   .notes aside (see below) deliberately isn't part of this budget at
   all: it's absolutely positioned off to the side, so it has no effect
   on the page's rendered height or width to begin with.
   Never scales up past 1 (`min(...)`): a small window shrinks the mock;
   a large one always shows it at its real, designed size. The plain
   `zoom: 1` first is a safe fallback for any browser that can't parse
   the calc() below — an invalid declaration is dropped, not applied, so
   that line is what's left standing instead of an unscaled phone just
   vanishing or erroring. */
body:not(.hub-index) {
  zoom: 1;
  zoom: min(
    1,
    calc((100vw - 32px) / 406px), /* 406 = 390 device width + 16px border */
    calc((100vh - 90px) / 908px)  /* 908 = 844 device height + 16px border + 24px top/bottom margin */
  );
}
.flag {
  display: inline-block;
  background: var(--color-flag-bg);
  color: var(--color-flag);
  border: 1px solid var(--color-flag);
  border-radius: var(--radius-m);
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-left: var(--space-2);
}

/* ---- Side notes ----
   The dev/QA caption that used to sit directly below the phone (a plain
   <p>, centered under it, one per screen) added its own height to the
   page on top of the phone's — often several lines, varying screen to
   screen, which is exactly the kind of text-length-dependent height the
   zoom rule above can't account for. It's now a .notes aside, positioned
   off to the right of the phone instead of stacked beneath it.
   .device-wrap is a plain, tight-fitting box around .device (position:
   relative, width:fit-content, so it's exactly the phone's own footprint,
   nothing more) — that's what .notes is positioned against. Giving .notes
   position:absolute is what actually keeps it out of the page's layout:
   an absolutely positioned box is removed from normal flow entirely, so
   it contributes no height to .device-wrap (nothing pushes the page
   taller) and no width either (nothing can widen the zoom calculation's
   406px phone-only budget above) — it simply floats in the gray gutter
   beside the phone. On a narrow window it may run past the edge of that
   gutter; that's an acceptable trade real estate for keeping the phone
   itself always fully visible, which is the one thing clients actually
   judge the prototype by. */
.device-wrap {
  position: relative;
  width: fit-content;
  margin: 0 auto;
}
.notes {
  position: absolute;
  top: 0;
  left: 100%;
  width: 260px;
  margin-left: var(--space-4);
  text-align: left;
  font-family: var(--font-body);
  font-size: 11px;
  line-height: 1.5;
  color: var(--color-gray-700);
}
.notes p { margin: 0 0 var(--space-2); }
.notes p:last-child { margin-bottom: 0; }

/* ---- Phone frame ----
   Fixed height (not min-height) is what makes .screen's overflow-y:auto do
   real work: content scrolls INSIDE a phone-sized viewport instead of
   stretching the whole frame to fit. Important: .nav-bar (and, on Explore,
   .snackbar-area) must be siblings of .screen INSIDE .device, never children
   OF .screen — an element inside a scrolling box scrolls away with the
   content even if it's position:absolute, so a nav bar placed inside .screen
   would ride up out of view as soon as content overflows. Keeping them
   outside .screen but inside .device (which doesn't scroll) is what makes
   the nav read as "stuck" to the bottom of the phone while content scrolls
   underneath it. */
.device {
  width: var(--device-width);
  height: var(--device-height);
  margin: var(--space-4) auto;
  background: var(--color-white);
  border-radius: 36px;
  border: 8px solid #1a1a1a;
  overflow: hidden;
  position: relative;
  box-shadow: 0 12px 32px rgba(0,0,0,0.18);
  display: flex;
  flex-direction: column;
}
.status-bar {
  height: 34px;
  background: var(--color-white);
  flex-shrink: 0;
}
.screen {
  flex: 1;
  min-height: 0; /* the flexbox fix: without this, a flex item that's also a
    flex container won't shrink below its content's natural height, so
    overflow-y:auto never actually gets a bounded box to scroll inside —
    this is what broke scrolling and pushed the nav off-screen. */
  display: flex;
  flex-direction: column;
  position: relative;
  overflow-y: auto;
  scrollbar-width: none; /* Firefox: keep scroll, hide the bar itself */
  /* Slightly darker than pure white so white cards and the white nav bar
     read as distinct surfaces sitting on top of it, instead of everything
     blending into one flat white plane. */
  background: var(--color-paper);
}
.screen::-webkit-scrollbar { display: none; } /* Chrome/Safari: same */
.screen.dark { background: var(--color-black); color: var(--color-white); }

/* ---- Bottom nav ----
   A normal (non-absolute) flex item, placed as the LAST CHILD OF .device —
   a sibling of .screen, not nested inside it. That's what keeps it visually
   pinned to the bottom of the phone while .screen scrolls independently
   above it; see the note on .device above.
   Rebuilt to read closer to a real iOS/Material tab bar: shorter overall
   (--nav-height dropped from 78px to 56px, in line with iOS's ~49pt bar and
   Material's 56dp content height), a light ground with a hairline top
   border instead of a solid dark fill, real icon glyphs instead of flat
   color swatches, and no vertical divider lines — stock tab bars space
   items evenly on their own, dividers just added visual noise. The active
   state was previously almost invisible (every item was already white text
   on the dark fill; only a subtle icon-swatch shade told them apart) — now
   the active item gets a distinctly darker color AND a heavier weight, on
   top of the icon change, so it reads at a glance the way a real tab bar's
   selected-vs-unselected state does. */
.nav-bar {
  flex-shrink: 0;
  height: var(--nav-height);
  background: var(--color-white);
  border-top: 1px solid var(--color-gray-200);
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  padding: 0 var(--space-2);
}
.nav-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  text-decoration: none;
  color: var(--color-gray-500);
  font-family: var(--font-button);
  font-size: 10px;
  font-weight: 400; /* lighter weight reads calmer/more premium than the
    previous 600–700 — uppercase+bold together felt heavy and a bit
    "badge"-like rather than refined. */
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.nav-item .nav-icon {
  width: 24px; height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* No background/border here — the icon glyph itself (currentColor SVG)
     is the whole visual; a filled swatch behind it was the old (now
     removed) treatment. */
}
.nav-item .nav-icon svg { width: 22px; height: 22px; }
.nav-item.active { color: var(--color-text); font-weight: 600; }

/* ---- Site header / logo (every "our own" screen, links back to the landing) ---- */
.site-header {
  display: block;
  text-align: center;
  text-decoration: none;
  color: inherit;
  padding: var(--space-3) var(--space-3) var(--space-2);
  flex-shrink: 0;
}
.site-header-logo {
  font-family: var(--font-button);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ---- Headings / text ---- */
.page-title {
  font-family: var(--font-heading);
  font-size: var(--text-heading-l);
  font-weight: 400;
  text-align: center;
  margin: 0 0 var(--space-1);
}
.page-subhead {
  font-family: var(--font-button);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  text-align: center;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-4);
}
.header-block {
  flex-shrink: 0;
  padding: var(--space-3) var(--space-3) var(--space-3);
  text-align: center;
}
.back-link {
  display: inline-block;
  font-family: var(--font-button);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  text-decoration: none;
  color: inherit;
  padding: var(--space-3);
}

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-button);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius-m);
  padding: var(--space-2) var(--space-3);
  border: none;
  cursor: pointer;
}
.btn-dark { background: var(--color-gray-800); color: var(--color-white); }
.btn-outline { background: transparent; color: var(--color-text); border: 1px solid var(--color-text); }
.btn-block { display: flex; width: 100%; }

/* ---- Cards / placeholders ---- */
.placeholder-block {
  background: var(--color-placeholder-fill-dark);
  color: var(--color-white);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-card);
  padding: var(--space-4) var(--space-3);
}
.placeholder-block .item-title {
  font-family: var(--font-heading);
  font-size: var(--text-heading-s);
  margin: 0 0 var(--space-1);
}
.placeholder-block .item-caption {
  font-family: var(--font-button);
  font-size: var(--text-caption);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin: 0;
  opacity: 0.9;
}

.section-label {
  font-family: var(--font-button);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  margin: 0 0 var(--space-2);
  padding: 0 var(--space-3);
}

.chip-row {
  display: flex;
  flex-shrink: 0; /* .chip-row is a flex item inside .screen's column flex —
    without this it's eligible to compress if .screen's content runs tall
    (e.g. a long masonry grid below it), which is what read as "squished"
    the second time around. */
  align-items: center;
  gap: var(--space-2);
  overflow-x: auto;
  padding: 0 var(--space-3) var(--space-3);
  scrollbar-width: none; /* Firefox: keep scroll, hide the bar itself — same
    fix as .screen. This one was missed earlier: on a system set to always
    show scrollbars, the visible horizontal bar sat right under the chips
    and ate into their padding, which is what read as "squished." */
}
.chip-row::-webkit-scrollbar { display: none; } /* Chrome/Safari: same */
.chip {
  flex-shrink: 0;
  cursor: pointer;
  border: none;
  font-family: var(--font-button);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-l);
  background: var(--color-gray-300);
  color: var(--color-text);
  white-space: nowrap;
}
.chip.active { background: var(--color-gray-800); color: var(--color-white); }

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
  padding: 0 var(--space-3) var(--space-4);
}

/* ---- Masonry variant (Memories) ----
   A real CSS Grid, not the CSS-columns trick tried earlier — columns
   reflowed items top-to-bottom-per-column, which read as ragged and
   unbalanced rather than deliberate. This instead fixes a row unit
   (--masonry-row) and lets each card span 2 or 3 of those rows while
   staying exactly 1 column wide, so every card lines up on the same grid
   instead of floating at an arbitrary height. grid-auto-flow:dense fills
   gaps left by shorter neighbors instead of leaving holes. Every card is
   at least .span-2 (short) now; add .span-3 for a tall one — there's no
   1-row size any more. */
.grid-masonry {
  --masonry-row: 79px; /* row unit halved again this round (was 157px) */
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: var(--masonry-row);
  grid-auto-flow: row dense;
  gap: var(--space-2);
  padding: 0 var(--space-3) var(--space-4);
}
.grid-masonry .card-link.span-2 { grid-row: span 2; }
.grid-masonry .card-link.span-3 { grid-row: span 3; }
.grid-masonry .placeholder-block { height: 100%; }

.tag-pill {
  display: inline-block;
  background: var(--color-gray-300);
  color: var(--color-gray-800);
  font-family: var(--font-button);
  font-size: var(--text-caption);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border-radius: var(--radius-m);
  padding: var(--space-1) var(--space-2);
}

.card-link { text-decoration: none; color: inherit; display: block; }
button.card-link { background: none; border: none; padding: 0; margin: 0; font: inherit; text-align: left; width: 100%; height: 100%; cursor: pointer; }

/* ---- Category placeholder "photo" gradients ----
   Standing in for real photography (not supplied yet) across both the
   Offer and Memory cards below — a brand-toned duotone per category reads
   as "designed" rather than a flat missing-image swatch. Swap each for a
   real photo whenever the client supplies one; nothing else about either
   card component needs to change. */
.ph-dining    { background: linear-gradient(135deg, var(--color-gold), var(--color-ember)); }
.ph-shopping  { background: linear-gradient(135deg, var(--color-lagoon), var(--color-accent-dark)); }
.ph-spa       { background: linear-gradient(135deg, var(--color-placeholder-fill), var(--color-accent)); }
.ph-golf      { background: linear-gradient(135deg, var(--color-accent), var(--color-accent-dark)); }
.ph-play      { background: linear-gradient(135deg, var(--color-dune), var(--color-gold)); }
.ph-arts      { background: linear-gradient(135deg, var(--color-ember), var(--color-black)); }
.ph-sound     { background: linear-gradient(135deg, var(--color-accent-dark), var(--color-accent)); }
.ph-sights    { background: linear-gradient(135deg, var(--color-lagoon), var(--color-black)); }
.ph-video     { background: linear-gradient(135deg, var(--color-black), var(--color-accent)); }
.ph-souvenirs { background: linear-gradient(135deg, var(--color-dune), var(--color-gold)); }

/* ---- Offer card ("Photo-led editorial" — picked from the card-options
   comps), revised for legibility: nothing sits on top of the photo except
   a small opaque category pill (top-left) — the previous version put the
   deal headline directly on the image over a scrim, which read as hard to
   read against busy/bright photos. The headline and business name now
   both live in a plain footer strip below the image instead. Every text
   size here is pushed down about as far as it can go while staying
   legible — a 9–12px range — since contrast (Ink-on-white/Ink-on-white-pill)
   is already comfortably past WCAG AA on its own, so size was the only
   remaining lever for "hard to read". */
.offer-card {
  display: block;
  border-radius: var(--radius-s);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  background: var(--color-white);
}
.offer-card-media { position: relative; height: 132px; background-size: cover; background-position: center; }
.offer-card-tag-pill {
  position: absolute; top: var(--space-2); left: var(--space-2);
  background: var(--color-white); color: var(--color-text);
  font-family: var(--font-button); font-weight: 800; font-size: 9px;
  text-transform: uppercase; letter-spacing: var(--tracking-button);
  padding: 3px 8px; border-radius: var(--radius-pill);
  box-shadow: 0 1px 3px rgba(10, 22, 24, 0.3);
}
.offer-card-foot { padding: var(--space-2) var(--space-3) var(--space-3); }
.offer-card-headline {
  font-family: var(--font-body); font-weight: 700; font-size: 12px;
  color: var(--color-text); line-height: 1.3; margin: 0 0 3px;
  /* Fixed to exactly 2 lines at this line-height (2.6 = 2 x 1.3), truncated
     with an ellipsis past that — not just a max-height. A 1-line headline
     ("Kids play free") still reserves the full 2 lines of space, so every
     card's footer, and so every card overall, ends up the same height
     regardless of how long its headline text runs; longer ones ("$10 off
     a wheel-throwing class") no longer stretch their card taller than its
     grid neighbors. */
  height: 2.6em;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.offer-card-foot-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.offer-card-biz {
  font-family: var(--font-body); font-weight: 500; font-size: 10px; color: var(--color-text-muted);
  /* Same reasoning as the headline above, one line instead of two: a long
     business name truncates with an ellipsis instead of wrapping and
     adding a second row, which would again make that one card taller
     than the rest. min-width:0 is what actually lets a flex item (this
     sits in .offer-card-foot-row next to the arrow) shrink and truncate
     at all — flex items default to a content-based min-width otherwise. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.offer-card-arrow { color: var(--color-accent); font-weight: 700; font-size: 11px; flex-shrink: 0; }

/* ---- Memory card ("Museum label" — picked from the card-options comps)
   — the image sits inset like a framed print, with a labeled plaque below;
   a curated, exhibit-like read for "memories to keep." Fills its masonry
   grid cell's full height (see .grid-masonry), so the media area — not
   the plaque — is what grows on a 2-row (.span-2) card. ---- */
.memory-card {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--color-white);
  border: 1px solid var(--color-gray-200);
  border-radius: var(--radius-m);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.memory-card-media {
  flex: 1;
  min-height: 72px;
  margin: var(--space-2) var(--space-2) 0;
  border-radius: var(--radius-s);
  box-shadow: inset 0 1px 3px rgba(10, 22, 24, 0.4);
  background-size: cover;
  background-position: center;
}
.memory-card-plaque {
  flex-shrink: 0;
  padding: var(--space-2) var(--space-3) var(--space-3);
  border-top: 1px solid var(--color-gray-200);
  margin-top: var(--space-2);
}
.memory-card-eyebrow {
  font-family: var(--font-button); font-weight: 800; font-size: 10px; text-transform: uppercase;
  letter-spacing: var(--tracking-button); color: var(--color-text-muted); margin: 0 0 3px;
}
.memory-card-title { font-family: var(--font-heading); font-weight: 500; font-size: var(--text-body-tight); color: var(--color-text); margin: 0 0 2px; }
.memory-card-meta { font-family: var(--font-body); font-size: var(--text-caption); color: var(--color-text-muted); margin: 0; }

/* ---- Save/add overlay icons on a card's image placeholder (Inspiration
   tiles) ---- Decorative in this wireframe: the whole tile is already a
   link to the guide, so these aren't separately wired up — same
   .inert-control convention used elsewhere for MindTrip's own non-functional
   UI (chat-close, mt-fab, mt-own-tabbar). Needs the placeholder-block it
   sits inside to be position:relative (set inline per usage, not globally,
   since most placeholder-blocks don't need it). */
.tile-actions { position: absolute; top: var(--space-2); right: var(--space-2); display: flex; gap: var(--space-2); }
.tile-action { display: flex; color: var(--color-white); filter: drop-shadow(0 1px 2px rgba(0,0,0,0.5)); }
.tile-action svg { width: 18px; height: 18px; }

/* ---- Shop drawer (Memories) ----
   Covers the whole phone frame — same absolute-over-.device footprint as
   .hunt-modal-overlay below, so it blocks the nav bar too — but presents as
   a bottom sheet over a blurred backdrop (slides up on open) rather than a
   full-screen takeover. The sheet itself still has no close button and no
   grabber-drag-to-dismiss, since the real shop will be a separate, off-app
   hosted experience with its own exit, not something this prototype fakes —
   but tapping the dimmed backdrop outside the sheet does dismiss it (see
   the click handler in memories/index.html), so the prototype stays
   reviewable. Kept invisible via opacity/pointer-events rather than
   display:none so the slide-up transition can animate; it never intercepts
   clicks or shows up until .is-visible is added. */
.app-frame-overlay {
  position: absolute; inset: 0;
  display: flex;
  align-items: flex-end;
  z-index: 10;
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
.app-frame-overlay.is-visible { opacity: 1; pointer-events: auto; }
.shop-drawer-sheet {
  width: 100%;
  background: var(--color-white);
  border-radius: 20px 20px 0 0;
  padding: var(--space-2) 0 var(--space-5);
  transform: translateY(100%);
  transition: transform 0.3s cubic-bezier(.32, .72, 0, 1); /* iOS-sheet-style ease */
}
.app-frame-overlay.is-visible .shop-drawer-sheet { transform: translateY(0); }

/* ---- Webview embed (Inspiration / MindTrip hand-off) ----
   MindTrip now renders as a bounded component INSIDE the normal app frame
   instead of taking over the whole device: the real .site-header/logo
   (above) and .nav-bar (below — both siblings of .screen inside .device,
   per the note up top) stay mounted and visible the entire time, exactly
   like on every other screen in this prototype. Only the region between
   them becomes the embedded webview, so there's always a way to see what
   app you're in and to jump straight to another tab, instead of the old
   model where a black "HHI App / ✕ Close" bar replaced our own chrome and
   was the only way out.
   .webview-embed repeats the same flex:1 + min-height:0 nesting trick
   documented on .device/.screen above, one level deeper, so the embed
   scrolls internally (via .webview-embed-body) without pushing the real
   nav bar off-screen. .webview-chrome-topbar (below) is the embed's own
   browser-style chrome — unchanged from before, just relocated under our
   site-header instead of under a now-removed app-frame-topbar. */
.webview-embed {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--color-white);
}
.webview-embed-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column; /* matches .screen's own flex column, one level
    deeper — needed so children like .chat-body / .mt-status, which size
    themselves with flex:1, still fill and center correctly now that
    they're nested inside the embed instead of sitting directly in .screen */
  overflow-y: auto;
  scrollbar-width: none; /* Firefox: keep scroll, hide the bar itself */
}
.webview-embed-body::-webkit-scrollbar { display: none; } /* Chrome/Safari: same */
.inert-control { pointer-events: none; opacity: 0.55; cursor: default; }

/* ---- Real MindTrip screenshots ----
   Used in place of hand-recreating MindTrip's own UI in HTML/CSS for a
   handful of screens — getting a pixel-exact recreation wasn't landing
   after several attempts, so these are the actual screenshots, with
   invisible clickable hitboxes layered on top wherever the real screen
   links elsewhere. The image is always exactly --device-width wide (the
   screenshots were captured at that width), so hitbox coordinates below
   are plain pixel values, no percentage math needed. */
.mt-screenshot-wrap { position: relative; line-height: 0; }
.mt-screenshot-wrap img { display: block; width: 100%; height: auto; }
.mt-hitbox { position: absolute; }
.mt-hitbox:hover { background: rgba(0, 0, 0, 0.08); }
.mt-hitbox-full { position: absolute; inset: 0; }

/* ---- Webview chrome (Inspiration hand-off, variant B) ----
   Modeled on a real in-app browser bar (iOS's SFSafariViewController /
   Android's Custom Tabs) rather than repeating our own app-frame-topbar's
   "HHI App" label a second time — that redundancy, plus an all-caps
   "embedded.MINDTRIP.AI"-style URL and two empty decorative icon slots,
   was what made this read as unfinished chrome instead of a believable
   embedded browser. A back chevron only appears where there's somewhere
   in-webview to actually go back to (set via .webview-back, omitted
   otherwise); the url pill always just shows a lock + the real lowercase
   domain, nothing else. */
.webview-chrome-topbar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--color-gray-900);
  padding: var(--space-2) var(--space-2);
  flex-shrink: 0;
}
.webview-back {
  flex-shrink: 0;
  width: 22px;
  color: var(--color-white);
  font-size: 18px;
  line-height: 1;
  text-align: center;
  text-decoration: none;
}
.webview-chrome-urlbar {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: var(--color-gray-700);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-3);
  color: var(--color-white);
  font-size: var(--text-caption);
}
.webview-chrome-urlbar svg { width: 12px; height: 12px; flex-shrink: 0; opacity: 0.75; }

/* ---- Simple chat UI (recreated content, not a screenshot) ---- */
.chat-body { padding: var(--space-3); background: var(--color-white); flex: 1; }
.chat-toolbar { display: flex; align-items: center; justify-content: space-between; padding: var(--space-1) 0 var(--space-3); }
.chat-toolbar .chat-new { font-weight: 700; font-size: var(--text-label); }
.chat-toolbar .chat-icons { display: flex; gap: var(--space-2); align-items: center; }
.chat-close { width: 22px; height: 22px; border-radius: 50%; background: var(--color-black); color: var(--color-white); display: flex; align-items: center; justify-content: center; font-size: 13px; text-decoration: none; }
.chat-title { font-family: var(--font-heading); font-size: 26px; margin: var(--space-2) 0 var(--space-3); }
.chat-msg { display: flex; gap: var(--space-2); margin-bottom: var(--space-4); }
.chat-msg .avatar { width: 22px; height: 22px; border-radius: 50%; background: var(--color-gray-800); color: var(--color-white); flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; }
.chat-msg.user .avatar { background: var(--color-gray-300); color: var(--color-text); }
.chat-msg p { margin: 0; font-size: var(--text-body); line-height: 1.5; }
/* A sibling of .screen inside .device (not nested inside .screen) — same
   pinning pattern as .nav-bar above: keeps the input bar fixed at the
   bottom of the phone while .chat-body scrolls independently above it. */
.chat-input {
  flex-shrink: 0;
  display: flex; align-items: center; gap: var(--space-2);
  background: var(--color-gray-100); border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-3); color: var(--color-gray-700);
  font-size: var(--text-body-tight); margin: var(--space-3);
}
.rec-card { border-top: 1px solid var(--color-gray-200); padding: var(--space-4) 0; }
.rec-card-head { display: flex; justify-content: space-between; align-items: baseline; font-weight: 700; }
.rec-card-meta { color: var(--color-text-muted); font-size: var(--text-body-tight); margin: var(--space-1) 0 var(--space-2); }
.rec-card p { margin: 0 0 var(--space-2); line-height: 1.5; }
.rec-card .placeholder-block { height: 180px; }

/* ---- MindTrip page furniture: tab rows (Overview/Map, Overview/Guides/Reviews/Location) ---- */
.mt-tabs { display: flex; gap: var(--space-4); border-bottom: 1px solid var(--color-gray-200); margin: 0 0 var(--space-3); }
.mt-tab { font-family: var(--font-button); font-size: var(--text-label); color: var(--color-gray-500); padding-bottom: var(--space-2); border-bottom: 2px solid transparent; }
.mt-tab.active { color: var(--color-text); border-bottom-color: var(--color-text); font-weight: 700; }
.mt-hero { position: relative; }
.mt-hero .placeholder-block { border-radius: 0; height: 180px; }
.mt-hero-overlay { position: absolute; left: 0; right: 0; bottom: 0; padding: var(--space-3); color: var(--color-white); background: linear-gradient(transparent, rgba(0,0,0,0.55)); }
.mt-hero-overlay p { margin: 0; font-family: var(--font-heading); font-size: var(--text-heading-m); line-height: 1.2; }
.mt-byline { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-body-tight); color: var(--color-text-muted); margin: var(--space-2) 0 0; }
.mt-fab {
  display: inline-flex; align-items: center; gap: var(--space-1);
  background: var(--color-black); color: var(--color-white); border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-4); font-family: var(--font-button); font-size: var(--text-label);
  margin: var(--space-3) 0; text-decoration: none;
}
.mt-own-tabbar { display: flex; justify-content: space-around; border-top: 1px solid var(--color-gray-200); padding: var(--space-2) 0; margin-top: var(--space-3); }
.mt-own-tabbar span { display: flex; flex-direction: column; align-items: center; gap: 2px; font-size: 9px; color: var(--color-gray-500); }

/* ---- MindTrip webview status states (our own handling — not part of MindTrip's UI) ---- */
.mt-status { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: var(--space-5) var(--space-4); gap: var(--space-3); }
.mt-status-icon {
  width: 56px; height: 56px; border-radius: 50%; background: var(--color-gray-200);
  display: flex; align-items: center; justify-content: center; font-size: 24px; color: var(--color-gray-700); flex-shrink: 0;
}
.mt-status p.item-title { margin: 0; }
.mt-status p.item-caption { text-transform: none; letter-spacing: 0; max-width: 260px; }

/* ---- Explore landing hero (image background, title, search bar, quick actions) ----
   Deliberately fills most of .screen's initial viewport so "Explore more" and
   the option cards below sit off-screen at first — only the section label is
   meant to peek above the fold as a scroll affordance, per the design brief. */
.explore-hero {
  position: relative;
  flex-shrink: 0;
  height: 620px; /* tall enough that only the "Explore more" label peeks above
    the fold on load — the option cards themselves need a scroll now,
    tightening up the original "peeking" design note below */
  margin-bottom: var(--space-5); /* >=2rem gap before "Explore more" per design note */
  /* Real photography now (pulled from the client's own site — see
     assets/images/README.md) in place of the brand-gradient placeholder
     tried in the previous pass. The ::before scrim below still handles
     text legibility over whatever sits behind it. */
  background: url('../assets/images/dji-aerial.jpg');
  background-size: cover;
  background-position: center;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
}
.explore-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.75) 100%);
}
.explore-hero-content {
  position: relative;
  z-index: 1;
  width: 100%;
  padding: var(--space-4) var(--space-3) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.explore-hero-title {
  font-family: var(--font-heading);
  font-size: var(--text-heading-xl);
  font-weight: 400;
  color: var(--color-white);
  text-align: center;
  margin: 0 0 var(--space-2);
}
.explore-search-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--color-white);
  color: var(--color-gray-700);
  border-radius: var(--radius-pill);
  padding: var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-body-tight);
  text-decoration: none;
}
.explore-search-icon { display: flex; opacity: 0.6; }
.explore-search-icon svg { width: 18px; height: 18px; }
.explore-hero-actions { display: flex; flex-direction: column; gap: var(--space-2); }
.btn-outline-light { background: rgba(255,255,255,0.12); color: var(--color-white); border: 1px solid var(--color-white); }

.snackbar-icon { display: inline-flex; vertical-align: -2px; margin-right: 2px; }
.snackbar-icon svg { width: 14px; height: 14px; }

/* ---- "Explore more" option cards (Scavenger Hunt / Audio Tours / Trails) ----
   "Cinematic full-bleed" — the same direction picked for Memories' card C in
   the card-options comps, reused here: a full-bleed photo, a scrim, a small
   tag top-right, and the title sitting directly on the image rather than in
   a separate text row. Scavenger Hunt (the one real, playable feature here)
   stays full-width and taller; Audio Tours and Trails sit side by side in a
   shorter 2-up row. */
.explore-option-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); }
.cinematic-card {
  position: relative;
  display: block;
  border-radius: var(--radius-m);
  overflow: hidden;
  background-size: cover;
  background-position: center;
  text-decoration: none;
  color: var(--color-white);
  box-shadow: var(--shadow-card);
}
.cinematic-card-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(10, 22, 24, 0.85), transparent 65%);
}
.cinematic-card-tag {
  position: absolute; top: var(--space-2); right: var(--space-2);
  background: rgba(255, 255, 255, 0.2);
  color: var(--color-white);
  font-family: var(--font-button); font-weight: 800; font-size: 10px;
  text-transform: uppercase; letter-spacing: var(--tracking-button);
  padding: 3px 8px; border-radius: var(--radius-s);
}
.cinematic-card-content { position: absolute; left: var(--space-3); right: var(--space-3); bottom: var(--space-2); }
.cinematic-card-title { font-family: var(--font-heading); font-style: italic; font-weight: 500; font-size: var(--text-heading-s); margin: 0; line-height: 1.15; }
.cinematic-card-caption { font-family: var(--font-body); font-size: var(--text-caption); margin: 2px 0 0; opacity: 0.9; }

/* ---- Location-aware snackbar (Explore) ----
   Three simulated states, since a static prototype can't read real GPS/
   permission state: near+location-on (show a nearby offer), location-off
   (prompt to enable it), far+location-on (show nothing). A dev-only toggle
   switches between them for demoing; only one .snackbar is visible at a time.
   Must be a sibling of .screen inside .device (not nested inside .screen) —
   same reason as .nav-bar above — so it floats above the nav regardless of
   .screen's scroll position, instead of scrolling away with the content. */
.snackbar-area {
  position: absolute;
  left: var(--space-3);
  right: var(--space-3);
  bottom: calc(var(--nav-height) + var(--space-2));
  z-index: 5;
}
.snackbar {
  display: none;
  align-items: center;
  gap: var(--space-2);
  background: var(--color-black);
  color: var(--color-white);
  border-radius: var(--radius-m);
  padding: var(--space-2) var(--space-3);
  box-shadow: 0 4px 14px rgba(0,0,0,0.25);
}
.snackbar.is-visible { display: flex; }
.snackbar p { margin: 0; font-size: var(--text-body-tight); line-height: 1.4; flex: 1; }
.snackbar a.snackbar-action, .snackbar span.snackbar-action {
  font-weight: 700; font-size: var(--text-label); text-decoration: none; color: var(--color-white);
  white-space: nowrap; border-bottom: 1px solid var(--color-white);
}
.snackbar span.snackbar-action.inert-control { border-bottom-color: var(--color-gray-500); color: var(--color-gray-300); }
.snackbar-dismiss { background: none; border: none; color: var(--color-gray-300); font-size: var(--text-body); cursor: pointer; padding: 0 0 0 var(--space-2); line-height: 1; }

.sim-toggle { display: flex; gap: var(--space-1); }
.sim-toggle button {
  font-family: var(--font-body); font-size: 10px; padding: 3px 6px;
  border: 1px solid var(--color-gray-500); background: var(--color-white); color: var(--color-gray-800);
  border-radius: var(--radius-s); cursor: pointer;
}
.sim-toggle button.active { background: var(--color-black); color: var(--color-white); border-color: var(--color-black); }

/* ---- Immersive media screens (Memories: Sound / Sights / Video) ----
   Full-bleed black/gray screens, deliberately different from the "our app"
   card-and-list look — the intent (per the tracker) is to immerse the user
   in one sound/sight/video from their trip, not show a normal detail page.
   Each Sounds card deep-links here pre-loaded with its own track; Sights
   and Video currently have only one real item each. */
.media-screen {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--color-black);
  color: var(--color-white);
  position: relative;
}
.media-back {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 3;
  color: var(--color-white);
  text-decoration: none;
  font-size: 18px;
  line-height: 1;
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,0.15);
  border-radius: 50%;
}
.loop-toggle {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  z-index: 3;
  background: rgba(255,255,255,0.15);
  border: none;
  color: var(--color-gray-300);
  width: 32px; height: 32px;
  border-radius: 50%;
  font-size: 15px;
  cursor: pointer;
}
.loop-toggle.active { color: var(--color-white); background: rgba(255,255,255,0.3); }

/* Sights / Video: full-bleed viewer, header caption overlaid on top */
.media-header-overlay {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 2;
  padding: 52px var(--space-3) var(--space-4);
  background: rgba(0,0,0,0.6);
}
.media-header-overlay .item-title { font-family: var(--font-heading); font-size: var(--text-heading-m); margin: 0 0 2px; }
.media-header-overlay .item-caption { font-family: var(--font-button); font-size: var(--text-caption); letter-spacing: 0.05em; text-transform: uppercase; opacity: 0.8; margin: 0; }
.media-viewer {
  flex: 1;
  background: var(--color-gray-900);
  display: flex;
  align-items: center;
  justify-content: center;
}
.media-viewer-badge {
  width: 84px; height: 84px;
  border: 2px solid var(--color-white);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-button);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: 0.05em;
  opacity: 0.85;
  text-align: center;
}

/* Sound: centered player layout */
.player-body { flex: 1; display: flex; flex-direction: column; justify-content: center; padding: 0 var(--space-4); }
.player-label { text-align: center; font-family: var(--font-button); font-size: var(--text-caption); letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-gray-500); margin: 0 0 var(--space-4); }
.player-art { width: 235px; height: 235px; margin: 0 auto var(--space-4); background: var(--color-gray-700); border-radius: var(--radius-m); }
.player-meta { text-align: center; margin-bottom: var(--space-5); }
.player-meta .item-title { font-family: var(--font-heading); font-size: var(--text-heading-m); margin: 0 0 4px; }
.player-meta .item-caption { font-family: var(--font-button); font-size: var(--text-caption); letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-gray-500); margin: 0; }

/* Scrubber (shared by the sound player and the video screen) */
.scrubber { margin-bottom: var(--space-4); }
.scrubber-bar { height: 3px; background: var(--color-gray-700); border-radius: 2px; position: relative; }
.scrubber-bar-fill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--color-white); border-radius: 2px; }
.scrubber-time { display: flex; justify-content: space-between; font-size: 10px; color: var(--color-gray-500); font-family: var(--font-body); margin-top: var(--space-1); }

.transport { display: flex; align-items: center; justify-content: center; gap: var(--space-5); padding-bottom: var(--space-5); }
.transport-btn { background: none; border: none; color: var(--color-white); font-size: 22px; cursor: pointer; text-decoration: none; display: flex; align-items: center; justify-content: center; }
.transport-btn.disabled { opacity: 0.3; pointer-events: none; }
.transport-play { width: 56px; height: 56px; border-radius: 50%; background: var(--color-white); color: var(--color-black); display: flex; align-items: center; justify-content: center; font-size: 18px; }

/* ---- Scavenger Hunt (full takeover) ----
   Confirmed via Figma (Scavenger Hunt Game section). This flow gets its own
   header and drops our normal site-header/bottom nav entirely — it's meant
   to read as a distinct "game mode" you step into and explicitly exit, not
   another tab. State (which of the 5 clues are solved) is kept in the
   browser's localStorage by js/game.js so it survives moving between these
   pages — that only works because this is a real folder of files opened in
   a real browser, not a preview; "Play Again" clears it. */
.hunt-screen {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow-y: auto;
  background: var(--color-white);
  scrollbar-width: none;
}
.hunt-screen::-webkit-scrollbar { display: none; }
/* Loading screen only — a stippled, brand-green-tinted texture instead of
   flat white, since this beat is otherwise just a bare turtle-safety
   message with nothing else on screen. Bumped way up from the first
   attempt's 1px/6%-opacity dots, which turned out too faint to register
   in the ~1.3s this screen is actually on-screen for. */
.hunt-screen--loading {
  background-color: var(--color-paper);
  background-image:
    radial-gradient(rgba(70, 134, 99, 0.35) 2px, transparent 2px),
    radial-gradient(rgba(70, 134, 99, 0.35) 2px, transparent 2px);
  background-size: 18px 18px;
  background-position: 0 0, 9px 9px;
}
.hunt-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-3) var(--space-2);
}
.hunt-back {
  font-family: var(--font-button);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--color-text);
}
.hunt-toggle {
  font-family: var(--font-button);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--color-accent-dark);
  background: var(--color-placeholder-fill);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-pill);
}
.hunt-title { font-family: var(--font-heading); font-size: var(--text-heading-xl); font-weight: 400; text-align: center; margin: var(--space-3) 0 var(--space-2); padding: 0 var(--space-3); }
.hunt-kicker { font-family: var(--font-button); font-size: var(--text-label); font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; text-align: center; color: var(--color-accent); margin: 0 0 var(--space-4); padding: 0 var(--space-3); }
.hunt-splash-image {
  height: 160px; margin: 0 var(--space-4) var(--space-4);
  border-radius: var(--radius-m); background-size: cover; background-position: center;
  box-shadow: var(--shadow-card);
}
.hunt-body { font-family: var(--font-body); font-size: var(--text-body-tight); line-height: 1.6; padding: 0 var(--space-4); color: var(--color-text); }
.hunt-body p { margin: 0 0 var(--space-3); }
.hunt-safety { border: 1px solid var(--color-gold); border-radius: var(--radius-m); background: var(--color-dune); margin: var(--space-3) var(--space-4) 0; padding: var(--space-2) var(--space-3); font-family: var(--font-button); font-size: 11px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; text-align: center; color: var(--color-accent-dark); }
.hunt-actions { padding: var(--space-5) var(--space-4); margin-top: auto; }
.hunt-actions .btn { width: 100%; }

.hunt-tracker { display: flex; gap: var(--space-2); padding: 0 var(--space-3); justify-content: center; }
.hunt-tile {
  width: 56px; height: 56px;
  border: 1px solid var(--color-gray-300);
  border-radius: var(--radius-l);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-heading); font-size: 26px; color: var(--color-gray-800);
  background: var(--color-white);
}
.hunt-tile.current { border: 3px solid var(--color-gold); }
.hunt-tile.done { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-white); font-size: 20px; }

.hunt-photo {
  margin: var(--space-4) var(--space-3) 0;
  background: var(--color-dune);
  border-radius: var(--radius-l);
  height: 150px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-2);
  font-family: var(--font-button); font-size: var(--text-caption);
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-accent-dark);
  text-align: center; padding: var(--space-2);
}
.hunt-photo svg { width: 28px; height: 28px; opacity: 0.7; }
.hunt-question { font-family: var(--font-button); font-size: var(--text-label); font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; margin: var(--space-4) var(--space-3) 0; }
.hunt-answer-input {
  display: block; width: calc(100% - 2 * var(--space-3));
  margin: var(--space-3) var(--space-3) 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-gray-700); border-radius: var(--radius-pill);
  font-family: var(--font-body); font-size: var(--text-body-tight);
  background: var(--color-gray-100);
}

.hunt-map { flex: 1; min-height: 0; position: relative; background: var(--color-placeholder-fill); overflow: hidden; }
.hunt-map-caption {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; justify-content: center;
  font-family: var(--font-button); font-size: var(--text-caption);
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-accent-dark);
  text-align: center; padding: var(--space-4) var(--space-5) 0; pointer-events: none;
}
.hunt-pin {
  position: absolute; width: 40px; height: 40px;
  border-radius: 50%;
  background: var(--color-white); border: 3px solid var(--color-gold);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-heading); font-size: 16px; color: var(--color-accent-dark);
  cursor: pointer; text-decoration: none;
  box-shadow: var(--shadow-card);
  transform: translate(-50%, -50%);
}
.hunt-pin.done { background: var(--color-accent); color: var(--color-white); border-color: var(--color-accent); pointer-events: none; font-size: 14px; }

/* Scavenger Hunt buttons: green instead of the shared .btn-dark's near-black
   — scoped to just the hunt screens/modal so Inspiration's own .btn-dark
   buttons (a separate, unrelated use of the same class) are untouched. */
.hunt-screen .btn-dark, .hunt-modal .btn-dark { background: var(--color-accent); }
.hunt-win-banner {
  flex-shrink: 0; display: none;
  align-items: center; justify-content: space-between; gap: var(--space-2);
  background: var(--color-accent-dark); color: var(--color-white);
  padding: var(--space-3) var(--space-3);
}
.hunt-win-banner.is-visible { display: flex; }
.hunt-win-banner p { margin: 0; font-size: var(--text-body-tight); }
.hunt-win-banner a { color: var(--color-white); font-weight: 700; font-size: var(--text-label); text-decoration: none; border-bottom: 1px solid var(--color-white); white-space: nowrap; }

/* Image on top, at real scale, so the partner photo reads as the prize's
   main visual and the card doesn't look like a plain text button — text
   and CTA follow underneath at normal card padding. */
.hunt-prize-card {
  margin: var(--space-5) var(--space-4) 0;
  border: 2px dashed var(--color-gold); border-radius: var(--radius-l);
  padding: 0 0 var(--space-4); text-align: center; background: none; cursor: pointer;
  font-family: var(--font-body); width: calc(100% - 2 * var(--space-4));
  display: flex; flex-direction: column; align-items: center;
  overflow: hidden;
}
.hunt-prize-image { width: 100%; height: 200px; flex-shrink: 0; border-radius: 0; border: none; padding: 0; margin: 0 0 var(--space-3); }
.hunt-prize-content { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); padding: 0 var(--space-4); }
.hunt-prize-card .item-title { font-size: var(--text-body); margin: 0; font-weight: 700; }

.hunt-modal-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.5); display: none; align-items: center; justify-content: center; z-index: 10; padding: var(--space-4); }
.hunt-modal-overlay.is-visible { display: flex; }
.hunt-modal { background: var(--color-white); border: 1px solid var(--color-gray-300); border-radius: var(--radius-l); padding: var(--space-4) var(--space-3); width: 100%; max-width: 320px; text-align: center; }
.hunt-modal .page-title { margin-bottom: var(--space-2); }
.hunt-modal p { font-family: var(--font-body); font-size: var(--text-body-tight); margin: 0 0 var(--space-3); }
.hunt-field { display: block; width: 100%; margin-bottom: var(--space-2); padding: var(--space-2) var(--space-3); border: 1px solid var(--color-gray-500); border-radius: var(--radius-s); font-family: var(--font-body); font-size: var(--text-body-tight); text-align: left; }
.hunt-checkbox-row { display: flex; align-items: flex-start; gap: var(--space-2); text-align: left; font-size: var(--text-caption); color: var(--color-gray-700); margin: var(--space-2) 0 var(--space-4); }
.hunt-checkbox-row input { margin-top: 3px; }
.hunt-qr { width: 180px; height: 180px; border: 2px dashed var(--color-gold); border-radius: var(--radius-m); margin: var(--space-3) auto; display: flex; align-items: center; justify-content: center; font-family: var(--font-button); font-size: var(--text-caption); letter-spacing: 0.05em; text-transform: uppercase; }

/* ---- Handoff overlay (Variant A: native Open-with sheet) ---- */
.sheet-overlay { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; background: rgba(0,0,0,0.35); }
.sheet { background: var(--color-gray-100); border-radius: 16px 16px 0 0; padding: var(--space-3) var(--space-3) var(--space-5); }
.sheet-grabber { width: 34px; height: 4px; background: var(--color-gray-700); border-radius: 2px; margin: 0 auto var(--space-4); }
.sheet-title { font-size: var(--text-body); font-weight: 700; margin: 0 0 var(--space-3); }
.sheet-app-row { background: var(--color-white); border-radius: 14px; padding: var(--space-3); display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-1); text-decoration: none; color: inherit; }
.sheet-app-icon { width: 34px; height: 34px; background: var(--color-gray-300); border-radius: var(--radius-m); flex-shrink: 0; }
.sheet-app-name { font-weight: 700; font-size: var(--text-body-tight); }
.sheet-app-sub { font-size: var(--text-caption); color: var(--color-gray-700); }
.sheet-toggle-row { display: flex; align-items: center; justify-content: space-between; padding: var(--space-3) var(--space-2) 0; font-size: var(--text-caption); }
.sheet-toggle { width: 40px; height: 22px; background: var(--color-gray-700); border-radius: 11px; position: relative; }
.sheet-toggle::after { content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; background: var(--color-white); border-radius: 50%; }
