/* ═══════════════════════════════════════════════════════════════════════
   Flow Design System - Layer 3 (Component Classes)
   ─────────────────────────────────────────────────────────────────────
   .fs-* classes for HEEx function components in lib/flow_stay_web/components/ui/.

   DISCIPLINE RULE: Every property here references --flow-* tokens from
   flow_tokens.css. Never raw hex, never Open Props vars directly.
   If a property needs a value not in flow_tokens.css, add the token
   there first, then consume it here.

   Organized to match component file order in components/ui/.

   Spec:  docs/superpowers/specs/2026-04-26-flowvue-ui-integration-design.md
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Semantic typography roles ─────────────────────────────────────
 *
 * Migrated from flowvue_tokens.css (2026-05-05 - Task #9b). These are
 * utility-class typography roles, not component-specific selectors. They
 * encode the FlowStay type scale (Cormorant for display/serif, DM Sans
 * for UI, Sacramento for accent, JetBrains Mono for code) plus the
 * paired weight + size + tracking that defines each role.
 *
 * Use these classes for one-off typography in HEEx where building a
 * dedicated component is overkill. Component CSS below should NOT
 * depend on these classes - components compose their own typography
 * directly from --flow-font-* and --flow-fs-* tokens.
 */

.fs-h1, .fs-hero {
  font-family:    var(--flow-font-display);
  font-weight:    600;
  font-size:      clamp(28px, 4vw, 44px);
  line-height:    var(--flow-lh-tight);
  color:          var(--flow-fg-1);
  letter-spacing: -0.005em;
}

.fs-h2, .fs-modal-title {
  font-family: var(--flow-font-display);
  font-weight: 600;
  font-size:   var(--flow-fs-modal);
  line-height: var(--flow-lh-tight);
  color:       var(--flow-fg-1);
}

.fs-h3, .fs-room-name {
  font-family: var(--flow-font-display);
  font-weight: 600;
  font-size:   var(--flow-fs-display);
  line-height: var(--flow-lh-tight);
  color:       var(--flow-fg-1);
}

.fs-verb {
  font-family:    var(--flow-font-display);
  font-weight:    600;
  font-size:      var(--flow-fs-verb);
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  line-height:    var(--flow-lh-tight);
  color:          var(--flow-fg-1);
}

.fs-script {
  font-family: var(--flow-font-script);
  font-size:   var(--flow-fs-script);
  line-height: 1;
  color:       var(--flow-fg-2);
}

.fs-p {
  font-family: var(--flow-font-ui);
  font-weight: 400;
  font-size:   var(--flow-fs-body);
  line-height: var(--flow-lh-body);
  color:       var(--flow-fg-1);
}

.fs-meta {
  font-family: var(--flow-font-ui);
  font-weight: 500;
  font-size:   var(--flow-fs-meta);
  color:       var(--flow-fg-3);
}

.fs-label {
  font-family:    var(--flow-font-ui);
  font-weight:    500;
  font-size:      var(--flow-fs-label);
  letter-spacing: var(--flow-tracking-label);
  text-transform: uppercase;
  color:          var(--flow-fg-3);
}

.fs-data {
  font-family:           var(--flow-font-ui);
  font-weight:           600;
  font-size:             var(--flow-fs-body-sm);
  color:                 var(--flow-fg-1);
  font-variant-numeric:  tabular-nums;
}

.fs-code {
  font-family: var(--flow-font-mono);
  font-size:   var(--flow-fs-meta);
  color:       var(--flow-fg-2);
}

/* ── chip.ex ─────────────────────────────────────────────────────── */

.fs-live-chip {
  display:         inline-flex;
  align-items:     center;
  gap:             5px;
  padding:         3px 8px 3px 7px;
  border-radius:   var(--flow-r-pill);
  background:      var(--flow-bg-chip-dark);
  border:          1px solid var(--flow-live-green-25);
  font-family:     var(--flow-font-ui);
  font-size:       8px;
  font-weight:     700;
  letter-spacing:  0.12em;
  /* Match upstream `.fv-live` ink + uppercase + flex-shrink. The
     migration's collision map for --fv-ink → --flow-ink-* slipped here
     and routed to --flow-ink-2 (0.85) instead of --flow-ink (0.92);
     uppercase + flex-shrink were dropped entirely. */
  color:           var(--flow-ink);
  text-transform:  uppercase;
  flex-shrink:     0;
}

.fs-live-dot {
  width:        4px;
  height:       4px;
  border-radius: var(--flow-r-dot);
  background:   var(--flow-live-green);
  box-shadow:   0 0 5px var(--flow-live-green-60);
  animation:    fs-live-pulse var(--flow-dur-pulse) var(--flow-ease-inout) infinite;
}

/* The single `@keyframes fs-live-pulse` definition lives further down
   (next to `.fs-live::before`) - it animates BOTH opacity and box-shadow
   so the green dot breathes its glow as well as fades. The earlier
   opacity-only declaration that lived here was redundant noise; CSS
   resolves @keyframes by name, last-one-wins, so the dual-property one
   was always what animated. */

/* ── button.ex ────────────────────────────────────────────────────── */

/* speak_pill - floating gold "tap to speak" prompt. */
.fs-speak-pill {
  display:         inline-flex;
  align-items:     center;
  gap:             9px;
  padding:         var(--flow-space-2) 14px var(--flow-space-2) var(--flow-space-3);
  border-radius:   var(--flow-r-pill-lg);
  background:      var(--flow-gold-a12);
  border:          1px solid var(--flow-gold-a30);
  box-shadow:      0 0 0 1px var(--flow-gold-a08);
  backdrop-filter: blur(20px);
  font-family:     var(--flow-font-ui);
  color:           var(--flow-gold-ink);
  cursor:          pointer;
  transition:      background var(--flow-dur-sm) var(--flow-ease-out);
}

.fs-speak-pill:hover {
  background: var(--flow-gold-a30);
}

.fs-speak-pill:focus-visible {
  outline:        2px solid var(--flow-gold);
  outline-offset: 2px;
}

.fs-speak-pill-dot {
  width:        var(--flow-space-2);
  height:       var(--flow-space-2);
  border-radius: var(--flow-r-dot);
  background:   var(--flow-gold);
  box-shadow:   0 0 6px var(--flow-gold-a60),
                0 0 12px var(--flow-gold-a30);
  animation:    fs-speak-dot var(--flow-dur-pulse) var(--flow-ease-inout) infinite;
}

.fs-speak-pill-text {
  display:        flex;
  flex-direction: column;
  gap:            1px;
  text-align:     left;
}

.fs-speak-pill-label {
  font-size:   11px;
  font-weight: 600;
  color:       var(--flow-gold-ink);
  white-space: nowrap;
}

.fs-speak-pill-sub {
  font-size:      7px;
  font-weight:    500;
  letter-spacing: 0.12em;
  color:          var(--flow-gold-ink-50);
  text-transform: uppercase;
}

/* Disabled - quiet neutral, no pulse, dimmer than active so it reads as
   inactive at a glance rather than as another gold pill with a tweak. */
.fs-speak-pill[disabled] {
  background:   var(--flow-surface-glass-06);
  border-color: var(--flow-ink-30);
  box-shadow:   none;
  color:        var(--flow-ink-3);
  cursor:       not-allowed;
  opacity:      0.55;
}

.fs-speak-pill[disabled]:hover {
  background: var(--flow-surface-glass-06);
}

.fs-speak-pill[disabled] .fs-speak-pill-dot {
  animation:  none;
  background: var(--flow-ink-30);
  box-shadow: none;
}

.fs-speak-pill[disabled] .fs-speak-pill-label,
.fs-speak-pill[disabled] .fs-speak-pill-sub {
  color: var(--flow-ink-3);
}

@keyframes fs-speak-dot {
  0%, 100% { opacity: 0.9; transform: scale(1);    }
  50%      { opacity: 0.5; transform: scale(0.85); }
}

/* ── three_dots.ex ───────────────────────────────────────────────── */

/* Bouncing 3-dot loader for "agent thinking" / loading states.
   Per-dot `--dot-index` custom property drives staggered delay so a
   single rule covers all three dots. */
.fs-three-dots {
  display:     inline-flex;
  align-items: center;
  gap:         var(--flow-space-1);
}

.fs-three-dots-dot {
  width:           6px;
  height:          6px;
  border-radius:   var(--flow-r-dot);
  background:      var(--flow-ink-3);
  animation:       fs-three-dots-bounce var(--flow-dur-pulse) var(--flow-ease-inout) infinite;
  animation-delay: calc(var(--dot-index) * 160ms);
}

@keyframes fs-three-dots-bounce {
  0%, 80%, 100% { transform: translateY(0);    opacity: 0.4; }
  40%           { transform: translateY(-4px); opacity: 1;   }
}

/* ── check_draw.ex ───────────────────────────────────────────────── */

/* Animated SVG checkmark for booking-confirmation states. Both the circle
   and the inner path draw themselves on via stroke-dasharray /
   stroke-dashoffset transitions. The path lengths are pre-measured for the
   48x48 viewBox in this component:
     circle (r=22)       → ~138.23px circumference
     check  (M14 25 …)   → ~28.4px length
   We round up so the dash always covers the full stroke. */
.fs-check-draw {
  display: inline-block;
}

.fs-check-draw-circle {
  stroke:             var(--flow-live-green);
  stroke-width:       var(--flow-stroke-w);
  stroke-dasharray:   140;
  stroke-dashoffset:  140;
  animation:          fs-check-draw-on var(--flow-dur-draw) var(--flow-ease-out) forwards;
}

.fs-check-draw-path {
  stroke:             var(--flow-live-green);
  stroke-width:       var(--flow-stroke-w-md);
  stroke-dasharray:   30;
  stroke-dashoffset:  30;
  animation:          fs-check-draw-on var(--flow-dur-draw) var(--flow-ease-out) forwards;
}

@keyframes fs-check-draw-on {
  to { stroke-dashoffset: 0; }
}

/* ── divider.ex ──────────────────────────────────────────────────── */

/* Hairline horizontal rule used to separate sections. Defaults to 80% width
   centered, mirroring the flowvue source. Consumers can override with their
   own width via inline style or a wrapping container. */
.fs-divider {
  width:        80%;
  height:       1px;
  margin:       0 auto;
  background:   var(--flow-surface-glass-06);
}

/* ── traffic_dots.ex ─────────────────────────────────────────────── */

/* macOS window-control trio (red/yellow/green). Decorative chrome for
   browser-frame compositions. */
.fs-traffic-dots {
  display: inline-flex;
  gap:     5px;
}

.fs-traffic-dots-dot {
  width:         9px;
  height:        9px;
  border-radius: var(--flow-r-dot);
}

.fs-traffic-dots-dot--red    { background: var(--flow-mac-red);    }
.fs-traffic-dots-dot--yellow { background: var(--flow-mac-yellow); }
.fs-traffic-dots-dot--green  { background: var(--flow-mac-green);  }

/* ── avatar.ex ───────────────────────────────────────────────────── */

/* Circular initials avatar. Size is per-instance, set via the
   `--fs-avatar-size` custom property on the element (the only legitimate
   inline-style use here, since diameter varies per instance). The font
   scales with the diameter so initials always sit visually centered. */
.fs-avatar {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  width:           var(--fs-avatar-size);
  height:          var(--fs-avatar-size);
  border-radius:   var(--flow-r-dot);
  background:      var(--flow-gold);
  color:           var(--flow-bg);
  font-family:     var(--flow-font-display);
  font-size:       calc(var(--fs-avatar-size) * 0.42);
  font-weight:     600;
  line-height:     1;
  letter-spacing:  0.02em;
  user-select:     none;
}

/* ── url_padlock.ex ──────────────────────────────────────────────── */

/* Safari-style URL-bar fragment: padlock icon + domain on a low-alpha pill. */
.fs-url-padlock {
  display:        inline-flex;
  align-items:    center;
  gap:            5px;
  height:         20px;
  padding:        0 var(--flow-space-2);
  border-radius:  5px;
  background:     var(--flow-surface-glass-06);
  font-family:    var(--flow-font-ui);
}

.fs-url-padlock-icon {
  width:  9px;
  height: 9px;
  color:  var(--flow-ink-30);
}

.fs-url-padlock-domain {
  font-size:      10px;
  letter-spacing: 0.02em;
  color:          var(--flow-ink-3);
}

/* ── room_hero.ex ────────────────────────────────────────────────── */

/* Hero image card with gradient overlay, info block (name + price), and
   pagination dots. Sized by the parent: this component fills its
   container so consumers control width/height (the original flowvue
   styles included slot-specific `flex` and `clamp()` rules tied to the
   phone-frame layout - those are intentionally not ported here). */
.fs-room-hero {
  position:      relative;
  overflow:      hidden;
  width:         100%;
  height:        100%;
  border-radius: var(--flow-r-card);
}

.fs-room-hero-image {
  position:   absolute;
  inset:      0;
  width:      100%;
  height:     100%;
  object-fit: cover;
}

.fs-room-hero-gradient {
  position:       absolute;
  bottom:         0;
  left:           0;
  right:          0;
  height:         50%;
  background:     var(--flow-gradient-hero-fade);
  pointer-events: none;
}

.fs-room-hero-info {
  position: absolute;
  bottom:   var(--flow-space-4);
  left:     var(--flow-space-5);
  z-index:  2;
}

.fs-room-hero-name {
  font-family:   var(--flow-font-display);
  font-size:     20px;
  font-weight:   600;
  line-height:   1.2;
  margin-bottom: 2px;
  color:         var(--flow-ink-pure);
  text-shadow:   var(--flow-shadow-text-strong);
}

.fs-room-hero-price {
  font-family: var(--flow-font-ui);
  font-size:   12px;
  font-weight: 700;
  color:       var(--flow-live-green);
  text-shadow: var(--flow-shadow-text-soft);
}

.fs-room-hero-dots {
  position: absolute;
  bottom:   var(--flow-space-4);
  right:    var(--flow-space-5);
  z-index:  2;
  display:  flex;
  gap:      var(--flow-space-1);
}

.fs-room-hero-dot {
  width:         6px;
  height:        6px;
  border-radius: var(--flow-r-dot);
  background:    var(--flow-ink-30);
  transition:    background var(--flow-dur-md) var(--flow-ease-out);
}

.fs-room-hero-dot--active {
  background: var(--flow-ink-90);
}

/* ── grid_tile.ex ────────────────────────────────────────────────── */

/* Image-fill cell with dark tint + bottom-anchored verb (uppercase
   display) and cursive script label. Sized by the parent: this
   component fills its container so consumers control width / height
   (the original flowvue source nested per-slot `flex` and `clamp()`
   rules tied to a phone-frame layout - those are intentionally not
   ported here). */
.fs-grid-tile {
  position:      relative;
  overflow:      hidden;
  width:         100%;
  height:        100%;
  border-radius: var(--flow-r-card);
}

.fs-grid-tile-image {
  position:   absolute;
  inset:      0;
  width:      100%;
  height:     100%;
  object-fit: cover;
}

/* Tile tint: flat blue-navy scrim over warm hotel photography so the
   centered text lockup reads cleanly. Spec §Backgrounds & Imagery. */
.fs-grid-tile-tint {
  position:       absolute;
  inset:          0;
  background:     var(--flow-scrim-photo-navy);
  pointer-events: none;
}

/* Text container: centered (not bottom-anchored). The verb-script
   lockup is the brand's signature mark - it sits in the middle of
   the tile like a wax seal. */
.fs-grid-tile-text {
  position:        absolute;
  inset:           0;
  display:         flex;
  flex-direction:  column;
  align-items:     center;
  justify-content: center;
  z-index:         2;
}

/* UPPERCASE serif verb (Cormorant Garamond 600) - the action half of
   the lockup. Always paired with a Sacramento script noun below. */
.fs-grid-tile-verb {
  font-family:    var(--flow-font-display);
  font-size:      var(--flow-fs-verb);
  font-weight:    600;
  letter-spacing: var(--flow-tracking-caps);
  color:          var(--flow-ink-pure);
  text-shadow:    var(--flow-shadow-text-soft);
  text-transform: uppercase;
  line-height:    var(--flow-lh-tight);
}

/* Sacramento script noun - the tender half of the lockup. Negative
   margin-top pulls it up so the cursive ascenders kiss the verb's
   baseline. Sacramento is single-weight; do not set font-weight. */
.fs-grid-tile-script {
  font-family: var(--flow-font-script);
  font-size:   var(--flow-fs-script);
  line-height: 1;
  margin-top:  -2px;
  color:       var(--flow-ink-pure);
  text-shadow: var(--flow-shadow-text-strong);
}

/* ── submenu_card.ex ─────────────────────────────────────────────── */

/* Variant card for booking actions (new / modify / cancel). Same
   image-fill + dark-tint + bottom-text structure as `fs-grid-tile`,
   plus a per-variant accent color on the verb (gold / neutral /
   danger) and an optional sub-line beneath the script. Sized by the
   parent. */
.fs-submenu-card {
  position:      relative;
  overflow:      hidden;
  width:         100%;
  height:        100%;
  border-radius: var(--flow-r-card);
}

.fs-submenu-card-image {
  position:   absolute;
  inset:      0;
  width:      100%;
  height:     100%;
  object-fit: cover;
}

.fs-submenu-card-tint {
  position:       absolute;
  inset:          0;
  background:     var(--flow-gradient-hero-fade);
  pointer-events: none;
}

.fs-submenu-card-text {
  position: absolute;
  bottom:   var(--flow-space-3);
  left:     var(--flow-space-4);
  right:    var(--flow-space-4);
  z-index:  2;
}

.fs-submenu-card-verb {
  font-family:    var(--flow-font-ui);
  font-size:      11px;
  font-weight:    700;
  letter-spacing: 0.12em;
  text-shadow:    var(--flow-shadow-text-soft);
  text-transform: uppercase;
}

.fs-submenu-card-script {
  font-family: var(--flow-font-display);
  font-style:  italic;
  font-size:   18px;
  font-weight: 500;
  line-height: 1.1;
  color:       var(--flow-ink-pure);
  text-shadow: var(--flow-shadow-text-strong);
}

.fs-submenu-card-sub {
  margin-top:     2px;
  font-family:    var(--flow-font-ui);
  font-size:      10px;
  font-weight:    500;
  letter-spacing: 0.02em;
  color:          var(--flow-ink-3);
  text-shadow:    var(--flow-shadow-text-soft);
}

/* Variant accents - only the verb color shifts; image, tint, and
   script keep the shared treatment so the strip reads as one set. */
.fs-submenu-card--new    .fs-submenu-card-verb { color: var(--flow-gold);     }
.fs-submenu-card--mod    .fs-submenu-card-verb { color: var(--flow-ink-pure); }
.fs-submenu-card--cancel .fs-submenu-card-verb { color: var(--flow-danger);   }

/* ── date_strip.ex ───────────────────────────────────────────────── */

/* Date-strip BEM children - primary text uses --flow-ink-2; arrow +
   tiny dot dividers ride at --flow-ink-3 to recede; the trailing link
   (the only interactive element here) lifts to --flow-gold and shows
   a focus ring. The legacy `.fs-date-strip` parent rule lower in this
   file (next to .fs-date-* legacy descendants) owns the wrapper layout
   today; the duplicate BEM parent that previously lived here was
   deleted to resolve the collision while leaving these BEM children
   intact for `<.date_strip>` and the storyboard preview. */
.fs-date-strip-checkin,
.fs-date-strip-checkout,
.fs-date-strip-guests,
.fs-date-strip-nights {
  white-space: nowrap;
}

.fs-date-strip-arrow {
  color:       var(--flow-ink-3);
  font-size:   11px;
  line-height: 1;
}

/* Tiny bullet divider between segments. */
.fs-date-strip-dot {
  width:         3px;
  height:        3px;
  border-radius: var(--flow-r-dot);
  background:    var(--flow-ink-3);
  flex-shrink:   0;
}

.fs-date-strip-see-all {
  color:           var(--flow-gold);
  text-decoration: none;
  font-weight:     600;
  white-space:     nowrap;
  cursor:          pointer;
  transition:      opacity var(--flow-dur-sm) var(--flow-ease-out);
}

.fs-date-strip-see-all:hover {
  opacity: 0.85;
}

.fs-date-strip-see-all:focus-visible {
  outline:        2px solid var(--flow-gold);
  outline-offset: 2px;
  border-radius:  2px;
}

/* ── widget shell (widget_live.ex - Task 22) ─────────────────────── */

/* Top-level flex shell for the widget LiveView. The visual panel grows; the
   voice panel stays a fixed sidebar. System font stack is used here (vs. the
   Cormorant/DM Sans display fonts used elsewhere) to blend with host-page
   chrome on embed. */
.fs-widget-root {
  display:        flex;
  flex-direction: column;
  width:          100%;
  height:         100vh;
  background:     var(--flow-bg);
  font-family:    var(--flow-font-system);
}

/* widget_stepper */
.fs-widget-stepper {
  padding: 14px 22px;
  background: rgba(0, 0, 0, 0.35);
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.fs-widget-stepper__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
}

.fs-widget-stepper__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.fs-widget-stepper__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--flow-ink-dim);
  transition: background 0.18s ease, transform 0.18s ease;
}

.fs-widget-stepper__dot--past {
  background: rgba(212, 168, 83, 0.55);
}

.fs-widget-stepper__dot--current {
  background: var(--flow-gold);
  transform: scale(1.25);
  box-shadow: 0 0 8px rgba(212, 168, 83, 0.5);
}

.fs-widget-stepper__label {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--flow-ink-dim);
}

.fs-widget-stepper__item--current .fs-widget-stepper__label {
  color: var(--flow-gold);
}

/* ── flow/agent_bubble ─────────────────────────── */
.fs-flow-agent-bubble {
  max-width: 88%;
  padding: 12px 16px;
  border-radius: 18px 18px 18px 4px;
  background: var(--flow-surface-glass-08, rgba(255, 255, 255, 0.08));
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--flow-line, rgba(255, 255, 255, 0.08));
  color: var(--flow-ink);
  font-family: var(--flow-font-ui, 'DM Sans', sans-serif);
  font-size: 14px;
  line-height: 1.4;
  animation: fs-flow-agent-bubble-enter var(--flow-dur-xl, 600ms) var(--flow-ease-spring, cubic-bezier(.34, 1.56, .64, 1));
}
.fs-flow-agent-bubble-text { margin: 0; }
.fs-flow-agent-bubble--typing {
  padding: 14px 16px;
  min-width: 56px;
  display: inline-flex;
  align-items: center;
}
.fs-flow-agent-bubble-dots {
  display: inline-flex;
  gap: 4px;
}
.fs-flow-agent-bubble-dots > span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--flow-ink-3);
  animation: fs-flow-agent-bubble-dot 1200ms ease-in-out infinite;
}
.fs-flow-agent-bubble-dots > span:nth-child(2) { animation-delay: 150ms; }
.fs-flow-agent-bubble-dots > span:nth-child(3) { animation-delay: 300ms; }
@keyframes fs-flow-agent-bubble-enter {
  from { opacity: 0; transform: translateY(8px) scale(.96); }
  to   { opacity: 1; transform: translateY(0)   scale(1); }
}
@keyframes fs-flow-agent-bubble-dot {
  0%, 80%, 100% { transform: scale(.6); opacity: .4; }
  40%           { transform: scale(1);  opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .fs-flow-agent-bubble { animation: none; }
  .fs-flow-agent-bubble-dots > span { animation: none; opacity: .6; }
}

/* ── flow/room_facts ───────────────────────────────────────────────────── */
.fs-flow-room-facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 24px;
  margin: 16px 0 0;
  padding: 16px;
  border-radius: var(--flow-r-card, 10px);
  background: var(--flow-surface-glass-06);
  border: 1px solid var(--flow-line);
}
.fs-flow-room-facts-row { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fs-flow-room-facts-label {
  font-family: var(--flow-font-ui);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--flow-ink-3);
  margin: 0;
}
.fs-flow-room-facts-value {
  font-family: var(--flow-font-ui, 'DM Sans', sans-serif);
  font-size: 14px;
  color: var(--flow-ink);
  margin: 0;
}

/* ── flow/booking_held_card ────────────────────────────────────────── */
.fs-flow-booking-held-card {
  padding: 20px;
  border-radius: var(--flow-r-card, 10px);
  background: var(--flow-surface-glass-08, rgba(255, 255, 255, 0.08));
  border: 1px solid var(--flow-gold-a30);
  box-shadow: var(--flow-shadow-card, 0 4px 12px rgba(0,0,0,.2));
  font-family: var(--flow-font-ui, 'DM Sans', sans-serif);
  color: var(--flow-ink);
}
.fs-flow-booking-held-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
.fs-flow-booking-held-title {
  font-family: var(--flow-font-display, 'Cormorant Garamond', Georgia, serif);
  font-size: 22px;
  font-weight: 600;
  margin: 0;
}
.fs-flow-booking-held-rows { margin: 0; display: grid; gap: 8px; }
.fs-flow-booking-held-row {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
}
.fs-flow-booking-held-row dt { color: var(--flow-ink-3); margin: 0; }
.fs-flow-booking-held-row dd { color: var(--flow-ink); margin: 0; }
.fs-flow-booking-held-row--total dd { font-weight: 600; }

/* ── flow/payment_card ─────────────────────────── */
.fs-flow-payment-card {
  padding: 20px;
  border-radius: var(--flow-r-card, 10px);
  background: linear-gradient(135deg, var(--flow-gold-a08) 0%, transparent 100%);
  border: 1px solid var(--flow-gold-a30);
  display: grid;
  gap: 12px;
  font-family: var(--flow-font-ui, 'DM Sans', sans-serif);
  color: var(--flow-ink);
}
.fs-flow-payment-title {
  font-family: var(--flow-font-display, 'Cormorant Garamond', Georgia, serif);
  font-size: 22px;
  font-weight: 600;
  margin: 0;
}
.fs-flow-payment-help { font-size: 13px; color: var(--flow-ink-2); margin: 0; }
.fs-flow-payment-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 12px 20px;
  border-radius: var(--flow-r-pill-lg, 50px);
  background: linear-gradient(135deg, var(--flow-gold-a30), var(--flow-gold-a40));
  border: 1px solid var(--flow-gold-a40);
  color: var(--flow-ink);
  font-weight: 600;
  text-decoration: none;
  letter-spacing: .04em;
  transition: background var(--flow-dur-sm, 250ms) var(--flow-ease-out, cubic-bezier(.22, 1, .36, 1));
}
.fs-flow-payment-link:hover { background: linear-gradient(135deg, var(--flow-gold-a40), var(--flow-gold-a60)); }

/* ── flow/confirmation_card ────────────────────────── */
.fs-flow-confirmation-card {
  padding: 24px 20px;
  border-radius: var(--flow-r-card, 10px);
  background: var(--flow-surface-glass-08, rgba(255, 255, 255, 0.08));
  border: 1px solid var(--flow-live-green-25);
  font-family: var(--flow-font-ui, 'DM Sans', sans-serif);
  color: var(--flow-ink);
  text-align: center;
}
.fs-flow-confirmation-icon {
  display: flex;
  justify-content: center;
  margin-bottom: 12px;
}
.fs-flow-confirmation-title {
  font-family: var(--flow-font-display, 'Cormorant Garamond', Georgia, serif);
  font-size: 24px;
  font-weight: 600;
  margin: 0 0 4px;
}
.fs-flow-confirmation-number {
  font-family: var(--flow-font-script, 'Sacramento', cursive);
  font-size: 22px;
  color: var(--flow-gold-ink, #d4c5a0);
  margin: 0 0 18px;
}
.fs-flow-confirmation-rows { margin: 0; display: grid; gap: 8px; text-align: left; }
.fs-flow-confirmation-row {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
}
.fs-flow-confirmation-row dt { color: var(--flow-ink-3); margin: 0; }
.fs-flow-confirmation-row dd { color: var(--flow-ink); margin: 0; }
.fs-flow-confirmation-row--total dd { font-weight: 600; }

/* ── flow/context_gathering ───────────────────────────────────────────── */
.fs-flow-gathering {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: var(--flow-bg);
  min-height: 0;
  width: 100%;
  height: 100%;
  /* Echo the widget modal's 16px radius so the scene panel - and the opaque
     slideshow photo at its right edge - reads as a soft rounded card inside
     the rounded iframe, not a hard square against it. overflow:hidden clips
     the carousel's bottom corners to the radius. */
  border-radius: 16px;
  overflow: hidden;
}
.fs-flow-gathering-facts {
  background: var(--flow-bg);
  padding: clamp(28px, 3.5vw, 56px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(20px, 2.5vw, 36px);
}
/* ── Entry reveal (compositor-only - no layout thrash) ────────────────────
   The scene enters as a FULL-BLEED photo; the black facts panel then SLIDES in
   from the left (a single `transform` - GPU-composited, no per-frame layout)
   to reveal the text. Animating grid-template-columns instead forces a layout
   recalc every frame → the flicker/thrash. The photo sits full-bleed behind;
   the panel's feathered right edge is the soft seam. Runs once per node mount
   (LiveView reuses the node on fact patches). Scoped off .fs-searching-with-
   context so the searching variant keeps its grid layout untouched. */
.fs-flow-gathering:not(.fs-searching-with-context) {
  display: block;
  position: relative;
}
.fs-flow-gathering:not(.fs-searching-with-context) .fs-flow-gathering-image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}
.fs-flow-gathering:not(.fs-searching-with-context) .fs-flow-gathering-facts {
  position: relative;
  z-index: 1;
  width: 50%;
  height: 100%;
  box-sizing: border-box;
  /* Feathered right edge = the soft seam into the photo (preserves the
     approved look: mostly-opaque black left, photo right). */
  -webkit-mask-image: linear-gradient(to right, var(--flow-ink-pure) 86%, transparent 100%);
  mask-image: linear-gradient(to right, var(--flow-ink-pure) 86%, transparent 100%);
  /* Plain fade-in on mount (replaced the prior slide-in-from-left reveal). */
  animation: fs-fade-in 0.5s var(--flow-ease-out, ease) both;
}
.fs-flow-gathering:not(.fs-searching-with-context) .fs-flow-gathering-caption {
  /* Photo is full-bleed now - keep the caption in the visible right half. */
  left: calc(50% + var(--flow-space-5, 20px));
}
@media (prefers-reduced-motion: reduce) {
  .fs-flow-gathering:not(.fs-searching-with-context) .fs-flow-gathering-facts {
    animation: none;
  }
}
.fs-flow-gathering-greeting {
  font-family: var(--flow-font-display);
  font-size: clamp(20px, 2vw, 28px);
  font-weight: 400;
  line-height: 1.2;
  color: var(--flow-ink);
  margin: 0;
}
.fs-flow-gathering-greeting-name {
  font-family: var(--flow-font-script);
  color: var(--flow-gold);
  margin-left: var(--flow-space-1);
}
.fs-flow-gathering-sentence {
  font-family: var(--flow-font-display);
  font-size: clamp(16px, 1.6vw, 22px);
  font-weight: 300;
  line-height: 1.55;
  color: var(--flow-ink-2);
  margin: 0;
  animation: fs-flow-gathering-appear var(--flow-dur-md) var(--flow-ease-out) both;
}
.fs-flow-gathering-highlight {
  color: var(--flow-gold);
  font-style: italic;
}
@keyframes fs-flow-gathering-appear {
  0%   { opacity: 0; transform: translateY(6px); }
  100% { opacity: 1; transform: translateY(0); }
}
.fs-flow-gathering-image {
  position: relative;
  overflow: hidden;
  background: var(--flow-bg);
}
.fs-flow-gathering-image-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.04);
  filter: saturate(1.05) brightness(.92);
}
/* Bottom fade for caption legibility - sanctioned room_hero treatment.
   The left-side fade smooths the seam where the image meets the dark
   facts column; it's specific to the split-scene layout. */
.fs-flow-gathering-image-fade {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 50%;
  background: var(--flow-gradient-hero-fade);
  pointer-events: none;
}
.fs-flow-gathering-image::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to right, var(--flow-bg-chip-dark) 0%, transparent 25%);
  pointer-events: none;
}
.fs-flow-gathering-caption {
  position: absolute;
  left: var(--flow-space-5);
  bottom: var(--flow-space-5);
  display: flex;
  flex-direction: column;
  z-index: 2;
}
.fs-flow-gathering-caption-name {
  font-family: var(--flow-font-display);
  font-size: clamp(22px, 2.4vw, 32px);
  font-weight: 600;
  line-height: 1.2;
  color: var(--flow-ink-pure);
  text-shadow: var(--flow-shadow-text-strong);
  margin: 0;
}
.fs-flow-gathering-caption-place {
  font-family: var(--flow-font-script);
  font-size: clamp(18px, 1.6vw, 22px);
  color: var(--flow-gold);
  text-shadow: var(--flow-shadow-text-soft);
  margin: 0;
}
@media (max-width: 720px) {
  .fs-flow-gathering { grid-template-columns: 1fr; }
  .fs-flow-gathering-image { aspect-ratio: 4 / 3; }
}
@media (prefers-reduced-motion: reduce) {
  .fs-flow-gathering-sentence { animation: none; }
}

/* ── "Reservation Pending" eyebrow ───────────────────────────────────────
   A quiet kicker above the cursive line - no box/badge (that read as a stamp).
   Small, letter-spaced, muted gold; sits left-aligned as a section label. */
.fs-gathering-pending {
  align-self: flex-start;
  font-family: var(--flow-font-ui, 'DM Sans', sans-serif);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--flow-gold-a60);
}

/* ── Cursive narrative ────────────────────────────────────────────────────
   Left-aligned editorial prose on the dark panel (no card to center within).
   Keeps the cursive display + script faces and gold highlights. */
.fs-gathering-narrative {
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: left;
  width: 100%;
}
.fs-gathering-narrative .fs-flow-gathering-greeting {
  font-size: clamp(22px, 2.1vw, 30px);
}
.fs-gathering-narrative .fs-flow-gathering-sentence {
  font-size: clamp(16px, 1.5vw, 21px);
  color: var(--flow-ink-65);
}

/* ── Right-side cross-fade slideshow (hotel + amenity photos) ─────────────
   Pure CSS: every image runs the SAME full-loop animation, staggered by
   `animation-delay = i * slide`. With `animation-duration = n * slide`,
   delay i/n lands each image's window on its 100/n% slot automatically -
   so the staggering self-scales to the image count. The keyframe's visible
   window (2%–22% ≈ an `n`-second span of the `5n`s loop) meets its neighbour
   only at EXACTLY n=5 - the windows just touch, with a brief ~50%-opacity dip
   at each hand-off. With FEWER than 5 photos the windows separate and the
   slideshow dips to BLACK between slides; with more than 5 they over-overlap.
   So this is tuned for exactly 5 (both current galleries - galeon + storyboard
   - are 5); changing the count means re-tuning the keyframe percentages.
   A slow scale adds a gentle Ken-Burns drift. */
.fs-gathering-carousel {
  position: absolute;
  inset: 0;
}
.fs-gathering-carousel-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(1.05) brightness(0.9);
}
/* Only the multi-photo (carousel) variant fades + animates. A SINGLE image
   (production's static `hero_url`, no gallery → no `--carousel` class) stays
   fully opaque and still - otherwise n=1 would flash once and sit black. */
.fs-flow-gathering-image--carousel .fs-gathering-carousel-img {
  opacity: 0;
  animation: fs-gathering-carousel-cross calc(var(--n) * 6s) ease-in-out infinite;
  animation-delay: calc(var(--i) * 6s);
}
@keyframes fs-gathering-carousel-cross {
  0%   { opacity: 0; }
  2%   { opacity: 1; }
  18%  { opacity: 1; }
  22%  { opacity: 0; }
  100% { opacity: 0; }
}

/* De-box: feather the photo edges so it melts into the dark ambiance
   instead of reading as a hard rectangle. Mask the carousel layer only
   (NOT the container) so the caption stays crisp. Two gradients composited:
   a strong left feather to dissolve the seam against the facts column, and
   a gentle top/bottom feather. */
.fs-flow-gathering-image--carousel .fs-gathering-carousel {
  -webkit-mask-image:
    linear-gradient(to right, transparent 0%, var(--flow-ink-pure) 16%, var(--flow-ink-pure) 100%),
    linear-gradient(to bottom, transparent 0%, var(--flow-ink-pure) 9%, var(--flow-ink-pure) 90%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0%, var(--flow-ink-pure) 16%, var(--flow-ink-pure) 100%),
    linear-gradient(to bottom, transparent 0%, var(--flow-ink-pure) 9%, var(--flow-ink-pure) 90%, transparent 100%);
  mask-composite: intersect;
}
/* With the carousel feathered, the old hard left-seam overlay is redundant
   and would re-introduce a crisp band - drop it for the carousel variant. */
.fs-flow-gathering-image--carousel::before { display: none; }
@media (prefers-reduced-motion: reduce) {
  .fs-flow-gathering-image--carousel .fs-gathering-carousel-img { animation: none; }
  .fs-flow-gathering-image--carousel .fs-gathering-carousel-img:first-child { opacity: 1; }
}

/* Placeholder scenes - render when a workflow node references a visual
   that hasn't been designed yet. Honest, dimmed, surfaces the gap. */
.fs-scene-placeholder {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  min-height: 360px;
  padding: 24px;
}
.fs-scene-placeholder-frame {
  max-width: 460px;
  padding: 32px 36px;
  background: var(--flow-surface-glass-06);
  border: 1px dashed var(--flow-ink-30);
  border-radius: 18px;
  text-align: center;
  color: var(--flow-ink-3);
}
.fs-scene-placeholder-eyebrow {
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--flow-gold-ink, #d4c5a0);
  margin-bottom: 12px;
}
.fs-scene-placeholder-title {
  font-size: 22px;
  font-weight: 600;
  color: var(--flow-ink);
  margin: 0 0 12px;
}
.fs-scene-placeholder-desc {
  font-size: 13px;
  line-height: 1.55;
  color: var(--flow-ink-3);
  margin: 0;
}

/* ════════════════════════════════════════════════════════════════════════
   Canonical scene body rules - relocated 2026-05-05 from
   flowvue_components.css (where they were trapped under #slot-a). These
   describe the body content of the booking-arc scenes (channel chooser,
   home grid, submenu, searching, room select, enhance, payment,
   confirmation, brand bar, captions, progress) and must be reachable
   from the production widget shell, not just the storyboard.

   Containing block: any consumer must provide a `position: relative`
   ancestor for rules that use `position: absolute; inset: 0`. The
   production widget's `.fs-body` provides this; the storyboard's
   `.fs-modal` does too via its `transform: scale()` (creates a
   containing block).
   ════════════════════════════════════════════════════════════════════════ */

/* ── Channel chooser ────────────────────────────────────────────────── */
.fs-chooser-tint { position: absolute; inset: 0; z-index: 120; background: rgba(0,0,0,.3); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .4s ease, visibility .4s ease; }
.fs-chooser-tint.open { opacity: 1; visibility: visible; }
.fs-chooser { position: absolute; bottom: clamp(48px, 7.6vw, 68px); right: clamp(8px, 1.6vw, 16px); z-index: 135; display: flex; flex-direction: column; gap: clamp(5px, 0.8vw, 8px); pointer-events: none; }
.fs-chooser.open { pointer-events: auto; }
/* Chooser pill - shared geometry + motion. Variants set bg/border/color. */
.fs-chooser-opt { display: flex; align-items: center; gap: clamp(8px, 1.2vw, 10px); padding: clamp(8px, 1.2vw, 10px) clamp(12px, 1.8vw, 18px) clamp(8px, 1.2vw, 10px) clamp(10px, 1.4vw, 14px); border-radius: var(--flow-r-pill-lg); cursor: pointer; backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); opacity: 0; transform: translateY(24px) scale(.88); transition: opacity .35s ease, transform .4s var(--flow-ease-out-snappy), background .25s, border-color .25s, box-shadow .25s; }
.fs-chooser.open .fs-chooser-opt { opacity: 1; transform: translateY(0) scale(1); }

/* Icon circle inside any chooser pill - 24×24, the variant tints it. */
.fs-chooser-opt .fs-chooser-icon { width: 24px; height: 24px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; transition: background .25s, border-color .25s, color .25s; }
.fs-chooser-opt .fs-chooser-icon svg { width: 12px; height: 12px; }

/* Label stack - name + descriptor. */
.fs-chooser-opt .fs-chooser-label { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fs-chooser-opt .fs-chooser-name { font-family: var(--flow-font-ui); font-size: 11px; font-weight: 600; white-space: nowrap; }
.fs-chooser-opt .fs-chooser-desc { font-family: var(--flow-font-ui); font-size: 7px; font-weight: 500; letter-spacing: .04em; color: rgba(255,255,255,.45); white-space: nowrap; }

/* Primary - Voice (gold). The brand's signature pill: a 135° gold
   gradient body, gold border, gold icon circle, gold-warm name.
   Spec: `_components.css §.fv-pill--gold` + chooser preview's
   `.opt.primary`. */
.fs-chooser-opt.voice { background: linear-gradient(135deg, var(--flow-gold-a15) 0%, var(--flow-gold-deep-a10) 100%); border: 1px solid var(--flow-gold-a30); box-shadow: 0 4px 20px var(--flow-gold-a12); color: var(--flow-gold-ink); }
.fs-chooser-opt.voice:hover { background: linear-gradient(135deg, var(--flow-gold-a25) 0%, var(--flow-gold-deep-a18) 100%); border-color: var(--flow-gold-a40); transform: translateY(-1px); }
.fs-chooser-opt.voice .fs-chooser-icon { background: var(--flow-gold-a15); border: 1px solid var(--flow-gold-a30); color: var(--flow-gold); }
.fs-chooser-opt.voice .fs-chooser-name { color: var(--flow-gold-ink); }

/* Secondary - Text (neutral ghost). */
.fs-chooser-opt.text { background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.08); box-shadow: var(--flow-shadow-card); color: rgba(255,255,255,.7); }
.fs-chooser-opt.text:hover { background: rgba(255,255,255,.09); border-color: rgba(255,255,255,.14); transform: translateY(-1px); }
.fs-chooser-opt.text .fs-chooser-icon { background: var(--flow-tint-2); border: 1px solid var(--flow-line); color: rgba(255,255,255,.55); }
.fs-chooser-opt.text .fs-chooser-name { color: rgba(255,255,255,.78); }

/* Hover lift only when chooser is actually open. */
.fs-chooser:not(.open) .fs-chooser-opt:hover { transform: translateY(24px) scale(.88); }

/* ── Modal frame (booking arc) - `.fs-overlay` only ─────────────────────
   `.fs-modal` itself is defined later in the file (full-bleed canvas +
   glass shell block). The earlier `.fs-modal` declarations + the
   `.fs-overlay.open .fs-modal{transform:scale(1);opacity:1}` pairing
   were removed in the Phase C dedupe (Task #6) - they were
   cascade-shadowed by the later block (`position:fixed; inset:4% 4%;
   display:grid; animation:fs-modal-in`) and the entry-state choreography
   was redundant with the animation. The overlay tint + gating still
   applies to the storyboard, which renders a `.fs-overlay` wrapper
   around the modal; the production widget at `/widget/:slug` does not
   wrap the modal in an overlay (see widget_shell.ex). */
.fs-overlay{position:absolute;inset:0;z-index:150;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.40);opacity:0;visibility:hidden;pointer-events:none}
.fs-overlay.open{opacity:1;visibility:visible;pointer-events:auto}

/* ── BRAND BAR ──────────────────────────────────────────────────────── */
.fs-brand-bar{position:relative;height:clamp(28px, 4vw, 40px);z-index:200;display:flex;align-items:center;padding:0 clamp(8px, 1.6vw, 16px);border-bottom:1px solid rgba(255,255,255,.08);flex-shrink:0;gap:clamp(8px, 1.4vw, 14px)}
.fs-brand-logo{font-family:'Cormorant Garamond',serif;font-size:clamp(11px, 1.55vw, 16px);font-weight:600;color:rgba(255,255,255,.75);line-height:1;flex-shrink:0}
.fs-brand-logo small{display:block;font-size:clamp(6px, 0.8vw, 8px);font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.3);margin-top:1px}
.fs-brand-voice{display:flex;align-items:center;gap:clamp(6px, 1vw, 10px);flex-shrink:0;margin-left:auto}
.fs-vb-live{display:flex;align-items:center;gap:clamp(3px,0.5vw,5px);padding:clamp(2px,0.3vw,3px) clamp(5px,0.8vw,8px) clamp(2px,0.3vw,3px) clamp(5px,0.7vw,7px);border-radius:20px;background:rgba(0,0,0,.3);border:1px solid rgba(74,222,128,.25);font-size:clamp(6px,0.75vw,8px);font-weight:700;letter-spacing:.12em;color:rgba(255,255,255,.85);flex-shrink:0}
.fs-vb-dot{width:4px;height:4px;border-radius:50%;background:var(--flow-live-green);box-shadow:0 0 5px rgba(74,222,128,.6);animation:livePulse 2s ease-in-out infinite}
@keyframes livePulse{0%,100%{opacity:1;box-shadow:0 0 6px rgba(74,222,128,.6)}50%{opacity:.5;box-shadow:0 0 10px rgba(74,222,128,.8)}}
.fs-vb-agent{font-size:clamp(9px, 1.2vw, 12px);font-weight:600;color:rgba(255,255,255,.85)}
.fs-vb-timer{font-size:clamp(8px,0.9vw,10px);font-weight:500;color:rgba(255,255,255,.5);font-variant-numeric:tabular-nums;flex-shrink:0}
.fs-waveform{display:flex;align-items:center;gap:clamp(1.5px,0.22vw,2.5px);height:clamp(12px,1.6vw,18px);width:clamp(80px,10vw,130px);opacity:0.35;transition:opacity .3s;flex-shrink:0}
.fs-waveform.active{opacity:1}
.fs-wf-bar{width:clamp(1.5px, 0.25vw, 2.5px);border-radius:1px;background:rgba(255,255,255,.12);height:12%;transition:background .3s}
.fs-waveform.agent .fs-wf-bar{background:var(--flow-gold);opacity:.55}
.fs-waveform.guest .fs-wf-bar{background:var(--flow-guest-blue);opacity:.55}
/* Agent - slow, gentle AI cadence with fading */
.fs-waveform.agent .fs-wf-bar:nth-child(1){animation:vA1 5.0s ease-in-out infinite}
.fs-waveform.agent .fs-wf-bar:nth-child(2){animation:vA2 4.2s ease-in-out infinite}
.fs-waveform.agent .fs-wf-bar:nth-child(3){animation:vA3 3.6s ease-in-out infinite}
.fs-waveform.agent .fs-wf-bar:nth-child(4){animation:vA4 4.6s ease-in-out infinite}
.fs-waveform.agent .fs-wf-bar:nth-child(5){animation:vA5 3.8s ease-in-out infinite}
.fs-waveform.agent .fs-wf-bar:nth-child(6){animation:vA6 3.2s ease-in-out infinite}
.fs-waveform.agent .fs-wf-bar:nth-child(7){animation:vA7 4.8s ease-in-out infinite}
.fs-waveform.agent .fs-wf-bar:nth-child(8){animation:vA8 3.6s ease-in-out infinite}
.fs-waveform.agent .fs-wf-bar:nth-child(9){animation:vA9 4.4s ease-in-out infinite}
.fs-waveform.agent .fs-wf-bar:nth-child(10){animation:vA10 5.2s ease-in-out infinite}
/* Guest - moderate, human speech */
.fs-waveform.guest .fs-wf-bar:nth-child(1){animation:vG1 3.2s ease-in-out infinite}
.fs-waveform.guest .fs-wf-bar:nth-child(2){animation:vG2 2.6s ease-in-out infinite}
.fs-waveform.guest .fs-wf-bar:nth-child(3){animation:vG3 2.2s ease-in-out infinite}
.fs-waveform.guest .fs-wf-bar:nth-child(4){animation:vG4 3.0s ease-in-out infinite}
.fs-waveform.guest .fs-wf-bar:nth-child(5){animation:vG5 2.4s ease-in-out infinite}
.fs-waveform.guest .fs-wf-bar:nth-child(6){animation:vG6 2.0s ease-in-out infinite}
.fs-waveform.guest .fs-wf-bar:nth-child(7){animation:vG7 2.8s ease-in-out infinite}
.fs-waveform.guest .fs-wf-bar:nth-child(8){animation:vG8 2.3s ease-in-out infinite}
.fs-waveform.guest .fs-wf-bar:nth-child(9){animation:vG9 2.7s ease-in-out infinite}
.fs-waveform.guest .fs-wf-bar:nth-child(10){animation:vG10 3.4s ease-in-out infinite}
/* Agent keyframes - syllable bursts with word-boundary rests (outer bars shorter) */
@keyframes vA1{0%,100%{height:10%}8%{height:42%}16%{height:12%}28%{height:50%}36%{height:15%}52%{height:38%}64%{height:10%}78%{height:45%}88%{height:12%}}
@keyframes vA2{0%,100%{height:12%}10%{height:65%}18%{height:20%}30%{height:72%}40%{height:14%}55%{height:58%}68%{height:18%}80%{height:62%}90%{height:15%}}
@keyframes vA3{0%,100%{height:15%}7%{height:80%}15%{height:28%}25%{height:88%}35%{height:18%}48%{height:75%}58%{height:22%}72%{height:82%}82%{height:20%}}
@keyframes vA4{0%,100%{height:14%}9%{height:90%}17%{height:25%}28%{height:95%}38%{height:16%}50%{height:85%}62%{height:20%}75%{height:92%}86%{height:18%}}
@keyframes vA5{0%,100%{height:16%}8%{height:95%}16%{height:30%}26%{height:100%}36%{height:18%}48%{height:90%}60%{height:25%}74%{height:95%}85%{height:20%}}
@keyframes vA6{0%,100%{height:14%}10%{height:88%}19%{height:22%}30%{height:92%}40%{height:15%}52%{height:82%}64%{height:20%}76%{height:88%}87%{height:16%}}
@keyframes vA7{0%,100%{height:13%}7%{height:78%}16%{height:20%}27%{height:82%}37%{height:14%}50%{height:72%}62%{height:18%}75%{height:78%}86%{height:15%}}
@keyframes vA8{0%,100%{height:12%}9%{height:62%}18%{height:18%}29%{height:68%}39%{height:14%}52%{height:58%}65%{height:16%}78%{height:64%}88%{height:13%}}
@keyframes vA9{0%,100%{height:11%}8%{height:52%}17%{height:15%}28%{height:58%}38%{height:12%}50%{height:48%}63%{height:14%}76%{height:54%}87%{height:12%}}
@keyframes vA10{0%,100%{height:10%}10%{height:38%}20%{height:12%}32%{height:44%}42%{height:10%}55%{height:35%}68%{height:12%}80%{height:40%}90%{height:10%}}
/* Guest keyframes - spikier, more irregular human speech */
@keyframes vG1{0%,100%{height:12%}6%{height:48%}12%{height:10%}22%{height:55%}30%{height:14%}45%{height:42%}56%{height:10%}70%{height:50%}80%{height:12%}}
@keyframes vG2{0%,100%{height:14%}8%{height:72%}14%{height:18%}24%{height:80%}34%{height:12%}48%{height:65%}58%{height:16%}72%{height:75%}84%{height:14%}}
@keyframes vG3{0%,100%{height:16%}5%{height:92%}12%{height:22%}20%{height:98%}28%{height:15%}40%{height:85%}50%{height:20%}65%{height:95%}76%{height:18%}}
@keyframes vG4{0%,100%{height:15%}7%{height:100%}13%{height:28%}22%{height:95%}32%{height:14%}44%{height:90%}54%{height:22%}68%{height:100%}78%{height:16%}}
@keyframes vG5{0%,100%{height:18%}6%{height:95%}14%{height:25%}24%{height:100%}34%{height:16%}46%{height:88%}56%{height:28%}70%{height:95%}82%{height:18%}}
@keyframes vG6{0%,100%{height:15%}8%{height:90%}15%{height:20%}26%{height:95%}36%{height:14%}48%{height:82%}60%{height:18%}74%{height:92%}85%{height:15%}}
@keyframes vG7{0%,100%{height:13%}7%{height:75%}14%{height:18%}25%{height:82%}35%{height:12%}47%{height:70%}58%{height:16%}72%{height:78%}83%{height:14%}}
@keyframes vG8{0%,100%{height:12%}9%{height:60%}16%{height:15%}26%{height:68%}36%{height:12%}50%{height:55%}62%{height:14%}75%{height:62%}86%{height:12%}}
@keyframes vG9{0%,100%{height:11%}8%{height:48%}16%{height:13%}27%{height:55%}37%{height:11%}50%{height:44%}62%{height:13%}76%{height:50%}87%{height:11%}}
@keyframes vG10{0%,100%{height:10%}10%{height:35%}18%{height:11%}30%{height:40%}40%{height:10%}54%{height:32%}66%{height:11%}78%{height:38%}88%{height:10%}}
.fs-brand-step{font-family:'DM Sans',sans-serif;font-size:clamp(9px, 1.1vw, 11px);font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.55);opacity:0;transition:opacity .4s;pointer-events:none;line-height:1;text-align:right;margin-left:auto}
.fs-brand-step.visible{opacity:1}
.fs-brand-actions{display:flex;align-items:center;gap:6px;z-index:2;flex-shrink:0}
.fs-mute-btn{position:relative}
.fs-mute-btn.muted::after{content:'';position:absolute;top:3px;left:50%;width:1.5px;height:70%;background:rgba(255,255,255,.6);transform:translateX(-50%) rotate(-45deg);border-radius:1px}

.fs-brand-nav {
  display: inline-flex;
  gap: 8px;
  margin-right: 16px;
  align-items: center;
}
.fs-brand-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(26px, 3.2vw, 32px);
  height: clamp(26px, 3.2vw, 32px);
  padding: 0;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, .12);
  background: rgba(255, 255, 255, .06);
  color: rgba(255, 255, 255, .55);
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.fs-brand-nav-btn:hover:not(:disabled) {
  background: rgba(212, 168, 83, .12);
  color: rgba(255, 255, 255, .92);
  border-color: rgba(212, 168, 83, .25);
}
.fs-brand-nav-btn:disabled {
  opacity: .35;
  cursor: not-allowed;
}
.fs-brand-nav-btn svg {
  width: 14px;
  height: 14px;
}

/* ── MAIN CONTENT ───────────────────────────────────────────────────── */
.fs-main{position:relative;flex:1;overflow:hidden;display:flex;flex-direction:column;min-height:0}

/* Home Grid - .fs-home-grid is the grid container; no inner wrapper. */
.fs-home-grid{position:absolute;inset:0;z-index:80;display:grid;grid-template-columns:repeat(2,1fr);grid-auto-rows:1fr;gap:clamp(4px, 0.8vw, 8px);padding:clamp(5px, 1vw, 10px) clamp(7px, 1.4vw, 14px);box-sizing:border-box;opacity:1;transition:opacity .5s ease,visibility .5s ease}
.fs-home-grid.hidden{opacity:0;visibility:hidden;pointer-events:none;display:none}

/* Composed Explore Board (§1.0-048) - the N>1 grouped curated grid. Unlike the
   flat .fs-home-grid (one absolute-inset 2-col grid), the board stacks labelled
   sections, each its OWN 2-col grid mirroring the home grid's columns/gap/aspect
   so tiles share the same lockup. The board fills the stage on the dark ground
   and scrolls if the groups overflow. */
.fs-explore-board{position:absolute;inset:0;z-index:80;display:flex;flex-direction:column;gap:clamp(6px, 1.2vw, 12px);padding:clamp(5px, 1vw, 10px) clamp(7px, 1.4vw, 14px);box-sizing:border-box;overflow-y:auto;background:var(--flow-bg)}
.fs-explore-board-group{display:flex;flex-direction:column;gap:clamp(3px, 0.6vw, 6px)}
.fs-explore-board-group-label{margin:0;font-family:var(--flow-font-display);font-size:clamp(13px, 1.6vw, 17px);font-weight:600;letter-spacing:var(--flow-tracking-caps);text-transform:uppercase;color:var(--flow-ink)}
.fs-explore-board-grid{display:grid;grid-template-columns:repeat(2,1fr);grid-auto-rows:clamp(120px, 16vw, 200px);gap:clamp(4px, 0.8vw, 8px);box-sizing:border-box}

/* Demo prompt - hand-drawn arrow + cream-card caption on the demo
   marketing page (/demos/galeon) pointing at the floating "Speak with
   Reservations" pill at bottom-right. The pill is mounted by the embed
   loader inside a closed shadow DOM at `position:fixed; bottom:8-16px;
   right:8-16px`. The overlay sits well to the left of the pill so the
   arrow has a long diagonal sweep down-right into it. Pointer-events
   disabled so the pill stays clickable. */
.fs-demo-prompt {
  position: fixed;
  bottom: clamp(90px, 11vh, 150px);
  right: clamp(160px, 17vw, 260px);
  width: clamp(260px, 30vw, 380px);
  z-index: 2147483646;
  color: var(--flow-gold);
  pointer-events: none;
}
.fs-demo-prompt-label {
  /* Cream parchment card: warm off-white so the gold ink reads cleanly
     against the photo background. Subtle gold border + shadow give it
     a hand-pinned, sticky-note feel. */
  display: inline-block;
  background: rgba(250, 246, 236, 0.96);
  color: #5c421f;
  font-family: 'Sacramento', cursive;
  font-size: clamp(22px, 2.6vw, 34px);
  line-height: 1.05;
  text-align: center;
  padding: 12px 22px 16px;
  border-radius: 14px;
  border: 1px solid var(--flow-gold-a45);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35),
              inset 0 1px 0 rgba(255, 255, 255, 0.7);
  transform: rotate(-3deg);
  transform-origin: bottom left;
}
.fs-demo-prompt-label em {
  font-style: normal;
  display: block;
  margin-top: 4px;
  font-size: 1em;
  color: #5c421f;
}
.fs-demo-prompt-label small {
  display: block;
  font-family: var(--flow-font-ui, 'DM Sans', sans-serif);
  font-size: 0.36em;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #8a6c3f;
  margin-bottom: 8px;
  font-weight: 600;
}
.fs-demo-prompt-arrow {
  /* SVG extends visually past the cream card so the arrow's tip lands
     well to the right - closer to the pill the user is meant to tap.
     `width: 110%` plus negative right margin pushes the right edge
     beyond the overlay container. */
  width: 110%;
  height: auto;
  display: block;
  margin-left: auto;
  margin-right: -10%;
  margin-top: -8px;
  transform: rotate(-1deg);
  /* Strokes against varied photo backgrounds need a touch of darkness
     and a soft gold halo to read at any zoom. */
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6))
          drop-shadow(0 0 0.5px var(--flow-gold-a45));
}

/* Sub-menu */
.fs-submenu{position:absolute;inset:0;z-index:85;display:flex;flex-direction:column;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .5s ease,visibility .5s ease}
.fs-submenu.visible{opacity:1;visibility:visible;pointer-events:auto}
.fs-submenu-grid{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1.3fr 1fr;gap:clamp(4px, 0.8vw, 8px);padding:clamp(5px, 1vw, 10px) clamp(7px, 1.4vw, 14px);flex:1;min-height:0}
.fs-submenu-card.sm-new{grid-column:1/-1}
.fs-submenu-card img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.fs-submenu-card.pulse{box-shadow:0 0 0 2px var(--flow-gold-a50),0 8px 24px rgba(0,0,0,.4)}

/* Searching - legacy centered overlay (storyboard / no-context fallback) */
.fs-searching{position:absolute;inset:0;z-index:90;display:flex;flex-direction:column;align-items:center;justify-content:center;opacity:0;transition:opacity .5s;pointer-events:none}
.fs-searching.visible{opacity:1}
.fs-search-content{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;gap:10px}
.fs-search-dots{display:flex;gap:7px}
.fs-search-dot{width:8px;height:8px;border-radius:50%;background:var(--flow-ink-pure);animation:sDot 1.4s ease-in-out infinite}
.fs-search-dot:nth-child(2){animation-delay:.16s}.fs-search-dot:nth-child(3){animation-delay:.32s}
@keyframes sDot{0%,80%,100%{transform:scale(.4);opacity:.4}40%{transform:scale(1);opacity:1}}
.fs-search-text{font-size:clamp(8px, 1.1vw, 11px);letter-spacing:.08em;color:rgba(255,255,255,.6);text-transform:uppercase}
.fs-search-subtext{font-size:clamp(8px, 1.05vw, 11px);color:var(--flow-ink-30);text-align:center;max-width:38ch;line-height:1.5;letter-spacing:.01em;margin-top:var(--flow-space-1)}

/* Searching - with-context layout (replaces hero image with a calm loading
   panel; left column reuses .fs-flow-gathering-facts unchanged). The outer
   .fs-flow-gathering wrapper carries the 2-col grid + bg; this panel fills
   the slot the hero image normally occupies. Mr. Cobb 2026-05-09. */
.fs-searching-panel {
  position: relative;
  background: var(--flow-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.fs-searching-panel::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to right, var(--flow-bg-chip-dark) 0%, transparent 25%);
  pointer-events: none;
}
.fs-searching-panel-content {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 1.6vw, 22px);
  padding: clamp(28px, 3.5vw, 56px);
  text-align: center;
}
.fs-searching-panel-label {
  font-family: var(--flow-font-display);
  font-size: clamp(14px, 1.4vw, 18px);
  font-weight: 300;
  color: var(--flow-ink-2);
  letter-spacing: .04em;
  margin: 0;
}
.fs-searching-panel-detail {
  font-family: var(--flow-font-display);
  font-size: clamp(13px, 1.2vw, 16px);
  font-weight: 300;
  color: var(--flow-ink-3);
  margin: 0;
}
@media (max-width: 720px) {
  .fs-searching-with-context { grid-template-columns: 1fr; }
  .fs-searching-panel { aspect-ratio: 4 / 3; }
}

/* ═══════════════════════════════════════ */
/* ── ROOM CONTENT: Hero-Left + Cards-Right */
/* ═══════════════════════════════════════ */
.fs-room-content{display:none;flex-direction:column;flex:1;min-height:0;opacity:0;transition:opacity .5s ease}
.fs-room-content.visible{display:flex;opacity:1}

/* Date strip - typography sizes per component-date-strip.html. */
.fs-date-strip{display:flex;align-items:center;gap:clamp(16px, 2.4vw, 24px);padding:clamp(10px, 1.4vw, 14px) clamp(14px, 1.8vw, 18px);flex-shrink:0}
.fs-date-item{display:flex;align-items:center;gap:clamp(6px, 0.8vw, 8px);opacity:0;transform:translateY(4px);transition:opacity .5s ease,transform .5s ease}
.fs-date-item.filled{opacity:1;transform:translateY(0)}
/* CHECK-IN / CHECK-OUT mini-cap */
.fs-date-label{font-size:clamp(8px, 0.9vw, 9px);font-weight:600;letter-spacing:var(--flow-tracking-caps);text-transform:uppercase;color:rgba(255,255,255,.42)}
/* The actual date - Mar 12 / Jul 4 - tabular for line-up. */
.fs-date-val{font-family:var(--flow-font-ui);font-size:clamp(12px, 1.4vw, 14px);font-weight:600;color:rgba(255,255,255,.94);font-variant-numeric:tabular-nums;letter-spacing:-.005em;white-space:nowrap}
.fs-date-sep{font-size:clamp(9px, 1.1vw, 12px);color:rgba(255,255,255,.22);flex-shrink:0;opacity:0;transition:opacity .4s ease .2s}
.fs-date-sep.filled{opacity:1}
.fs-date-dot{width:3px;height:3px;border-radius:50%;background:rgba(255,255,255,.22);flex-shrink:0;opacity:0;transition:opacity .4s ease .4s}
.fs-date-dot.filled{opacity:1}
.fs-guests-display{font-size:clamp(11px, 1.3vw, 13px);font-weight:500;color:rgba(255,255,255,.72);font-variant-numeric:tabular-nums;opacity:0;transition:opacity .4s ease .5s;white-space:nowrap}
.fs-guests-display.filled{opacity:1}
.fs-nights{font-size:clamp(11px, 1.3vw, 13px);font-weight:400;color:rgba(255,255,255,.45);opacity:0;transition:opacity .4s ease .6s;white-space:nowrap}
.fs-nights.filled{opacity:1}
/* "See all rooms" - gold-warm, NOT white-55. The single warm accent
   on this strip; pulls focus right toward the rooms grid. */
.fs-see-all-inline{font-size:clamp(10px, 1.2vw, 12px);color:var(--flow-gold-ink);font-weight:500;margin-left:auto;opacity:0;transition:opacity .25s ease .7s,color .25s ease;white-space:nowrap}
.fs-see-all-inline.filled{opacity:1}
.fs-see-all-inline:hover{color:var(--flow-gold)}

/* Split layout */
.fs-split{display:flex;flex:1;min-height:0;gap:0}
.fs-hero-wrap{flex:0 0 60%;position:relative;overflow:hidden;margin:0 0 clamp(4px, 0.8vw, 8px) clamp(7px, 1.4vw, 14px);border-radius:clamp(8px, 1.2vw, 12px)}
.fs-hero-frames{position:absolute;inset:0}
.fs-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;will-change:opacity;opacity:0;transition:opacity .8s ease}
.fs-hero-img.is-active{opacity:1}
@keyframes fsKB1{0%{transform:scale(1.0) translate(0,0)}100%{transform:scale(1.18) translate(-3%,-2.5%)}}
@keyframes fsKB2{0%{transform:scale(1.02) translate(-1%,0)}100%{transform:scale(1.2) translate(2%,-3%)}}
.fs-hero-gradient{position:absolute;bottom:0;left:0;right:0;height:50%;background:linear-gradient(to top,rgba(0,0,0,.55) 0%,transparent 100%);pointer-events:none}
.fs-hero-info{position:absolute;bottom:clamp(8px, 1.6vw, 16px);left:clamp(10px, 2vw, 20px);z-index:2}
.fs-hero-name{font-family:'Cormorant Garamond',serif;font-size:clamp(14px, 2vw, 20px);font-weight:600;color:var(--flow-ink-pure);line-height:1.2;margin-bottom:2px;text-shadow:0 1px 8px rgba(0,0,0,.6)}
.fs-hero-price{font-family:'DM Sans',sans-serif;font-size:clamp(9px, 1.2vw, 12px);font-weight:700;color:var(--flow-live-green);text-shadow:0 1px 4px rgba(0,0,0,.5)}
.fs-hero-cta{margin-top:clamp(6px,1vw,9px);display:inline-flex;align-items:center;gap:5px;padding:clamp(6px,0.8vw,8px) clamp(12px,1.6vw,16px);border-radius:999px;background:rgba(20,16,12,.55);border:1px solid var(--flow-gold-a40);color:var(--flow-gold);font-family:var(--flow-font-ui);font-size:clamp(10px,1.2vw,12px);font-weight:600;letter-spacing:.03em;cursor:pointer;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);transition:background .15s ease,transform .1s ease;text-shadow:0 1px 3px rgba(0,0,0,.4)}
.fs-hero-cta:hover{background:rgba(20,16,12,.74)}
.fs-hero-cta:active{transform:scale(.97)}
.fs-hero-dots{position:absolute;bottom:clamp(8px, 1.6vw, 16px);right:clamp(10px, 2vw, 20px);z-index:2;display:flex;gap:clamp(4px, 0.6vw, 6px)}
.fs-dot{width:6px;height:6px;border-radius:50%;background:rgba(255,255,255,.3);transition:background .3s}.fs-dot.active{background:rgba(255,255,255,.9)}

/* Cards column */
.fs-cards-col{flex:0 0 40%;display:flex;flex-direction:column;gap:clamp(4px, 0.8vw, 8px);padding:0 clamp(28px, 4.4vw, 44px) clamp(6px, 1vw, 10px) clamp(28px, 4.4vw, 44px);min-height:0}
.fs-room-card{flex:1;min-height:0;border-radius:clamp(6px, 1vw, 10px);overflow:hidden;border:1px solid rgba(255,255,255,.12);position:relative;animation:cardSlide .4s ease forwards;opacity:0;cursor:pointer;transition:border-color .3s,box-shadow .3s;clip-path:inset(0 round clamp(6px, 1vw, 10px))}
.fs-room-card:nth-child(1){animation-delay:.1s}.fs-room-card:nth-child(2){animation-delay:.2s}.fs-room-card:nth-child(3){animation-delay:.3s}
.fs-room-card.selected{border-color:rgba(212,168,83,.95)}
/* Focus ring for the room shown in the main hero. A ::after overlay (above the
   image, z-index 3) because the card's clip-path clips outset box-shadow and an
   inset shadow would sit behind the absolutely-positioned image. */
.fs-room-card.selected::after{content:"";position:absolute;inset:0;border:2px solid rgba(212,168,83,.95);border-radius:inherit;box-shadow:inset 0 0 14px rgba(212,168,83,.45);pointer-events:none;z-index:3}
.fs-room-card:not(.selected){opacity:.45;transition:opacity .3s,border-color .3s}
@keyframes cardSlide{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:translateX(0)}}
.fs-card-img{position:absolute;inset:0;overflow:hidden}
.fs-card-img img{width:100%;height:100%;object-fit:cover}
.fs-card-body{position:absolute;bottom:0;left:0;right:0;padding:clamp(3px, 0.6vw, 6px) clamp(4px, 0.7vw, 7px);background:linear-gradient(to top,rgba(0,0,0,.8) 0%,rgba(0,0,0,.4) 60%,transparent 100%);z-index:2}
.fs-card-name{font-family:'Cormorant Garamond',serif;font-size:clamp(14px, 1.7vw, 18px);font-weight:600;color:var(--flow-ink-pure);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 1px 4px rgba(0,0,0,.6)}
.fs-card-price{font-size:clamp(12px, 1.4vw, 15px);font-weight:700;color:var(--flow-live-green);text-shadow:0 1px 3px rgba(0,0,0,.5)}

/* ── ROOM DETAIL ─────────────────────────────────────────────────────
   Single-room expanded view rendered when `focused_room_id` is set but
   no enhancements have been offered yet. Reuses the date strip from
   `room_select`; adds hero + description + facts row + amenity chips.
   No alternates column - the caller is past picking. */
.fs-room-detail{display:flex;flex-direction:column;flex:1;min-height:0;opacity:1}
.fs-room-detail-content{flex:1 1 0;min-height:0;display:flex;gap:clamp(10px,1.6vw,18px);padding:clamp(8px,1.4vw,14px) clamp(10px,1.6vw,16px);align-items:stretch}
.fs-room-detail-hero{position:relative;flex:1 1 0;min-width:0;align-self:stretch;border-radius:clamp(8px,1.2vw,12px);overflow:hidden;border:1px solid var(--flow-line)}
.fs-room-detail-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;will-change:transform;animation:fsKB1 8s ease-in-out infinite alternate;transition:transform .8s ease-in-out}
.fs-room-detail-gradient{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 40%,rgba(0,0,0,.6) 100%);pointer-events:none}
.fs-room-detail-overlay{position:absolute;left:clamp(12px,2vw,20px);bottom:clamp(10px,1.6vw,16px);right:clamp(12px,2vw,20px);z-index:2;display:flex;flex-direction:column;gap:2px}
.fs-room-detail-name{font-family:'Cormorant Garamond',serif;font-size:clamp(18px,2.6vw,28px);font-weight:600;color:var(--flow-ink-pure);line-height:1.15;letter-spacing:-.005em;text-shadow:0 1px 8px rgba(0,0,0,.6)}
.fs-room-detail-price{font-family:'DM Sans',sans-serif;font-size:clamp(11px,1.4vw,14px);font-weight:700;color:var(--flow-live-green);text-shadow:0 1px 4px rgba(0,0,0,.5)}
.fs-room-detail-body{flex:1 1 0;min-width:0;min-height:0;display:flex;flex-direction:column;gap:clamp(10px,1.4vw,14px);padding:clamp(4px,0.6vw,8px) clamp(4px,0.8vw,10px);overflow-y:auto}
.fs-room-detail-desc{font-family:var(--flow-font-ui);font-size:clamp(12px,1.4vw,14px);font-weight:400;color:var(--flow-ink-65);line-height:1.55;margin:0;max-width:62ch}
.fs-room-detail-facts{display:flex;flex-wrap:wrap;gap:clamp(12px,2vw,20px) clamp(20px,3vw,32px);padding:clamp(8px,1.2vw,12px) 0;border-top:1px solid var(--flow-line);border-bottom:1px solid var(--flow-line)}
.fs-room-detail-fact{display:flex;flex-direction:column;gap:2px;min-width:0}
.fs-room-detail-fact-label{font-size:clamp(8px,0.9vw,9px);font-weight:600;letter-spacing:var(--flow-tracking-caps);text-transform:uppercase;color:rgba(255,255,255,.42)}
.fs-room-detail-fact-value{font-family:var(--flow-font-ui);font-size:clamp(12px,1.4vw,14px);font-weight:600;color:var(--flow-ink);font-variant-numeric:tabular-nums}
.fs-room-detail-amenities{display:flex;flex-wrap:wrap;gap:clamp(6px,1vw,8px)}
.fs-room-detail-chip{font-family:var(--flow-font-ui);font-size:clamp(10px,1.1vw,12px);font-weight:500;color:var(--flow-ink-65);background:var(--flow-tint);border:1px solid var(--flow-line);border-radius:999px;padding:clamp(4px,0.6vw,6px) clamp(8px,1.1vw,12px);white-space:nowrap}
/* Primary action in the detail body - same gold-gradient CTA as the dining
   "Reserve" / payment "Pay" buttons (was rendering as an unstyled white box). */
.fs-room-detail-pick{flex:0 0 auto;width:100%;margin-top:clamp(6px,1vw,10px);display:flex;align-items:center;justify-content:center;height:clamp(40px,4.8vw,48px);border-radius:clamp(8px,1.1vw,11px);background:linear-gradient(135deg,var(--flow-gold-a25),var(--flow-gold-a15));border:1px solid var(--flow-gold-a40);font-family:var(--flow-font-ui);font-size:clamp(13px,1.5vw,15px);font-weight:600;letter-spacing:.04em;color:var(--flow-gold);cursor:pointer;transition:opacity .15s ease,transform .1s ease}
.fs-room-detail-pick:hover{opacity:.85}
.fs-room-detail-pick:active{transform:scale(.99)}
.fs-room-detail-rates{display:flex;flex-direction:column;gap:clamp(6px,0.9vw,8px)}
.fs-rates-label{font-size:clamp(8px,0.9vw,9px);font-weight:600;letter-spacing:var(--flow-tracking-caps);text-transform:uppercase;color:rgba(255,255,255,.42)}
.fs-rate-card{display:flex;align-items:flex-start;gap:clamp(8px,1.1vw,12px);width:100%;text-align:left;padding:clamp(8px,1.1vw,12px) clamp(10px,1.3vw,14px);border-radius:clamp(8px,1.1vw,11px);background:var(--flow-tint);border:1px solid var(--flow-line);cursor:pointer;transition:border-color .15s ease,background .15s ease}
.fs-rate-card:hover{border-color:var(--flow-gold-a40)}
.fs-rate-card.is-selected{background:linear-gradient(135deg,var(--flow-gold-a25),var(--flow-gold-a15));border-color:var(--flow-gold-a40)}
.fs-rate-radio{flex:0 0 auto;margin-top:3px;width:14px;height:14px;border-radius:999px;border:1.5px solid rgba(255,255,255,.35);position:relative}
.fs-rate-card.is-selected .fs-rate-radio{border-color:var(--flow-gold)}
.fs-rate-card.is-selected .fs-rate-radio::after{content:"";position:absolute;inset:3px;border-radius:999px;background:var(--flow-gold)}
.fs-rate-main{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:3px}
.fs-rate-top{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.fs-rate-name{font-family:var(--flow-font-ui);font-size:clamp(12px,1.4vw,14px);font-weight:600;color:var(--flow-ink)}
.fs-rate-price{font-family:'DM Sans',sans-serif;font-size:clamp(12px,1.4vw,14px);font-weight:700;color:var(--flow-ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.fs-rate-per{font-weight:500;color:var(--flow-ink-65);font-size:.82em;margin-left:1px}
.fs-rate-incl{font-family:var(--flow-font-ui);font-size:clamp(10px,1.1vw,12px);font-weight:400;color:var(--flow-ink-65);line-height:1.4}
.fs-rate-cancel{font-family:var(--flow-font-ui);font-size:clamp(9px,1vw,11px);font-weight:500}
.fs-rate-cancel.is-refundable{color:var(--flow-live-green)}
.fs-rate-cancel.is-nonref{color:rgba(255,255,255,.42)}

/* Comparison - 2-3 rooms side-by-side. Reuses the same fact/chip
   typography vocabulary as room_detail; layout is a horizontal grid
   so the caller can see all candidates at once. Cards auto-fit:
   2 rooms render side-by-side, 3 rooms render in three columns. */
.fs-comparison{display:flex;flex-direction:column;flex:1;min-height:0;opacity:1}
/* minmax(0,1fr) let cards shrink BELOW content (clipping facts/price at narrow
   widths) instead of wrapping. The min(100%, …) floor wraps to one column when
   the container is narrower than the floor - fixes the phone clip AND the iPad
   right-card clip with no breakpoint (only ever 2-3 cards, so the floor never
   adds columns on a wide modal). 2026-06-02 mobile-reflow. */
.fs-comparison-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%, var(--flow-grid-card-min)),1fr));gap:clamp(8px,1.4vw,14px);padding:clamp(10px,1.6vw,16px) clamp(12px,2vw,20px);flex:1;min-height:0;align-content:start}
.fs-comparison-card{display:flex;flex-direction:column;border:1px solid var(--flow-line);border-radius:clamp(8px,1.2vw,12px);overflow:hidden;background:var(--flow-tint);min-width:0;opacity:0;animation:cardIn .4s ease forwards}
.fs-comparison-card:nth-child(1){animation-delay:.05s}.fs-comparison-card:nth-child(2){animation-delay:.12s}.fs-comparison-card:nth-child(3){animation-delay:.19s}
.fs-comparison-card.selected{border-color:var(--flow-live-green);box-shadow:0 0 0 1px var(--flow-live-green) inset}
.fs-comparison-img{position:relative;flex:0 0 auto;height:clamp(110px,16vw,180px);overflow:hidden}
.fs-comparison-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.fs-comparison-body{display:flex;flex-direction:column;gap:clamp(8px,1.2vw,12px);padding:clamp(10px,1.4vw,14px);min-width:0}
.fs-comparison-name{font-family:'Cormorant Garamond',serif;font-size:clamp(15px,1.9vw,20px);font-weight:600;color:var(--flow-ink);line-height:1.15;letter-spacing:-.005em}
.fs-comparison-price{font-family:'DM Sans',sans-serif;font-size:clamp(11px,1.3vw,13px);font-weight:700;color:var(--flow-live-green)}
.fs-comparison-facts{display:flex;flex-direction:column;gap:clamp(4px,0.6vw,6px);padding:clamp(6px,0.9vw,9px) 0;border-top:1px solid var(--flow-line);border-bottom:1px solid var(--flow-line)}
.fs-comparison-fact{display:flex;justify-content:space-between;gap:clamp(8px,1.2vw,12px);min-width:0}
.fs-comparison-fact-label{font-size:clamp(8px,0.9vw,9px);font-weight:600;letter-spacing:var(--flow-tracking-caps);text-transform:uppercase;color:rgba(255,255,255,.42)}
.fs-comparison-fact-value{font-family:var(--flow-font-ui);font-size:clamp(11px,1.2vw,13px);font-weight:600;color:var(--flow-ink);font-variant-numeric:tabular-nums;text-align:right}
.fs-comparison-amenities{display:flex;flex-wrap:wrap;gap:clamp(4px,0.7vw,6px)}
.fs-comparison-chip{font-family:var(--flow-font-ui);font-size:clamp(9px,1vw,11px);font-weight:500;color:var(--flow-ink-65);background:var(--flow-tint);border:1px solid var(--flow-line);border-radius:999px;padding:clamp(3px,0.5vw,5px) clamp(7px,1vw,10px);white-space:nowrap}

/* Enhancements */
.fs-enh-wrap{position:absolute;inset:0;display:flex;flex-direction:column;opacity:0;visibility:hidden;pointer-events:none;z-index:160}
.fs-enh-wrap.visible{opacity:1;visibility:visible;pointer-events:auto}
/* Enhance grid: 3-up per spec (component-enhancements.html). With our 8
   demo cards this yields a 3+3+2 row layout - natural grid auto-flow,
   no explicit grid-template-rows. */
.fs-enh-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(6px, 1.2vw, 12px);padding:clamp(8px, 1.4vw, 14px) clamp(10px, 1.6vw, 16px);flex:1;min-height:0;align-content:start}
.fs-enh-card{border-radius:var(--flow-r-pay);overflow:hidden;background:var(--flow-tint);border:1px solid var(--flow-line);display:flex;flex-direction:column;opacity:0;animation:cardIn .4s ease forwards}
.fs-enh-card:nth-child(1){animation-delay:.05s}.fs-enh-card:nth-child(2){animation-delay:.1s}.fs-enh-card:nth-child(3){animation-delay:.15s}.fs-enh-card:nth-child(4){animation-delay:.2s}
.fs-enh-card:nth-child(5){animation-delay:.25s}.fs-enh-card:nth-child(6){animation-delay:.3s}.fs-enh-card:nth-child(7){animation-delay:.35s}.fs-enh-card:nth-child(8){animation-delay:.4s}
@keyframes cardIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.fs-enh-img{width:100%;aspect-ratio:4/3;position:relative;overflow:hidden}
.fs-enh-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.fs-enh-img::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 55%,rgba(0,0,0,.55) 100%);pointer-events:none}
.fs-enh-body{padding:clamp(8px, 1.4vw, 14px) clamp(10px, 1.6vw, 16px) clamp(10px, 1.6vw, 16px);display:flex;flex-direction:column;gap:clamp(2px, 0.5vw, 5px)}
.fs-enh-name{font-size:clamp(13px, 1.5vw, 17px);font-weight:600;color:var(--flow-ink-pure);line-height:1.25;letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fs-enh-desc{font-size:clamp(11px, 1.2vw, 14px);color:var(--flow-ink-65);line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Price color = gold-warm, NOT green. Green (`--flow-live-green`) is
   reserved for the room price (positive event for the stay itself);
   enhancements are add-ons and use the brand's warm gold-ink. */
.fs-enh-price{font-size:clamp(11px, 1.4vw, 15px);font-weight:600;color:var(--flow-gold-ink);margin-top:clamp(4px, 0.7vw, 8px);font-variant-numeric:tabular-nums}

/* ── ENHANCE - focused-room hero (above the grid) ──────────────────────
   Optional hero card the widget renders when the caller has chosen a
   room and we want it persistently visible while picking add-ons.
   Storyboard demo doesn't use it (its caller is hypothetical) so the
   `:focused_room` attr defaults to nil. */
/* Thin context strip replacing the old cropped hero - keeps the room
   name + price visible while picking enhancements, but doesn't steal
   vertical space from the 9-card grid. */
.fs-enh-context{flex:0 0 auto;display:flex;align-items:center;gap:clamp(6px,0.9vw,10px);padding:clamp(6px,0.9vw,10px) clamp(12px,1.8vw,18px);border-bottom:1px solid var(--flow-line);font-family:var(--flow-font-ui);font-size:clamp(11px,1.2vw,13px);line-height:1.2;color:var(--flow-ink-65)}
.fs-enh-context-name{font-family:'Cormorant Garamond',serif;font-size:clamp(13px,1.6vw,17px);font-weight:600;color:var(--flow-ink-pure);letter-spacing:-.005em}
.fs-enh-context-sep{color:var(--flow-ink-3);font-weight:400}
.fs-enh-context-price{font-weight:700;color:var(--flow-live-green);font-variant-numeric:tabular-nums}
.fs-enh-context-tag{margin-left:auto;font-size:clamp(8px,0.9vw,10px);font-weight:600;letter-spacing:var(--flow-tracking-caps);text-transform:uppercase;color:var(--flow-ink-3);background:var(--flow-tint);border:1px solid var(--flow-line);border-radius:999px;padding:clamp(2px,0.3vw,3px) clamp(8px,1vw,10px)}

/* ── PAYMENT ────────────────────────────────────────────────────────── */
.fs-pay-wrap{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:clamp(12px,1.8vw,22px);opacity:0;visibility:hidden;pointer-events:none;z-index:165;padding:clamp(12px,2vw,22px) clamp(16px,2.6vw,28px);overflow:hidden}
.fs-pay-wrap > .fs-pay-left,.fs-pay-wrap > .fs-pay-right{align-self:center;max-height:100%;overflow:auto}
.fs-pay-wrap.visible{opacity:1;visibility:visible;pointer-events:auto}
.fs-pay-left{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:clamp(6px,1vw,10px)}
.fs-pay-right{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:clamp(6px,1vw,10px)}
.fs-pay-summary{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);border-radius:clamp(8px,1.2vw,12px);padding:clamp(10px,1.6vw,16px) clamp(12px,2vw,20px);width:100%;box-sizing:border-box}
.fs-pay-sum-row{display:flex;justify-content:space-between;padding:clamp(3px, 0.5vw, 5px) 0;font-size:clamp(8px, 1.1vw, 11px)}
.fs-pay-sum-label{color:rgba(255,255,255,.45)}
.fs-pay-sum-value{color:rgba(255,255,255,.85);font-weight:500}
.fs-pay-sum-div{height:1px;background:rgba(255,255,255,.06);margin:clamp(3px, 0.5vw, 5px) 0}
.fs-pay-sum-row.total .fs-pay-sum-label{color:var(--flow-ink-pure);font-weight:600;font-size:clamp(10px, 1.3vw, 14px)}
.fs-pay-sum-row.total .fs-pay-sum-value{color:var(--flow-gold);font-weight:700;font-size:clamp(10px, 1.3vw, 14px)}
.fs-review-wrap{position:absolute;inset:0;display:flex;flex-direction:column;opacity:0;visibility:hidden;pointer-events:none;z-index:160;color:var(--flow-ink-9)}
.fs-review-wrap.visible{opacity:1;visibility:visible;pointer-events:auto}
.fs-review-content{flex:1 1 0;min-height:0;display:flex;gap:clamp(10px,1.6vw,18px);padding:clamp(8px,1.4vw,14px) clamp(10px,1.6vw,16px);align-items:stretch}
.fs-review-hero{position:relative;flex:1 1 0;min-width:0;align-self:stretch;border-radius:clamp(8px,1.2vw,12px);overflow:hidden;border:1px solid rgba(255,255,255,.1)}
.fs-review-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.fs-review-hero-gradient{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 40%,rgba(0,0,0,.65) 100%);pointer-events:none}
.fs-review-hero-info{position:absolute;left:clamp(10px,1.6vw,16px);bottom:clamp(8px,1.4vw,14px);display:flex;flex-direction:column;gap:2px;color:#fff}
.fs-review-hero-name{font-size:clamp(15px,1.9vw,19px);font-weight:600;letter-spacing:-.01em}
.fs-review-hero-price{font-size:clamp(11px,1.3vw,14px);opacity:.85}
.fs-review-body{flex:1 1 0;min-width:0;min-height:0;overflow-y:auto;padding:clamp(10px,1.6vw,16px) clamp(12px,2vw,20px);display:flex;flex-direction:column;gap:clamp(6px,1vw,10px)}
.fs-review-title{font-size:clamp(13px,1.6vw,17px);font-weight:600;letter-spacing:-.01em;margin-bottom:clamp(4px,0.8vw,8px);color:var(--flow-ink-9)}
.fs-review-row{display:flex;justify-content:space-between;align-items:baseline;gap:clamp(8px,1.4vw,14px);padding:clamp(5px,0.8vw,8px) 0;border-bottom:1px solid rgba(255,255,255,.06)}
.fs-review-row-label{font-size:clamp(8px,1.05vw,11px);font-weight:600;letter-spacing:.10em;text-transform:uppercase;color:rgba(255,255,255,.45)}
.fs-review-row-value{font-size:clamp(11px,1.35vw,14px);color:var(--flow-ink-9)}
.fs-review-enh{display:flex;flex-direction:column;gap:clamp(3px,0.5vw,6px);margin-top:clamp(4px,0.8vw,8px)}
.fs-review-enh-title{font-size:clamp(8px,1.05vw,11px);font-weight:600;letter-spacing:.10em;text-transform:uppercase;color:rgba(255,255,255,.45);margin-bottom:clamp(2px,0.4vw,4px)}
.fs-review-enh-row{display:flex;justify-content:space-between;align-items:baseline;font-size:clamp(11px,1.3vw,13px)}
.fs-review-enh-name{color:var(--flow-ink-8)}
.fs-review-enh-price{color:rgba(255,255,255,.7)}
.fs-review-total{display:flex;justify-content:space-between;align-items:baseline;padding:clamp(8px,1.2vw,12px) 0 clamp(4px,0.7vw,6px);margin-top:clamp(6px,1vw,10px);border-top:1px solid rgba(255,255,255,.16)}
.fs-review-total-label{font-size:clamp(10px,1.25vw,12px);font-weight:600;letter-spacing:.10em;text-transform:uppercase;color:rgba(255,255,255,.6)}
.fs-review-total-value{font-size:clamp(18px,2.2vw,22px);font-weight:600;color:#fff}
.fs-review-note{margin-top:clamp(4px,0.8vw,8px);font-size:clamp(10px,1.2vw,12px);font-style:italic;color:rgba(255,255,255,.55);text-align:center}
.fs-pay-section{display:flex;flex-direction:column;gap:clamp(4px,0.7vw,7px)}
.fs-pay-section-label{font-size:clamp(7px, 0.9vw, 9px);font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.4);margin-bottom:clamp(2px,0.4vw,4px)}

/* Payment-processing overlay - shown ONLY while the pay form is submitting.
   LiveView toggles .phx-submit-loading on the <form> for the request round-trip;
   the galeon Demo adapter (Demo.confirm_booking) stretches that to ~2.8s so the
   card reads as "processing". Mirrors the searching loader (.fs-search-dot) with
   a gold accent on a dark blurred backdrop. */
.fs-pay-processing{display:none}
.fs-pay-form.phx-submit-loading .fs-pay-processing{
  display:flex;position:fixed;inset:0;z-index:60;align-items:center;justify-content:center;
  background:rgba(10,12,16,.86);
  background:color-mix(in srgb, var(--flow-bg) 90%, transparent);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  animation:fsPayProcessingIn .28s ease both
}
.fs-pay-processing-card{display:flex;flex-direction:column;align-items:center;gap:clamp(16px,1.8vw,24px);text-align:center;padding:clamp(28px,3.5vw,56px)}
.fs-pay-processing .fs-search-dot{background:var(--flow-gold)}
.fs-pay-processing-label{font-family:var(--flow-font-display);font-size:clamp(16px,1.6vw,22px);font-weight:300;color:var(--flow-ink-2);letter-spacing:.04em;margin:0}
.fs-pay-processing-sub{font-size:clamp(11px,1vw,13px);text-transform:uppercase;letter-spacing:.18em;color:var(--flow-ink-dim);margin:0}
@keyframes fsPayProcessingIn{from{opacity:0}to{opacity:1}}
.fs-pay-card{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);border-radius:clamp(8px,1.2vw,12px);padding:clamp(10px,1.6vw,16px) clamp(12px,2vw,20px);width:100%;box-sizing:border-box;display:flex;flex-direction:column;gap:clamp(5px,0.8vw,8px)}
.fs-pay-field{height:clamp(30px, 4vw, 42px);border-radius:clamp(4px, 0.7vw, 7px);background:rgba(255,255,255,.04);border:1px solid var(--flow-surface-glass-14);padding:0 clamp(8px, 1.4vw, 14px);display:flex;align-items:center;font-size:clamp(8px, 1.1vw, 11px);color:var(--flow-ink-7);margin-bottom:clamp(4px, 0.7vw, 7px)}
.fs-pay-field-row{display:flex;gap:clamp(4px, 0.7vw, 7px)}
.fs-pay-field-row .fs-pay-field{flex:1}
.fs-pay-field .fs-pay-field-label{color:var(--flow-ink-3);margin-right:clamp(4px, 0.7vw, 7px);font-size:clamp(7px, 1vw, 10px);flex-shrink:0}
.fs-pay-field.filled{border-color:var(--flow-gold-a30);color:rgba(255,255,255,.85)}
/* Focus ring - gold a12 halo. Spec component-payment.html `.field.focused`.
   Storyboard sets `.focused` programmatically; production widget sets it
   on real input focus (input → div mirror). */
.fs-pay-field.focused,.fs-pay-field:focus-within{border-color:var(--flow-gold-a55);background:var(--flow-gold-a06);box-shadow:0 0 0 3px var(--flow-gold-a12);transition:border-color .2s,background .2s,box-shadow .2s}
.fs-pay-requests{width:100%;box-sizing:border-box;min-height:clamp(44px,6vw,60px);border-radius:clamp(6px, 0.9vw, 9px);background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.1);padding:clamp(8px,1.2vw,12px) clamp(10px,1.4vw,14px);font-size:clamp(8px, 1.1vw, 11px);color:rgba(255,255,255,.6);display:flex;align-items:flex-start;line-height:1.45}
.fs-pay-requests.filled{border-color:var(--flow-gold-a30);color:rgba(255,255,255,.85)}
.fs-pay-confirm-btn{width:100%;box-sizing:border-box;height:clamp(32px,4vw,40px);border-radius:clamp(8px,1.1vw,11px);background:linear-gradient(135deg,var(--flow-gold-a25),var(--flow-gold-a14));border:1px solid var(--flow-gold-a40);display:flex;align-items:center;justify-content:center;font-size:clamp(10px,1.25vw,12px);font-weight:600;color:var(--flow-gold-a95);letter-spacing:.04em;margin-top:clamp(6px,1vw,10px)}
.fs-pay-confirm-btn.pressed{transform:scale(.97);background:linear-gradient(135deg,var(--flow-gold-a30),var(--flow-gold-a18))}

/* Payment error - failed-hold sibling of payment scene. Tokens-only.
   Lives inside the same .fs-pay-wrap shell so layout matches payment. */
.fs-pay-error-card{margin:auto;width:min(520px,84%);display:flex;flex-direction:column;gap:var(--flow-space-3);padding:clamp(16px,2.4vw,24px) clamp(20px,3vw,32px);background:var(--flow-danger-surface);border:1px solid var(--flow-danger);border-radius:var(--flow-r-card);box-shadow:0 0 0 1px var(--flow-danger-shadow),0 8px 32px var(--flow-danger-shadow);text-align:center}
.fs-pay-error-title{font-family:'Cormorant Garamond',serif;font-size:clamp(15px,2vw,20px);font-weight:600;color:var(--flow-ink-pure);line-height:1.2;margin:0}
.fs-pay-error-subline{font-size:clamp(9px,1.15vw,12px);color:var(--flow-ink-7);line-height:1.5;margin:0}
.fs-pay-error-detail{font-size:clamp(8px,1.05vw,11px);color:var(--flow-danger-bright);background:var(--flow-danger-tint);border:1px solid var(--flow-danger-shadow);border-radius:var(--flow-r-card);padding:var(--flow-space-2) var(--flow-space-3);line-height:1.45;letter-spacing:.01em}
.fs-pay-error-actions{display:flex;justify-content:center;margin-top:var(--flow-space-1)}
.fs-pay-error-end{appearance:none;-webkit-appearance:none;cursor:pointer;font-family:inherit;font-size:clamp(10px,1.25vw,12px);font-weight:600;letter-spacing:.04em;color:var(--flow-ink-pure);background:var(--flow-danger);border:1px solid var(--flow-danger);border-radius:var(--flow-r-pill-lg);padding:var(--flow-space-2) var(--flow-space-5);transition:transform var(--flow-dur-sm) var(--flow-ease-out),background var(--flow-dur-sm) var(--flow-ease-out)}
.fs-pay-error-end:hover{background:var(--flow-danger-bright)}
.fs-pay-error-end:active{transform:scale(.97)}
.fs-pay-error-end:focus-visible{outline:2px solid var(--flow-ink-pure);outline-offset:2px}

/* Confirmation */
.fs-conf-wrap{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:clamp(6px,1vw,10px) clamp(12px,2vw,20px);gap:clamp(4px,0.7vw,7px);opacity:0;visibility:hidden;pointer-events:none;z-index:170;overflow:hidden}
.fs-conf-wrap.visible{opacity:1;visibility:visible;pointer-events:auto}

/* ── Confirmation entry choreography ─────────────────────────────────
   Spec: component-confirmation.html `.conf.run`. Eight cues fire in
   sequence over ~1.5s when `.fs-conf-wrap` enters its `.visible` state:
     0ms     burst ring        scale .4→1.8, opacity .8→0
     80ms    badge pop         spring scale 0→1.18→.94→1, rotate -12°→0°
     480ms   check stroke      (drawn by .fs-check-draw - its own anim)
     540ms   confetti          8 shards fan out radially
     720ms   title rise        translateY 8→0, opacity 0→1
     800ms   badge glow pulse  one-time 1.6s halo
     820ms   code rise         translateY 6→0, opacity 0→1
     920ms   summary rise      translateY 12→0, opacity 0→1
    1100ms   done button rise  translateY 12→0, opacity 0→1
   ─────────────────────────────────────────────────────────────────── */

.fs-conf-check-wrap{position:relative;width:clamp(72px,9vw,96px);height:clamp(72px,9vw,96px);display:flex;align-items:center;justify-content:center;flex-shrink:0}

/* Burst ring - green expanding halo */
.fs-conf-burst{position:absolute;inset:0;border-radius:50%;border:2px solid var(--flow-live-green);opacity:0;transform:scale(.4);pointer-events:none}
.fs-conf-wrap.visible .fs-conf-burst{animation:fs-conf-burst .7s cubic-bezier(.2,.8,.2,1) forwards}
@keyframes fs-conf-burst{0%{opacity:0;transform:scale(.4)}30%{opacity:.8}100%{opacity:0;transform:scale(1.8)}}

/* Badge - round green disc holding the check-draw. Spring-pop in, then a
   one-time glow pulse 800ms after the pop. Baseline = final state so the
   badge is visible in static catalog previews where `.visible` is never
   added; the keyframe at 0% drives the entry transition when it does. */
.fs-conf-badge{width:clamp(56px,7.2vw,76px);height:clamp(56px,7.2vw,76px);border-radius:50%;background:radial-gradient(circle at 30% 30%,rgba(255,255,255,.10),transparent 60%),linear-gradient(135deg,rgba(74,222,128,.22),rgba(74,222,128,.10));border:1.5px solid rgba(74,222,128,.42);display:flex;align-items:center;justify-content:center;position:relative}
.fs-conf-wrap.visible .fs-conf-badge{animation:fs-conf-badge-pop .72s cubic-bezier(.34,1.56,.64,1) .08s forwards,fs-conf-badge-glow 1.6s ease-in-out .8s 1}
@keyframes fs-conf-badge-pop{0%{opacity:0;transform:scale(0) rotate(-12deg)}60%{opacity:1;transform:scale(1.18) rotate(0deg)}80%{transform:scale(.94) rotate(0deg)}100%{opacity:1;transform:scale(1) rotate(0deg)}}
@keyframes fs-conf-badge-glow{0%,100%{box-shadow:0 0 0 0 rgba(74,222,128,0),0 8px 32px -8px rgba(74,222,128,.45)}50%{box-shadow:0 0 0 10px rgba(74,222,128,0),0 8px 32px -8px rgba(74,222,128,.55)}}

/* The CheckDraw SVG inside the badge - sized and tinted to match. The
   stroke-draw animation is owned by .fs-check-draw rules above (line ~440). */
.fs-conf-badge .fs-check-draw{width:clamp(28px,3.6vw,38px);height:clamp(28px,3.6vw,38px);filter:drop-shadow(0 0 4px rgba(74,222,128,.55))}
.fs-conf-badge .fs-check-draw-circle{stroke:transparent}
.fs-conf-badge .fs-check-draw-path{stroke:var(--flow-live-green);stroke-width:3.5}

/* Confetti - 8 shards, alternating green and gold-warm, fanning out. */
.fs-conf-confetti{position:absolute;inset:0;pointer-events:none}
.fs-conf-confetti i{position:absolute;top:50%;left:50%;width:2px;height:10px;border-radius:1px;margin-left:-1px;margin-top:-5px;opacity:0}
.fs-conf-confetti i:nth-child(1){background:var(--flow-live-green)}
.fs-conf-confetti i:nth-child(2){background:var(--flow-gold-ink)}
.fs-conf-confetti i:nth-child(3){background:var(--flow-live-green)}
.fs-conf-confetti i:nth-child(4){background:var(--flow-gold)}
.fs-conf-confetti i:nth-child(5){background:var(--flow-live-green)}
.fs-conf-confetti i:nth-child(6){background:var(--flow-gold-ink)}
.fs-conf-confetti i:nth-child(7){background:var(--flow-live-green)}
.fs-conf-confetti i:nth-child(8){background:var(--flow-gold)}
.fs-conf-wrap.visible .fs-conf-confetti i:nth-child(1){animation:fs-conf-c1 .7s cubic-bezier(.2,.7,.3,1) .54s forwards}
.fs-conf-wrap.visible .fs-conf-confetti i:nth-child(2){animation:fs-conf-c2 .7s cubic-bezier(.2,.7,.3,1) .54s forwards}
.fs-conf-wrap.visible .fs-conf-confetti i:nth-child(3){animation:fs-conf-c3 .7s cubic-bezier(.2,.7,.3,1) .54s forwards}
.fs-conf-wrap.visible .fs-conf-confetti i:nth-child(4){animation:fs-conf-c4 .7s cubic-bezier(.2,.7,.3,1) .54s forwards}
.fs-conf-wrap.visible .fs-conf-confetti i:nth-child(5){animation:fs-conf-c5 .7s cubic-bezier(.2,.7,.3,1) .54s forwards}
.fs-conf-wrap.visible .fs-conf-confetti i:nth-child(6){animation:fs-conf-c6 .7s cubic-bezier(.2,.7,.3,1) .54s forwards}
.fs-conf-wrap.visible .fs-conf-confetti i:nth-child(7){animation:fs-conf-c7 .7s cubic-bezier(.2,.7,.3,1) .54s forwards}
.fs-conf-wrap.visible .fs-conf-confetti i:nth-child(8){animation:fs-conf-c8 .7s cubic-bezier(.2,.7,.3,1) .54s forwards}
@keyframes fs-conf-c1{0%{opacity:0;transform:rotate(0deg) translateY(0)}25%{opacity:1}100%{opacity:0;transform:rotate(0deg) translateY(-60px)}}
@keyframes fs-conf-c2{0%{opacity:0;transform:rotate(45deg) translateY(0)}25%{opacity:1}100%{opacity:0;transform:rotate(45deg) translateY(-56px)}}
@keyframes fs-conf-c3{0%{opacity:0;transform:rotate(90deg) translateY(0)}25%{opacity:1}100%{opacity:0;transform:rotate(90deg) translateY(-64px)}}
@keyframes fs-conf-c4{0%{opacity:0;transform:rotate(135deg) translateY(0)}25%{opacity:1}100%{opacity:0;transform:rotate(135deg) translateY(-56px)}}
@keyframes fs-conf-c5{0%{opacity:0;transform:rotate(180deg) translateY(0)}25%{opacity:1}100%{opacity:0;transform:rotate(180deg) translateY(-60px)}}
@keyframes fs-conf-c6{0%{opacity:0;transform:rotate(225deg) translateY(0)}25%{opacity:1}100%{opacity:0;transform:rotate(225deg) translateY(-56px)}}
@keyframes fs-conf-c7{0%{opacity:0;transform:rotate(270deg) translateY(0)}25%{opacity:1}100%{opacity:0;transform:rotate(270deg) translateY(-64px)}}
@keyframes fs-conf-c8{0%{opacity:0;transform:rotate(315deg) translateY(0)}25%{opacity:1}100%{opacity:0;transform:rotate(315deg) translateY(-56px)}}

/* Title / code / summary / done - staggered rises after the badge. Baselines
   are the final visible state; the rise keyframe's `from` (0% opacity / 8px
   below) drives the entry transition. Two-mode safe (static + animated). */
.fs-conf-title{font-family:var(--flow-font-display);font-size:clamp(16px,2vw,22px);font-weight:600;color:var(--flow-ink-pure);margin:0;line-height:1.1}
.fs-conf-code{font-family:var(--flow-font-mono);font-size:clamp(8px,1vw,10px);font-weight:500;color:var(--flow-ink-3);letter-spacing:.14em;margin:0}
.fs-conf-card{background:rgba(255,255,255,.04);border:1px solid var(--flow-line);border-radius:var(--flow-r-card);padding:clamp(8px,1.2vw,12px) clamp(14px,2vw,20px);width:min(440px,72%);margin:0;display:flex;flex-direction:column}
.fs-conf-wrap.visible .fs-conf-title{animation:fs-conf-rise-8 .4s ease-out .72s}
.fs-conf-wrap.visible .fs-conf-code{animation:fs-conf-rise-6 .4s ease-out .82s}
.fs-conf-wrap.visible .fs-conf-card{animation:fs-conf-rise-12 .5s ease-out .92s}
@keyframes fs-conf-rise-8{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
@keyframes fs-conf-rise-6{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
@keyframes fs-conf-rise-12{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}

/* Reduced motion: keep the final state, drop the showy bits. */
@media (prefers-reduced-motion:reduce){
  .fs-conf-wrap.visible .fs-conf-burst{animation:none;opacity:0}
  .fs-conf-wrap.visible .fs-conf-confetti i{animation:none;opacity:0}
  .fs-conf-wrap.visible .fs-conf-badge{animation:none;opacity:1;transform:none}
  .fs-conf-wrap.visible .fs-conf-title,
  .fs-conf-wrap.visible .fs-conf-code,
  .fs-conf-wrap.visible .fs-conf-card{animation-duration:.2s;animation-delay:0s}
}

.fs-conf-row{display:flex;justify-content:space-between;padding:clamp(1px,0.25vw,3px) 0;border-bottom:1px solid rgba(255,255,255,.06)}
.fs-conf-row:last-child{border-bottom:none}
.fs-conf-label{font-size:clamp(8px,1vw,11px);color:rgba(255,255,255,.45)}
.fs-conf-value{font-size:clamp(8px,1vw,11px);font-weight:600;color:var(--flow-ink-pure)}
.fs-conf-total .fs-conf-value{color:var(--flow-live-green);font-size:clamp(9px,1.2vw,13px)}
.fs-conf-actions{display:flex;gap:clamp(6px,1vw,10px);margin:0;justify-content:center;width:min(440px,72%)}
.fs-conf-action{flex:1;padding:clamp(5px,0.8vw,8px) clamp(6px,1.1vw,11px);border-radius:clamp(6px,0.9vw,9px);background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);font-size:clamp(7px,0.9vw,10px);font-weight:500;color:rgba(255,255,255,.75);display:flex;align-items:center;justify-content:center;gap:clamp(3px,0.5vw,5px)}
.fs-conf-done{width:min(440px,72%);padding:clamp(7px,1.05vw,10px) clamp(16px,3.2vw,32px);border-radius:clamp(8px,1.1vw,11px);background:linear-gradient(135deg,var(--flow-gold-a25),var(--flow-gold-a14));border:1px solid var(--flow-gold-a40);font-size:clamp(9px,1.2vw,12px);font-weight:600;color:var(--flow-gold-a95);letter-spacing:.04em;text-align:center}
.fs-conf-wrap.visible .fs-conf-done{animation:fs-conf-rise-12 .4s ease-out 1.1s}
@media (prefers-reduced-motion:reduce){.fs-conf-wrap.visible .fs-conf-done{animation-duration:.2s;animation-delay:0s}}

/* Handoff (Inntopia) checkout CTA - the guest pays first-party on the IBE, so
   the confirmation scene renders a real deep-link instead of the inert Done
   pill. Reuses the gold treatment but reads as an actionable button. */
.fs-conf-cta{display:block;box-sizing:border-box;width:min(440px,72%);padding:clamp(8px,1.15vw,11px) clamp(16px,3.2vw,32px);border-radius:clamp(8px,1.1vw,11px);background:linear-gradient(135deg,var(--flow-gold-a40),var(--flow-gold-a25));border:1px solid var(--flow-gold-a40);font-size:clamp(9px,1.2vw,12px);font-weight:700;color:var(--flow-gold-a95);letter-spacing:.04em;text-align:center;text-decoration:none;cursor:pointer}
.fs-conf-cta:hover{background:linear-gradient(135deg,var(--flow-gold-a40),var(--flow-gold-a40))}
.fs-conf-handoff-note{font-size:clamp(8px,1vw,10px);color:rgba(255,255,255,.45);text-align:center;margin:0}
.fs-conf-wrap.visible .fs-conf-cta{animation:fs-conf-rise-12 .4s ease-out 1.1s}
@media (prefers-reduced-motion:reduce){.fs-conf-wrap.visible .fs-conf-cta{animation-duration:.2s;animation-delay:0s}}

/* Progress bar - in-flow bottom row, compact.
   Hidden state collapses layout (no empty space at hub) and translates
   8px down so .visible class slides + fades it into view. */
.fs-progress{flex-shrink:0;z-index:190;padding:0 clamp(20px, 2.4vw, 32px);max-height:0;opacity:0;overflow:hidden;transform:translateY(8px);transition:max-height .4s ease, padding .4s ease, opacity .4s ease, transform .4s ease}
/* max-height:80px (was 60px) gives headroom at wide viewports where the
   clamp() ceilings push content close to 60px (pad-top 7 + label ~16 + dot 8
   + gap 4 + pad-bottom 20 ≈ 55-60px). 80px is a safety cap, not a target. */
.fs-progress.visible{max-height:80px;padding-top:clamp(4px, 0.7vw, 7px);padding-bottom:clamp(14px, 1.5vw, 20px);opacity:1;transform:translateY(0)}
.fs-prog-steps{display:flex;justify-content:space-between;position:relative}
.fs-prog-steps::before{content:'';position:absolute;top:3px;left:var(--track-left,0);right:var(--track-right,0);height:2px;background:rgba(255,255,255,.1);border-radius:1px}
.fs-prog-steps::after{content:'';position:absolute;top:3px;left:var(--track-left,0);height:2px;width:var(--prog-width,0px);background:var(--flow-gold);border-radius:1px;transition:width .6s ease}
.fs-prog-step{display:flex;flex-direction:column;align-items:center;gap:4px;position:relative;z-index:1;flex:1 1 0;min-width:0}
.fs-prog-dot{width:8px;height:8px;border-radius:50%;border:2px solid rgba(255,255,255,.15);background:transparent;transition:background .3s,border-color .3s}
.fs-prog-step.active .fs-prog-dot{background:var(--flow-gold);border-color:var(--flow-gold)}
.fs-prog-step.completed .fs-prog-dot{background:var(--flow-gold);border-color:var(--flow-gold)}
.fs-prog-step span{font-family:'DM Sans',sans-serif;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.2);transition:color .3s;white-space:nowrap}
.fs-prog-step.active span{color:rgba(255,255,255,.6)}
.fs-prog-step.completed span{color:rgba(255,255,255,.35)}

/* ═══════════════════════════════════════ */
/* ── CLOSED CAPTIONS - in-flow row ───── */
/* ═══════════════════════════════════════ */
.fs-captions{flex-shrink:0;z-index:210;display:flex;align-items:center;gap:clamp(10px,1.4vw,16px);padding:clamp(5px,0.7vw,8px) clamp(14px,2.4vw,24px);opacity:0;transition:opacity .4s ease;overflow:visible;min-height:0;border-top:1px solid rgba(255,255,255,.05);position:relative}
/* min-height ceiling bumped from 4.6vw/54px to 5vw/60px to give two-line
   captions slightly more breathing room at wide viewports (caption text is
   position:absolute and doesn't contribute to layout height - see note below). */
.fs-captions.visible{opacity:1;min-height:clamp(42px,5vw,60px)}
.fs-cap-live{display:flex;align-items:center;gap:clamp(6px,0.9vw,9px);flex-shrink:0}
/* Caption text layout notes:
   - position:absolute centers the caption on the full bar width (not on
     the space remaining after left siblings); mute button uses
     margin-left:auto to stay right-aligned. pointer-events:none keeps the
     centered overlay from blocking sibling clicks.
   - Because the caption is out of normal flow, it does NOT contribute to
     .fs-captions' layout height. The parent's `min-height` (set on
     .fs-captions.visible above) provides the floor that visually contains it.
   - max-width:min(60%,560px) + -webkit-line-clamp:2 caps content; longer
     captions truncate with an ellipsis rather than overflowing the bar.
   - If a future scope needs the caption to drive auto-growing height
     (e.g. multi-line tool-call narrations without truncation), switch to
     a grid-based centering layout so the caption participates in flow,
     instead of absolute positioning. */
.fs-caption-text{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);max-width:min(45%, 380px);pointer-events:none;font-family:'DM Sans',sans-serif;font-size:clamp(10px,1.1vw,13px);font-weight:400;color:rgba(255,255,255,.8);text-align:center;line-height:1.4;letter-spacing:.01em;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;line-clamp:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:opacity .3s ease;padding:0 clamp(4px,0.6vw,8px)}
.fs-captions .fs-mute-btn{margin-left:auto}
.fs-caption-text.changing{opacity:0}

/* ── Chat drawer - typed-conversation side panel ──────────────────────────
   Toggled from the captions bar's chat button; direct child of .fs-modal so
   it overlays body + footer. z 230 sits ABOVE the explore overlay (220): a
   guest reading an explore page can keep typing to Flo without dismissing
   it. Always in the DOM - translateX slide keeps transcript state; the
   delayed visibility flip removes it from the tab order while closed
   (modal is overflow:hidden, so the parked drawer is fully clipped). */
.fs-chat-drawer{position:absolute;top:0;right:0;bottom:0;width:min(360px,100%);z-index:230;display:flex;flex-direction:column;background:rgba(10,10,15,.88);backdrop-filter:blur(24px) saturate(120%);-webkit-backdrop-filter:blur(24px) saturate(120%);border-left:1px solid var(--flow-line-3);transform:translateX(100%);visibility:hidden;transition:transform var(--flow-dur-md) var(--flow-ease-inout),visibility 0s var(--flow-dur-md)}
.fs-chat-drawer.open{transform:none;visibility:visible;transition:transform var(--flow-dur-md) var(--flow-ease-inout)}
/* padding-right reserves the host close-✕ band (embed loader floats its ✕
   over the iframe's top-right corner) so the collapse chevron never sits
   under it. Standalone visits get the small default inset - harmless. */
.fs-chat-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:14px 16px;padding-right:calc(16px + var(--flowstay-chrome-inset-right, 0px));border-bottom:1px solid var(--flow-line-2);flex-shrink:0}
.fs-chat-title{font-family:var(--flow-font-ui);font-size:13px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--flow-gold-ink)}
.fs-chat-collapse{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:rgba(255,255,255,.08);border:1px solid var(--flow-line-2);color:rgba(255,255,255,.7);cursor:pointer;flex-shrink:0;transition:background var(--flow-dur-xs),color var(--flow-dur-xs)}
.fs-chat-collapse:hover{background:rgba(255,255,255,.16);color:rgba(255,255,255,.95)}
.fs-chat-collapse:focus-visible{outline:2px solid var(--flow-gold);outline-offset:2px}
.fs-chat-msgs{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.18) transparent}
.fs-chat-empty{font-family:var(--flow-font-ui);font-size:12.5px;line-height:1.55;color:rgba(255,255,255,.45);text-align:center;margin:auto;padding:0 14px}
.fs-chat-empty p{margin:0}
.fs-chat-empty p+p{margin-top:8px}
/* §9.0-012 (issue #672): the identity + staff-handoff sentence reads as a
   quieter footnote under the "prefer typing?" prompt, not a second headline. */
.fs-chat-empty-identity{color:rgba(255,255,255,.32);font-size:11px}
.fs-chat-msg{display:flex}
.fs-chat-msg.guest{justify-content:flex-end}
.fs-chat-bubble{max-width:85%;padding:8px 12px;border-radius:14px;border-bottom-left-radius:4px;font-family:var(--flow-font-ui);font-size:13px;line-height:1.45;color:rgba(255,255,255,.9);background:rgba(255,255,255,.08);border:1px solid var(--flow-line);white-space:pre-wrap;overflow-wrap:break-word}
.fs-chat-msg.guest .fs-chat-bubble{background:var(--flow-gold-a12);border-color:var(--flow-gold-a30);border-bottom-left-radius:14px;border-bottom-right-radius:4px;color:#f4ead6}
.fs-chat-composer{display:flex;gap:8px;padding:12px 14px;border-top:1px solid var(--flow-line-2);flex-shrink:0}
.fs-chat-input{flex:1;min-width:0;height:38px;padding:0 14px;border-radius:var(--flow-r-pill);background:rgba(255,255,255,.07);border:1px solid var(--flow-line-2);color:#fff;font-family:var(--flow-font-ui);font-size:13px;outline:none;transition:border-color var(--flow-dur-xs),background var(--flow-dur-xs)}
.fs-chat-input::placeholder{color:rgba(255,255,255,.35)}
.fs-chat-input:focus{border-color:var(--flow-gold-a40);background:rgba(255,255,255,.10)}
.fs-chat-send{width:38px;height:38px;flex-shrink:0;border-radius:50%;background:var(--flow-gold-a12);border:1px solid var(--flow-gold-a30);color:var(--flow-gold);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background var(--flow-dur-xs),border-color var(--flow-dur-xs)}
.fs-chat-send:hover{background:var(--flow-gold-a30)}
.fs-chat-send:focus-visible{outline:2px solid var(--flow-gold);outline-offset:2px}
/* Captions-bar chat toggle: gold "active" tint while open; unread dot while
   closed (cleared on open by the LV). */
.fs-chat-btn{position:relative;padding:0}
.fs-chat-btn.open{background:var(--flow-gold-a12);border-color:var(--flow-gold-a30);color:var(--flow-gold)}
.fs-chat-unread{position:absolute;top:-2px;right:-2px;width:9px;height:9px;border-radius:50%;background:var(--flow-gold);border:1.5px solid #0a0a0f}
@media (max-width: 560px){ .fs-chat-drawer{width:100%;border-left:none} }

/* ════════════════════════════════════════════════════════════════════════
   Widget body - production-widget visibility scope.

   Mirror of the storyboard's `#slot-a.dwe-state-only` overrides in
   `design_system_root.html.heex`. The canonical scenes default to
   `opacity:0; visibility:hidden` because the storyboard demo drives
   reveals via slot_a_timeline.js. The production widget has no such
   timeline - its body is always-on - so we force the active scene
   visible whenever it lives inside `.fs-widget-body` (the class
   widget_shell.ex applies to its body container).

   Keep this in sync with the storyboard override block when adding new
   scenes that default to hidden.
   ════════════════════════════════════════════════════════════════════════ */
.fs-widget-body {
  /* `.fs-room-content` uses `flex: 1; min-height: 0;` to fill its parent.
     Make the body a flex column so the scene can size itself. The
     storyboard's `.fs-main` wrapper provides the same containing block. */
  display: flex;
  flex-direction: column;
}
.fs-widget-body .fs-searching,
.fs-widget-body .fs-enh-wrap,
.fs-widget-body .fs-review-wrap,
.fs-widget-body .fs-pay-wrap,
.fs-widget-body .fs-conf-wrap {
  opacity: 1 !important;
  visibility: visible !important;
  pointer-events: auto !important;
  display: flex !important;
}
.fs-widget-body .fs-room-content {
  opacity: 1 !important;
  display: flex !important;
}
/* Card stagger animations start at opacity:0 - force visible inside the
   widget so they don't depend on the timeline. */
.fs-widget-body .fs-enh-card,
.fs-widget-body .fs-room-card {
  opacity: 1 !important;
  transform: none !important;
}

/* ── loading_overlay (added 2026-05-05; replaces precall + calling) ──
 *
 * Whisper-overlay that floats over the widget body during the connect
 * window (auto-start on mount → first transcript event). The home grid
 * stays the visual constant beneath; this overlay is the bridge.
 *
 * Replaces the older `pre_call_permission` and `calling` scenes which
 * required two full-bleed screen swaps before the agent's first word.
 * The overlay sits at `--flow-z-overlay` (= 120) - above the body, below
 * any modal-level chrome.
 */

.fs-loading-overlay {
  position:          fixed;
  inset:             0;
  display:           flex;
  align-items:       center;
  justify-content:   center;
  background:        var(--flow-modal-bg);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter:   blur(8px);
  /* Sits above `.fs-modal` (z=150) - the widget_shell's modal frame.
     `--flow-z-status` is the token for indicators that need to sit on
     top of the modal contents during transient states. */
  z-index:           var(--flow-z-status);
  animation:         fs-loading-overlay-fade-in var(--flow-dur-md) var(--flow-ease-out);
}

@keyframes fs-loading-overlay-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.fs-loading-overlay-content {
  display:           flex;
  flex-direction:    column;
  align-items:       center;
  gap:               var(--flow-space-3);
  text-align:        center;
  padding:           var(--flow-space-5);
}

.fs-loading-overlay-name {
  font-family:       var(--flow-font-ui);
  font-weight:       300;
  font-size:         clamp(24px, 3vw, 32px);
  letter-spacing:    -0.01em;
  color:             var(--flow-ink);
}

.fs-loading-overlay-status {
  display:           inline-flex;
  align-items:       center;
  gap:               var(--flow-space-2);
  font-family:       var(--flow-font-ui);
  font-weight:       300;
  font-size:         15px;
  color:             var(--flow-ink-65);
}

/* Keep the bouncing dots aligned with the baseline of "connecting". */
.fs-loading-overlay-status .fs-three-dots {
  display:           inline-flex;
  align-items:       baseline;
}

@media (prefers-reduced-motion: reduce) {
  .fs-loading-overlay {
    animation:       none;
  }
}
/* ════════════════════════════════════════════════════════════════════
   Migrated from flowvue_components.css (2026-05-05 - Task #9c)
   Selectors and tokens renamed to the unified .fs-/--flow-* prefix per
   the value-preserving map in flow_tokens.css. The flowvue typography
   block (.fs-h1, .fs-script, etc.) is NOT included here - those
   classes were migrated separately in Task #9b at the top of this file.
   Bare-name semantic aliases (--fg-1, --bg, --accent, etc.) are kept
   as forward aliases in flow_tokens.css and continue to resolve;
   future cleanup migrates them to --flow-fg-1 etc.
   ════════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════════
   FlowVue Components - primitives + Galeón modal shell.

   Layer 3 of the FlowVue stack. Consumes only --flow-* tokens defined in
   flowvue_tokens.css. Discipline: no raw hex outside primitive proofs
   (e.g. canvas #000 fallback). When a value is missing, add it to
   flowvue_tokens.css first.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Primitive: LIVE chip ──────────────────────────────────────────── */
.fs-live {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px 3px 7px;
  border-radius: 20px;
  background: rgba(0, 0, 0, .30);
  border: 1px solid rgba(74, 222, 128, .25);
  font-family: var(--flow-font-ui);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: var(--flow-tracking-label);
  text-transform: uppercase;
  color: var(--flow-ink);
  flex-shrink: 0;
}
.fs-live::before {
  content: '';
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--flow-live-green);
  box-shadow: 0 0 5px rgba(74, 222, 128, .6);
  animation: fs-live-pulse var(--flow-dur-pulse) ease-in-out infinite;
}
@keyframes fs-live-pulse {
  0%, 100% { opacity: 1;   box-shadow: 0 0 5px rgba(74,222,128,.6); }
  50%      { opacity: .55; box-shadow: 0 0 11px rgba(74,222,128,.85); }
}

/* ── Primitive: Waveform ───────────────────────────────────────────── */
.fs-wave {
  display: inline-flex;
  align-items: center;
  gap: 2.5px;
  height: 18px;
  width: 110px;
  flex-shrink: 0;
}
.fs-wave .b {
  width: 2.5px;
  border-radius: 1px;
  background: var(--flow-gold);
  opacity: .55;
  height: 12%;
}
.fs-wave.agent .b { background: var(--flow-gold); opacity: .55; }
.fs-wave.agent .b:nth-child(1)  { animation: fs-wA1  5.0s ease-in-out infinite; }
.fs-wave.agent .b:nth-child(2)  { animation: fs-wA2  4.2s ease-in-out infinite; }
.fs-wave.agent .b:nth-child(3)  { animation: fs-wA3  3.6s ease-in-out infinite; }
.fs-wave.agent .b:nth-child(4)  { animation: fs-wA4  4.6s ease-in-out infinite; }
.fs-wave.agent .b:nth-child(5)  { animation: fs-wA5  3.8s ease-in-out infinite; }
.fs-wave.agent .b:nth-child(6)  { animation: fs-wA6  3.2s ease-in-out infinite; }
.fs-wave.agent .b:nth-child(7)  { animation: fs-wA7  4.8s ease-in-out infinite; }
.fs-wave.agent .b:nth-child(8)  { animation: fs-wA8  3.6s ease-in-out infinite; }
.fs-wave.agent .b:nth-child(9)  { animation: fs-wA9  4.4s ease-in-out infinite; }
.fs-wave.agent .b:nth-child(10) { animation: fs-wA10 5.2s ease-in-out infinite; }
@keyframes fs-wA1  { 0%,100%{height:10%} 30%{height:50%} 60%{height:18%} }
@keyframes fs-wA2  { 0%,100%{height:14%} 30%{height:65%} 60%{height:24%} }
@keyframes fs-wA3  { 0%,100%{height:18%} 25%{height:78%} 55%{height:28%} }
@keyframes fs-wA4  { 0%,100%{height:16%} 28%{height:88%} 60%{height:22%} }
@keyframes fs-wA5  { 0%,100%{height:18%} 30%{height:95%} 58%{height:30%} }
@keyframes fs-wA6  { 0%,100%{height:16%} 28%{height:84%} 62%{height:26%} }
@keyframes fs-wA7  { 0%,100%{height:14%} 24%{height:74%} 58%{height:22%} }
@keyframes fs-wA8  { 0%,100%{height:14%} 26%{height:62%} 60%{height:22%} }
@keyframes fs-wA9  { 0%,100%{height:12%} 24%{height:50%} 56%{height:18%} }
@keyframes fs-wA10 { 0%,100%{height:12%} 30%{height:36%} 62%{height:14%} }
.fs-wave.listening .b { background: rgba(255,255,255,.45); opacity: .80; }
.fs-wave.listening .b:nth-child(odd)  { animation: fs-wL1 6s ease-in-out infinite; }
.fs-wave.listening .b:nth-child(even) { animation: fs-wL2 6s ease-in-out infinite; }
@keyframes fs-wL1 { 0%,100%{height:14%} 50%{height:38%} }
@keyframes fs-wL2 { 0%,100%{height:20%} 50%{height:46%} }
.fs-wave.idle .b { background: rgba(255,255,255,.18); opacity: 1; height: 12%; }

/* ── Primitive: Action button (brand bar circles) ──────────────────── */
.fs-action-btn {
  width: 30px; height: 30px;
  border-radius: 50%;
  background: rgba(255,255,255,.10);
  border: 1px solid var(--flow-line-2);
  display: inline-flex;
  align-items: center; justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
  color: rgba(255,255,255,.6);
  transition: background var(--flow-dur-xs), border-color var(--flow-dur-xs), color var(--flow-dur-xs);
}
.fs-action-btn:hover {
  background: rgba(255,255,255,.18);
  border-color: rgba(255,255,255,.25);
  color: rgba(255,255,255,.85);
}
.fs-action-btn svg { width: 13px; height: 13px; }

/* ── Primitive: Brand mark ────────────────────────────────────────── */
.fs-brand-mark {
  font-family: var(--flow-font-display);
  font-size: 18px;
  font-weight: 600;
  color: rgba(255,255,255,.92);
  line-height: 1;
  flex-shrink: 0;
}
.fs-brand-mark small {
  display: block;
  font-family: var(--flow-font-ui);
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--flow-ink-3);
  margin-top: 3px;
}

/* ── Primitive: Timer ─────────────────────────────────────────────── */
.fs-timer {
  font-family: var(--flow-font-ui);
  font-size: 10px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: rgba(255,255,255,.55);
  flex-shrink: 0;
}

/* ── Galeón modal: full-bleed canvas + glass shell ────────────────── */
.fs-canvas {
  position: fixed; inset: 0;
  overflow: hidden;
  /* Primitive black - token indirection adds no value here. Allowlisted
     by `mix design_system.audit` raw-hex check. */
  background: #000;
  z-index: var(--flow-z-scene);
}
.fs-canvas-hero {
  position: absolute; inset: -4%;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  animation: fs-kenburns 16s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes fs-kenburns {
  from { transform: scale(1.04) translate(0, 0); }
  to   { transform: scale(1.10) translate(-1.5%, -1%); }
}

.fs-modal {
  position: fixed;
  inset: 4% 4%;
  border-radius: var(--flow-r-modal);
  overflow: hidden;
  background: var(--flow-modal-bg);
  backdrop-filter: blur(24px) saturate(120%);
  -webkit-backdrop-filter: blur(24px) saturate(120%);
  border: 1px solid var(--flow-line-3);
  box-shadow: var(--flow-shadow-modal);
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  z-index: var(--flow-z-modal);
  animation: fs-modal-in var(--flow-dur-xl) var(--flow-ease-spring) both;
  color: var(--fg-1);
  font-family: var(--flow-font-ui);
}
/* Fullscreen variant - mobile-app WebView, native shell, or chrome=fullscreen URL.
   Removes inset and border so the modal fills the viewport edge-to-edge. */
.fs-modal--fullscreen {
  inset: 0;
  border-radius: 0;
  border-left: none;
  border-right: none;
  border-top: none;
  border-bottom: none;
  box-shadow: none;
}
@keyframes fs-modal-in {
  from { opacity: 0; transform: translateY(8px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* ── Top brand bar ────────────────────────────────────────────────── */
.fs-topbar {
  display: flex; align-items: center;
  /* Vertical uses --flow-space-4 (16px). Horizontal uses the responsive
     clamp(20px, 2.4vw, 32px) that the progress strip + other in-modal
     surfaces use, so top + bottom edges share visual rhythm.
     Right padding falls back to the embed loader's --flowstay-chrome-inset-right
     when published (iframe-embedded chrome adapts without a redeploy); when
     absent (standalone / dev viewing) it resolves to the same clamp as left. */
  padding: var(--flow-space-4) max(clamp(20px, 2.4vw, 32px), var(--flowstay-chrome-inset-right, 0px)) var(--flow-space-4) clamp(20px, 2.4vw, 32px);
  border-bottom: 1px solid var(--flow-line);
  background: rgba(255,255,255,.015);
}
.fs-topbar .spacer { flex: 1; }
/* §9.0-012 (issue #672): persistent identity chip - a quiet, always-visible
   reminder that the guest is talking to an AI concierge, not hotel staff.
   Deliberately understated (Mr. Cobb's minimal-chrome taste): no badge
   background, just small dim label text beside the brand mark. */
.fs-identity-chip {
  font-family: var(--flow-font-ui);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .01em;
  color: rgba(255,255,255,.4);
  white-space: nowrap;
  margin-left: 16px;
  flex: 0 0 auto;
}
/* issue #672: the "chats may be logged" notice shares the chip's quiet
   treatment but is a full sentence, so it must YIELD to the brand mark
   instead of colliding with it: it shrinks and ellipsizes first, and hides
   entirely on narrow chrome where the chip already carries the identity
   duty. */
.fs-logging-notice {
  font-family: var(--flow-font-ui);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .01em;
  color: rgba(255,255,255,.34);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 0 1 auto;
  min-width: 0;
  max-width: 40ch;
  margin-left: 12px;
  padding-left: 12px;
  border-left: 1px solid rgba(255,255,255,.12);
}
@media (max-width: 960px) {
  .fs-logging-notice { display: none; }
}
.fs-stage-label {
  font-family: var(--flow-font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(255,255,255,.85);
  margin-right: 14px;
}
.fs-topbar-actions { display: flex; gap: 8px; }

/* ── Body slot: switches per stage ────────────────────────────────── */
/* `position: relative` provides a containing block for canonical .fs-* body
   rules that use `position: absolute; inset: 0` (e.g., .fs-home-grid,
   .fs-submenu, .fs-searching, .fs-enh-wrap, .fs-pay-wrap, .fs-conf-wrap). */
.fs-body { position: relative; padding: 14px; overflow: hidden; min-height: 0; }

/* ── Bottom captions bar ─────────────────────────────────────────── */
.fs-botbar {
  display: flex; align-items: center;
  gap: 14px;
  padding: 14px 18px;
  border-top: 1px solid var(--flow-line);
  background: rgba(255,255,255,.02);
  min-height: 64px;
}
.fs-botbar .left { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.fs-botbar .right { display: flex; align-items: center; flex-shrink: 0; }
/* Widget chrome caption text - distinct from `.fs-captions` (storyboard
   captions_bar container with .fs-cap-live + .fs-waveform +
   .fs-caption-text siblings, defined ~line 2011). Renamed 2026-05-05
   from `.fs-captions` to resolve the name-collision flagged by
   `mix design_system.audit` (Task #5). The collision was the "third
   place" inversion: not BEM-aspirational vs legacy-alive, but two
   alive components sharing a class name across different DOM patterns
   (chrome text-slot vs storyboard whole-bar container). Single
   consumer: `widget_live.ex` botbar caption div. */
.fs-botbar-caption {
  flex: 1;
  text-align: center;
  font-family: var(--flow-font-ui);
  font-size: 13px;
  font-weight: 400;
  color: rgba(255,255,255,.85);
  line-height: 1.45;
  letter-spacing: .01em;
  padding: 0 8px;
}
.fs-botbar-caption.muted { color: var(--flow-ink-3); font-style: italic; }
.fs-botbar .fs-wave { width: 56px; height: 14px; gap: 2px; }
.fs-botbar .fs-wave .b { width: 2px; }

/* ── Bottom progress strip wrapper ─────────────────────────────────
   `.fs-progress-slot` wraps `<Scenes.progress_strip />` in the widget
   shell's `<:progress>` slot. The canonical strip itself (the gold
   track + dotted steps) is `.fs-progress` / `.fs-prog-*` defined at
   line ~1955; this rule only owns the slot's outer padding and
   border. */
.fs-progress-slot {
  padding: 18px 28px 16px;
  border-top: 1px solid var(--flow-line);
  background: rgba(255,255,255,.015);
}

/* ── Demo hotel marketing page (/demo/galeon) ────────────────────── */
.fs-demo-page {
  min-height: 100vh;
  background: var(--flow-bg);
  color: var(--fg-1);
  font-family: var(--flow-font-ui);
  position: relative;
  overflow-x: hidden;
}
.fs-demo-hero {
  position: relative;
  height: 100vh;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  display: flex; align-items: flex-end;
  padding: 0 8% 12vh;
}
.fs-demo-hero::before {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.7) 0%, rgba(0,0,0,.2) 50%, rgba(0,0,0,.4) 100%);
}
.fs-demo-hero-content { position: relative; max-width: 720px; }
.fs-demo-hero-eyebrow {
  font-family: var(--flow-font-ui);
  font-size: 11px; font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--flow-gold-ink);
  margin-bottom: 18px;
}
.fs-demo-hero-title {
  font-family: var(--flow-font-display);
  font-weight: 600;
  font-size: clamp(36px, 5vw, 64px);
  line-height: 1.05;
  /* Primitive white on hero gradient - opaque title needs full white;
     `--flow-ink` (rgba .92) is not opaque enough. Allowlisted. */
  color: #fff;
  margin-bottom: 14px;
}
.fs-demo-hero-title em {
  font-family: var(--flow-font-script);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(48px, 6vw, 80px);
  color: var(--flow-gold-ink);
  display: block;
  margin-top: -6px;
}
.fs-demo-hero-sub {
  font-size: 15px;
  line-height: 1.55;
  color: rgba(255,255,255,.78);
  max-width: 56ch;
}

/* Demo top navigation - purely cosmetic so the marketing page looks
   like a real hotel website during the YC pitch. Rendered into the
   hero via the DemoHotelTemplate `:extra` slot and absolute-positioned
   to the top so it floats over the hero photo. Three-column grid:
   left nav · centered logo · right nav with Reserve pill. */
.fs-demo-topbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 5;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(20px, 4vw, 60px);
  padding: clamp(18px, 2.6vh, 32px) clamp(20px, 4vw, 64px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
  font-family: var(--flow-font-ui, 'DM Sans', sans-serif);
  color: rgba(255, 255, 255, 0.92);
}
.fs-demo-topbar-nav {
  display: flex;
  align-items: center;
  gap: clamp(18px, 2.6vw, 36px);
}
.fs-demo-topbar-nav--left { justify-content: flex-start; }
.fs-demo-topbar-nav--right { justify-content: flex-end; }
.fs-demo-topbar-link {
  font-size: clamp(11px, 0.85vw, 13px);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
  transition: color 180ms ease;
}
.fs-demo-topbar-link:hover { color: #fff; }
.fs-demo-topbar-brand {
  text-align: center;
  pointer-events: none;
}
.fs-demo-topbar-logo {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(22px, 2.4vw, 32px);
  letter-spacing: 0.24em;
  font-weight: 500;
  text-transform: uppercase;
  color: #fff;
  line-height: 1;
}
.fs-demo-topbar-tagline {
  font-size: clamp(9px, 0.7vw, 11px);
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
  margin-top: 8px;
}
.fs-demo-topbar-reserve {
  margin-left: clamp(8px, 1vw, 16px);
  padding: clamp(8px, 0.9vw, 11px) clamp(18px, 1.8vw, 28px);
  font-size: clamp(11px, 0.85vw, 13px);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--flow-gold);
  text-decoration: none;
  border: 1px solid var(--flow-gold-a55);
  border-radius: 2px;
  transition: background 180ms ease, border-color 180ms ease;
}
.fs-demo-topbar-reserve:hover {
  background: var(--flow-gold-a10);
  border-color: var(--flow-gold);
}
/* error_banner - floating alert for transient widget errors.
   Sits above .fs-modal (z-status > z-modal) so call-start failures
   stay visible even when the modal chrome is up. */
.fs-error-banner {
  position:      fixed;
  top:           16px;
  left:          50%;
  transform:     translateX(-50%);
  z-index:       var(--flow-z-status);
  background:    var(--flow-danger-rich);
  color:         var(--flow-danger-ink);
  border:        1px solid var(--flow-danger-line);
  border-radius: var(--flow-r-xs);
  padding:       10px 16px;
  font-family:   var(--flow-font-system);
  font-size:     var(--flow-fs-body);
  max-width:     90vw;
  box-shadow:    var(--flow-shadow-card);
}

/* ── Demos index page (/demos) ─────────────────────────────────────
   Marketing-style grid of demo properties. Distinct from
   .fs-demo-* (above), which styles a single hotel landing page. */
.fs-demo-index-page {
  max-width:   1080px;
  margin:      0 auto;
  padding:     80px 32px 60px;
  font-family: var(--flow-font-system);
  min-height:  100vh;
  background:  var(--flow-bg);
  color:       var(--flow-ink-strong);
}
.fs-demo-index-header {
  text-align:    center;
  margin-bottom: 56px;
}
.fs-demo-index-header h1 {
  font-size:      32px;
  font-weight:    600;
  color:          var(--flow-ink-pure);
  margin-bottom:  10px;
  letter-spacing: -0.5px;
}
.fs-demo-index-header h1 span {
  color: var(--flow-brand-blue);
}
.fs-demo-index-header p {
  color:       var(--flow-ink-meta);
  font-size:   16px;
  font-weight: 400;
}
.fs-demo-index-grid {
  display:               grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap:                   24px;
}
.fs-demo-index-card {
  background:      var(--flow-bg-deep);
  border:          1px solid var(--flow-tint-2);
  border-radius:   14px;
  cursor:          pointer;
  transition:      all 0.25s ease;
  overflow:        hidden;
  text-decoration: none;
  color:           inherit;
  display:         block;
}
.fs-demo-index-card:hover {
  border-color: var(--flow-brand-blue-a40);
  transform:    translateY(-4px);
  box-shadow:   var(--flow-shadow-demo-card-hover);
}
.fs-demo-index-card-image {
  width:       100%;
  height:      200px;
  object-fit:  cover;
  background:  var(--flow-gradient-demo-placeholder);
  display:     block;
}
.fs-demo-index-card-body {
  padding: 18px 20px;
}
.fs-demo-index-card-body h3 {
  font-size:   17px;
  font-weight: 600;
  color:       var(--flow-ink-pure);
  margin:      0 0 10px;
}
.fs-demo-index-card-badge {
  display:        inline-block;
  background:     var(--flow-brand-blue-a08);
  color:          var(--flow-brand-blue-soft);
  font-size:      11px;
  font-weight:    500;
  padding:        3px 10px;
  border-radius:  6px;
  letter-spacing: 0.3px;
}
.fs-demo-index-empty {
  text-align: center;
  padding:    120px 24px;
  color:      var(--flow-ink-dim);
  font-size:  16px;
}
@media (max-width: 768px) {
  .fs-demo-index-page { padding: 40px 16px; }
  .fs-demo-index-header h1 { font-size: 24px; }
  .fs-demo-index-grid { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  .fs-modal { inset: 2% 2%; }
  .fs-topbar { padding: 12px var(--flowstay-chrome-inset-right, 22px) 12px 14px; }
  .fs-body { padding: 10px; }
  .fs-progress-slot { padding: 14px 18px 12px; }
  .fs-botbar { padding: 12px 14px; gap: 10px; }
  .fs-botbar-caption { font-size: 11.5px; }
  .fs-demo-hero { padding: 0 6% 14vh; }
}

/* Phone breakpoint: prevent the right column and chrome from clipping the
   viewport. The full identity chip and logging notice give way to a short
   chip that renders in full (truncating would hide the recording notice),
   the canvas hero stays inside 100% width, and the home grid falls back to
   a single column. */
.fs-identity-chip--short { display: none; }
@media (max-width: 480px) {
  .fs-topbar { min-width: 0; }
  .fs-identity-chip { display: none; }
  .fs-identity-chip--short {
    display: inline-flex;
    flex: 0 0 auto;
    white-space: nowrap;
  }
  .fs-logging-notice { display: none; }
  /* The brand mark yields; the compliance chip never truncates (issue #697). */
  .fs-brand-mark {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .fs-brand-mark small { display: none; }
  .fs-stage-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .fs-canvas-hero { inset: 0; width: 100%; height: 100%; }
  .fs-home-grid { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .fs-canvas-hero, .fs-modal,
  .fs-live::before, .fs-wave .b, .fs-speak-pill-dot {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}


/* ════════════════════════════════════════════════════════════════════════
   Slot A storyboard - laptop hardware, browser bar, cursor, chooser,
   fade overlay, scrubber. Loaded under the dev-only /design-system route.
   Scoped under #slot-a so production widget surfaces are unaffected.
   Source: flowvue_lv/priv/static/assets/css/slot_a.css
   ════════════════════════════════════════════════════════════════════════ */

/* ── Speak pill - storyboard placement + animation states.
   Reuses .fs-speak-pill from the design system; this layer adds the
   positioning + visible/dimmed transitions that slot_a_timeline.js
   toggles on the #speak-btn element. ─────────────────────────────── */
#slot-a .fs-speak-pill {
  position: absolute;
  bottom: clamp(12px, 1.6vw, 24px);
  right: clamp(12px, 1.6vw, 24px);
  z-index: 20;
  opacity: 0;
  transform: translateY(8px) scale(.92);
  transition: opacity .6s var(--flow-ease-out-snappy, cubic-bezier(.16,1,.3,1)),
              transform .6s var(--flow-ease-spring, cubic-bezier(.34,1.56,.64,1)),
              filter .4s ease;
}
#slot-a .fs-speak-pill.visible {
  opacity: 1;
  transform: translateY(0) scale(1);
}
#slot-a .fs-speak-pill.dimmed {
  opacity: .2;
  filter: grayscale(1) brightness(.7);
  transform: translateY(0) scale(1);
  pointer-events: none;
}

/* ── Storyboard-laptop hardware: macOS reproduction colours.
   The hex literals in the laptop frame, browser bar, and traffic-light
   dots reproduce real macOS hardware/chrome colours; they are not part
   of the design palette. Allowlisted by `mix design_system.audit`
   raw-hex check with this rationale.

   Also: `.storyboard-stage` (renamed from `.fs-stage` 2026-05-05) is
   storyboard chrome - the `.fs-` prefix was misleading and tripped the
   body-vs-chrome lint. ─────────────────────────────────────────── */
#slot-a .storyboard-stage {
  position: fixed;
  inset: 0;
  background: var(--flow-bg-laptop, #111);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* State-only modal override.
   The canonical `.fs-modal` rule (line 2277) is `display: grid` with
   `grid-template-rows: auto 1fr auto auto` - sized for the production
   widget's four direct children (header / body / footer / progress).
   The design-system `/states/<state>` route renders only a single scene
   inside `.fs-main` directly under `.fs-modal`. With grid, that single
   child auto-places into row 1 (`auto` → content height → 0), and every
   scene with `position:absolute; inset:0` collapses to invisibility.
   Switching to flex-column lets `.fs-main`'s `flex:1` fill the modal
   the way it did before the .fs-modal duplicate landed in Task #9c. */
#slot-a .fs-modal {
  display: flex;
  flex-direction: column;
}

/* Legacy storyboard hotel-landing CSS (#slot-a .hw-*) deleted
   2026-05-06: replaced by FlowStayWeb.Components.Flow.DemoHotelTemplate
   which the storyboard's hardware_screenshot/1 scene and the
   production /demos/galeon page both consume. The canonical
   .fs-demo-* rules above (lines 2422-2493) are now the single
   source of truth. */

#slot-a {
  min-height: 100vh;
  font-family: var(--flow-font-ui, 'DM Sans', sans-serif);
  overflow: hidden;
}

/* ── Laptop frame ───────────────────────────────────────────────────── */
#slot-a .laptop { width: min(960px, calc(100vw - 32px), calc((100vh - 40px) * 1.52)); position: relative; flex-shrink: 0; }
#slot-a .laptop-lid { background: linear-gradient(180deg, #2a2a2a 0%, #1c1c1c 100%); border-radius: clamp(8px, 1.4vw, 14px) clamp(8px, 1.4vw, 14px) 3px 3px; border: 1.5px solid rgba(255,255,255,.1); border-bottom: none; padding: clamp(8px, 1.4vw, 14px) clamp(8px, 1.4vw, 14px) 0; position: relative; }
#slot-a .laptop-camera { position: absolute; top: 7px; left: 50%; transform: translateX(-50%); width: 7px; height: 7px; background: #111; border-radius: 50%; border: 1px solid rgba(255,255,255,.06); }
#slot-a .laptop-screen { width: 100%; aspect-ratio: 16/10; background: #111; border-radius: 5px; overflow: hidden; position: relative; display: flex; flex-direction: column; }
#slot-a .laptop-base { width: 106%; margin-left: -3%; height: clamp(12px, 2.2vw, 22px); background: linear-gradient(180deg, #1c1c1c 0%, #252525 100%); border-radius: 0 0 clamp(6px, 1vw, 10px) clamp(6px, 1vw, 10px); border: 1.5px solid rgba(255,255,255,.08); border-top: none; }

/* ── Browser bar ─────────────────────────────────────────────────────── */
#slot-a .browser-bar { height: clamp(22px, 3.5vw, 34px); background: #1e1e26; border-bottom: 1px solid rgba(255,255,255,.06); display: flex; align-items: center; padding: 0 clamp(6px, 1.2vw, 12px); gap: clamp(4px, 0.8vw, 8px); flex-shrink: 0; }
#slot-a .browser-dots { display: flex; gap: 5px; }
#slot-a .browser-dot { width: clamp(6px, 0.9vw, 9px); height: clamp(6px, 0.9vw, 9px); border-radius: 50%; }
#slot-a .bd-r { background: #FF5F57; }
#slot-a .bd-y { background: #FFBD2E; }
#slot-a .bd-g { background: #28C840; }
#slot-a .browser-url { flex: 1; background: rgba(255,255,255,.06); border-radius: 5px; height: clamp(14px, 2vw, 20px); display: flex; align-items: center; padding: 0 clamp(4px, 0.8vw, 8px); gap: clamp(3px, 0.5vw, 5px); margin: 0 clamp(3px, 0.6vw, 6px); }
#slot-a .url-lock { font-size: clamp(6px, 0.9vw, 9px); color: rgba(255,255,255,.3); }
#slot-a .url-text { font-size: clamp(7px, 1vw, 10px); color: rgba(255,255,255,.4); font-family: 'DM Sans', sans-serif; letter-spacing: .02em; }

/* ── Cursor ──────────────────────────────────────────────────────────── */
#slot-a .cursor { position: absolute; pointer-events: none; z-index: 200; opacity: 0; width: 14px; height: 20px; transition: left 1.2s var(--flow-ease-inout, cubic-bezier(.4,0,.2,1)), top 1.2s var(--flow-ease-inout, cubic-bezier(.4,0,.2,1)), opacity .3s; }
#slot-a .cursor.visible { opacity: 1; }

/* ── Speak button + channel chooser ──────────────────────────────────── */
#slot-a .speak-btn { position: absolute; bottom: clamp(8px, 1.6vw, 16px); right: clamp(8px, 1.6vw, 16px); z-index: 20; display: flex; align-items: center; gap: clamp(6px, 1vw, 10px); padding: clamp(6px, 1vw, 10px) clamp(10px, 1.8vw, 18px) clamp(6px, 1vw, 10px) clamp(8px, 1.4vw, 14px); border-radius: 50px; background: rgba(16,16,24,.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(255,255,255,.15); box-shadow: 0 8px 28px rgba(0,0,0,.4); opacity: 0; transform: translateY(8px) scale(.92); transition: opacity .6s var(--flow-ease-out-snappy), transform .6s var(--flow-ease-spring); cursor: pointer; }
#slot-a .speak-btn.visible { opacity: 1; transform: translateY(0) scale(1); }
#slot-a .speak-btn.dimmed { opacity: .2; filter: grayscale(1) brightness(.7); transform: translateY(0) scale(1); pointer-events: none; transition: opacity .4s ease, filter .4s ease, transform .3s ease; }
#slot-a .speak-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--flow-gold, #d4a853); box-shadow: 0 0 6px rgba(212,168,83,.6), 0 0 12px rgba(212,168,83,.3); animation: dotPulse 2s ease-in-out infinite; flex-shrink: 0; }
@keyframes dotPulse { 0%,100% { box-shadow: 0 0 6px rgba(212,168,83,.6), 0 0 12px rgba(212,168,83,.3); } 50% { box-shadow: 0 0 10px rgba(212,168,83,.8), 0 0 20px rgba(212,168,83,.4); } }

/* Channel chooser body rules moved to flow_components.css (canonical body layer). */

/* ── Fade overlay - primitive black for full-screen wash; storyboard
   timeline relies on opacity: 0 → 1 transition only, no token. Allowlisted. */
#slot-a .fade-black { position: absolute; inset: 0; background: #000; opacity: 0; pointer-events: none; transition: opacity .4s ease; z-index: 300; }
#slot-a .fade-black.active { opacity: 1; }

/* ── Slot scrubber (unscoped - fixed-position dev tool) ──────────────── */
.slot-scrubber { position: fixed; left: 50%; top: 14px; transform: translateX(-50%); display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-radius: 999px; background: rgba(10,10,16,.78); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); border: 1px solid rgba(255,255,255,.08); box-shadow: 0 8px 28px rgba(0,0,0,.45); font-family: 'DM Sans', sans-serif; color: rgba(255,255,255,.85); z-index: 9999; width: min(560px, calc(100vw - 28px)); }
.slot-scrubber-btn { appearance: none; border: 0; cursor: pointer; width: 30px; height: 30px; border-radius: 50%; background: rgba(212,168,83,.14); color: var(--flow-gold, #d4a853); display: inline-flex; align-items: center; justify-content: center; transition: background .15s ease, transform .15s ease; }
.slot-scrubber-btn:hover { background: rgba(212,168,83,.24); }
.slot-scrubber-btn:active { transform: scale(.94); }
.slot-scrubber-icon { font-size: 14px; line-height: 1; }
.slot-scrubber-time { font-size: 11px; font-variant-numeric: tabular-nums; color: rgba(255,255,255,.65); min-width: 74px; text-align: center; letter-spacing: .02em; }
.slot-scrubber-bar { flex: 1; appearance: none; -webkit-appearance: none; height: 4px; border-radius: 999px; background: linear-gradient(to right, var(--flow-gold, #d4a853) 0%, var(--flow-gold, #d4a853) calc(var(--p,0) * 1%), rgba(255,255,255,.14) calc(var(--p,0) * 1%), rgba(255,255,255,.14) 100%); cursor: pointer; outline: none; margin: 0; }
.slot-scrubber-bar::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 14px; height: 14px; border-radius: 50%; background: var(--flow-gold, #d4a853); border: 2px solid rgba(10,10,16,.9); box-shadow: 0 0 0 1px rgba(212,168,83,.5); cursor: grab; }
.slot-scrubber-bar::-webkit-slider-thumb:active { cursor: grabbing; }
.slot-scrubber-bar::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--flow-gold, #d4a853); border: 2px solid rgba(10,10,16,.9); box-shadow: 0 0 0 1px rgba(212,168,83,.5); cursor: grab; }
@media (prefers-reduced-motion: reduce) { .slot-scrubber { display: none; } }

/* ════════════════════════════════════════════════════════════════════════
   Spa scenes (§5.7 widget) - service_selection · review(cart) · confirmation

   The `spa_service_selection/1`, `spa_review/1`, and `spa_confirmation/1`
   components (scenes.ex) shipped as unstyled `.fs-spa-*` markup. These rules
   give them bespoke, premium UI matching the room aesthetic.

   VISIBILITY MODEL - mirror `.fs-flow-gathering`, NOT `.fs-review-wrap`:
   the room wrap classes default to `position:absolute;opacity:0;visibility:
   hidden` and are force-shown by the hardcoded `.fs-widget-body` override
   list (line ~1691). The spa classes are NOT in that list, so they must be
   visible-by-default flow layout (width/height 100%, fills the flex-column
   `.fs-widget-body`). Aesthetics are borrowed from the room cards/review;
   layout + visibility are borrowed from gathering.

   FIT THE FRAME - the widget body is a fixed-height device frame. Each scene
   is a flex column with `min-height:0` children and `overflow-y:auto` on the
   scroll region so content never overflows into a tall column. Photo wrappers
   are explicitly `display:flex` (the markup uses inline `<span>`s) with
   clamped heights + `object-fit:cover`, which is what fixes the full-size-
   image defect.
   ════════════════════════════════════════════════════════════════════════ */

/* ── spa/service_selection ────────────────────────────────────────────── */
.fs-spa-menu {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
  /* Transparent: let the widget's translucent warm glass + hero show through,
     matching the room/dining/marina scenes. A solid var(--flow-bg) here read as
     a flat black panel over the resort ambiance. */
  background: transparent;
  padding: clamp(14px, 2vw, 24px) clamp(18px, 2.6vw, 32px) clamp(12px, 1.8vw, 20px);
  box-sizing: border-box;
  gap: clamp(10px, 1.4vw, 16px);
}
.fs-spa-menu-header { flex: 0 0 auto; display: flex; flex-direction: column; gap: clamp(2px, 0.4vw, 4px); }
.fs-spa-menu-title {
  font-family: var(--flow-font-display);
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 600;
  line-height: 1.1;
  color: var(--flow-ink);
  margin: 0;
}
.fs-spa-menu-subtitle {
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.2vw, 14px);
  font-weight: 400;
  color: var(--flow-ink-65);
  margin: 0;
}
/* 2×2 card grid that fits the frame - scrolls internally if it ever can't. */
.fs-spa-menu-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(8px, 1.2vw, 14px);
  overflow-y: auto;
  align-content: start;
  padding-right: 2px;
}

/* ── Spa service-selection: editorial master-detail "menu" ──────────────────
   A two-column split that fits the fixed scene frame. LEFT = a full-bleed
   "stage" (Las Olas Spa venue showcase by default; the previewed treatment's
   large image + detail when a row is tapped). RIGHT = the treatment list.
   `.fs-spa-split` sits ON the .fs-spa-menu wrapper and overrides its flex-column
   with a single full-height grid row; .fs-spa-treatments already forces the
   background transparent so the widget's warm glass + hero show through. */
.fs-spa-menu.fs-spa-split {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
  grid-template-rows: minmax(0, 1fr);
  gap: clamp(16px, 2.2vw, 30px);
  align-items: stretch;
}

/* LEFT - the stage */
.fs-spa-stage {
  position: relative;
  min-width: 0;
  min-height: 0;
  border-radius: var(--flow-r-card);
  overflow: hidden;
  box-shadow: var(--flow-shadow-card);
}
.fs-spa-stage-figure {
  position: absolute;
  inset: 0;
  margin: 0;
}
.fs-spa-stage-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 48%;
  display: block;
}
.fs-spa-stage-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(8, 8, 12, 0.88) 0%,
    rgba(8, 8, 12, 0.52) 30%,
    rgba(8, 8, 12, 0.06) 60%,
    rgba(8, 8, 12, 0.22) 100%
  );
}
.fs-spa-stage-body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(7px, 0.9vw, 12px);
  padding: clamp(18px, 2.4vw, 34px);
}
.fs-spa-stage-eyebrow {
  margin: 0;
  font-family: var(--flow-font-ui);
  font-size: clamp(10px, 1vw, 12px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-gold);
}
.fs-spa-stage-name {
  margin: 0;
  font-family: var(--flow-font-display);
  font-size: clamp(30px, 3.8vw, 54px);
  font-weight: 600;
  line-height: 1.02;
  color: var(--flow-ink-pure);
  text-shadow: var(--flow-shadow-text-strong);
}
.fs-spa-stage-desc {
  margin: 0;
  max-width: 48ch;
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.2vw, 15px);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.82);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.fs-spa-stage-facts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(8px, 1vw, 13px);
  font-family: var(--flow-font-ui);
  font-size: clamp(10px, 1.05vw, 13px);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.74);
}
.fs-spa-stage-fact {
  display: inline-flex;
  align-items: center;
}
.fs-spa-stage-fact:not(:last-child)::after {
  content: "";
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--flow-gold);
  margin-left: clamp(8px, 1vw, 13px);
}
.fs-spa-stage-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(12px, 1.6vw, 22px);
  margin-top: clamp(3px, 0.5vw, 7px);
}
.fs-spa-stage-price {
  font-family: var(--flow-font-display);
  font-size: clamp(24px, 2.6vw, 36px);
  font-weight: 600;
  color: var(--flow-gold-ink);
  font-variant-numeric: tabular-nums;
}
.fs-spa-stage-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.2vw, 15px);
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--flow-bg);
  background: var(--flow-gold);
  border: none;
  border-radius: var(--flow-r-pill);
  padding: clamp(10px, 1.15vw, 14px) clamp(18px, 2vw, 28px);
  cursor: pointer;
  transition: box-shadow var(--flow-dur-xs) var(--flow-ease-out),
    transform var(--flow-dur-xs) var(--flow-ease-out);
}
.fs-spa-stage-cta:hover {
  box-shadow: 0 0 20px var(--flow-gold-a40);
}
.fs-spa-stage-cta:active {
  transform: scale(0.98);
}
.fs-spa-stage-cta svg {
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
}

/* RIGHT - the menu list */
.fs-spa-list {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  gap: clamp(10px, 1.4vw, 18px);
}
.fs-spa-list-head {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(2px, 0.4vw, 5px);
}
.fs-spa-list-eyebrow {
  margin: 0;
  font-family: var(--flow-font-ui);
  font-size: clamp(9px, 0.9vw, 11px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-gold);
}
.fs-spa-list-title {
  margin: 0;
  font-family: var(--flow-font-display);
  font-size: clamp(22px, 2.5vw, 34px);
  font-weight: 600;
  line-height: 1.05;
  color: var(--flow-ink);
}
.fs-spa-list-items {
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.1vw, 14px);
  overflow-y: auto;
}
.fs-spa-list-items > li {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
}
.fs-spa-row {
  flex: 1 1 auto;
  width: 100%;
  min-height: clamp(70px, 9vh, 124px);
  display: grid;
  grid-template-columns: clamp(58px, 6vw, 94px) minmax(0, 1fr) auto;
  align-items: stretch;
  gap: clamp(11px, 1.4vw, 18px);
  text-align: left;
  background: var(--flow-surface-glass-06);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  padding: clamp(8px, 1vw, 12px);
  cursor: pointer;
  font-family: var(--flow-font-ui);
  overflow: hidden;
  transition: border-color var(--flow-dur-xs) var(--flow-ease-out),
    background var(--flow-dur-xs) var(--flow-ease-out),
    transform var(--flow-dur-xs) var(--flow-ease-out);
}
.fs-spa-row:hover {
  border-color: var(--flow-gold-a40);
  background: var(--flow-surface-glass-10);
}
.fs-spa-row:active {
  transform: scale(0.995);
}
.fs-spa-row.is-selected {
  border-color: var(--flow-gold);
  background: var(--flow-gold-a08);
  box-shadow: inset 3px 0 0 var(--flow-gold);
}
.fs-spa-row-thumb {
  position: relative;
  align-self: stretch;
  border-radius: calc(var(--flow-r-card) - 3px);
  overflow: hidden;
  background: var(--flow-bg-soft);
}
.fs-spa-row-thumb img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.fs-spa-row-text {
  min-width: 0;
  align-self: center;
  display: flex;
  flex-direction: column;
  gap: clamp(2px, 0.4vw, 5px);
}
.fs-spa-row-name {
  font-family: var(--flow-font-display);
  font-size: clamp(17px, 1.8vw, 24px);
  font-weight: 600;
  line-height: 1.1;
  color: var(--flow-ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.fs-spa-row-meta {
  font-size: clamp(10px, 1vw, 12px);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--flow-ink-65);
}
.fs-spa-row-price {
  align-self: center;
  justify-self: end;
  padding-right: clamp(6px, 0.8vw, 12px);
  font-family: var(--flow-font-display);
  font-size: clamp(17px, 1.8vw, 24px);
  font-weight: 600;
  color: var(--flow-gold-ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fs-spa-row.is-selected .fs-spa-row-price {
  color: var(--flow-gold);
}
@media (prefers-reduced-motion: reduce) {
  .fs-spa-stage-cta,
  .fs-spa-row {
    transition: none;
  }
  .fs-spa-stage-cta:active,
  .fs-spa-row:active {
    transform: none;
  }
}

/* Service card - horizontal: clamped thumbnail + body. Mirrors the
   `.fs-comparison-card` border/radius/tint vocabulary. */
.fs-spa-card {
  display: flex;
  text-align: left;
  align-items: stretch;
  gap: clamp(8px, 1.1vw, 12px);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  overflow: hidden;
  background: var(--flow-tint);
  min-width: 0;
  padding: 0;
  font-family: var(--flow-font-ui);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  color: inherit;
  transition: border-color .25s ease, box-shadow .25s ease, transform .15s ease;
}
.fs-spa-card:hover { border-color: var(--flow-gold-a40); box-shadow: 0 0 12px var(--flow-gold-a12); }
.fs-spa-card:active { transform: scale(.99); }
.fs-spa-card-photo {
  display: flex;
  flex: 0 0 clamp(86px, 11vw, 120px);
  position: relative;
  overflow: hidden;
  min-height: clamp(86px, 10vw, 110px);
}
.fs-spa-card-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fs-spa-card-body {
  display: flex;
  flex-direction: column;
  gap: clamp(2px, 0.5vw, 5px);
  padding: clamp(8px, 1.1vw, 12px) clamp(10px, 1.3vw, 14px) clamp(8px, 1.1vw, 12px) 0;
  min-width: 0;
  justify-content: center;
}
.fs-spa-card-name {
  font-family: var(--flow-font-display);
  font-size: clamp(15px, 1.8vw, 20px);
  font-weight: 600;
  color: var(--flow-ink-pure);
  line-height: 1.15;
  letter-spacing: -.005em;
}
.fs-spa-card-meta { display: flex; align-items: baseline; gap: clamp(6px, 0.9vw, 10px); }
.fs-spa-card-duration {
  font-size: clamp(9px, 1vw, 11px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
  font-variant-numeric: tabular-nums;
}
.fs-spa-card-price {
  font-size: clamp(11px, 1.3vw, 14px);
  font-weight: 700;
  color: var(--flow-gold-ink);
  font-variant-numeric: tabular-nums;
}
.fs-spa-card-desc {
  font-size: clamp(10px, 1.1vw, 12px);
  color: var(--flow-ink-65);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
/* Loading skeleton - shown while the seeded menu is still in flight (voice/tap
   entry calls list_spa_services async). Reuses .fs-spa-card geometry; the photo
   block and three body lines shimmer so the grid reads as "loading", never an
   empty void. Inert: no hover lift, no pointer. */
.fs-spa-card-skeleton { cursor: default; pointer-events: none; }
.fs-spa-card-skeleton:hover { border-color: var(--flow-line); box-shadow: none; }
.fs-spa-card-skeleton .fs-spa-card-body { gap: clamp(6px, 0.9vw, 9px); }
.fs-spa-skeleton-block,
.fs-spa-skeleton-line {
  background: linear-gradient(
    100deg,
    var(--flow-tint) 30%,
    var(--flow-surface-glass-10) 50%,
    var(--flow-tint) 70%
  );
  background-size: 220% 100%;
  animation: fs-spa-skeleton-shimmer 1.4s ease-in-out infinite;
}
.fs-spa-skeleton-line {
  height: clamp(10px, 1.2vw, 13px);
  border-radius: 5px;
}
.fs-spa-skeleton-line--title { width: 68%; height: clamp(15px, 1.8vw, 20px); }
.fs-spa-skeleton-line--meta { width: 42%; }
.fs-spa-skeleton-line--desc { width: 88%; }
@keyframes fs-spa-skeleton-shimmer {
  from { background-position: 130% 0; }
  to { background-position: -30% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .fs-spa-skeleton-block,
  .fs-spa-skeleton-line { animation: none; }
}
/* Therapist preference - one tidy row: gender pills + named avatars. */
.fs-spa-therapist-pref {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 0.9vw, 10px);
  padding-top: clamp(8px, 1.1vw, 12px);
  border-top: 1px solid var(--flow-line);
}
.fs-spa-therapist-pref-label {
  font-size: clamp(8px, 0.9vw, 10px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
  margin: 0;
}
.fs-spa-therapist-gender { display: flex; gap: clamp(6px, 0.8vw, 8px); flex-wrap: wrap; }
.fs-spa-therapist-gender-option {
  font-family: var(--flow-font-ui);
  font-size: clamp(10px, 1.1vw, 12px);
  font-weight: 500;
  color: var(--flow-ink-65);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: 999px;
  padding: clamp(4px, 0.6vw, 6px) clamp(10px, 1.3vw, 14px);
  white-space: nowrap;
  cursor: pointer;
  transition: border-color .2s ease, color .2s ease;
}
.fs-spa-therapist-gender-option:hover { border-color: var(--flow-gold-a40); color: var(--flow-ink); }
.fs-spa-therapist-named { display: flex; gap: clamp(10px, 1.4vw, 16px); flex-wrap: wrap; }
.fs-spa-therapist-avatar { display: flex; align-items: center; gap: clamp(5px, 0.7vw, 7px); cursor: pointer; }
.fs-spa-therapist-initial {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(26px, 3vw, 34px);
  height: clamp(26px, 3vw, 34px);
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, var(--flow-gold-a30), var(--flow-gold-a10));
  border: 1px solid var(--flow-gold-a40);
  font-family: var(--flow-font-display);
  font-size: clamp(12px, 1.3vw, 15px);
  font-weight: 600;
  color: var(--flow-gold);
  flex-shrink: 0;
}
.fs-spa-therapist-name {
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.2vw, 13px);
  font-weight: 500;
  color: var(--flow-ink-7);
  white-space: nowrap;
}

/* ── spa/review (cart) ────────────────────────────────────────────────── */
.fs-spa-review-wrap {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
  background: transparent;
  padding: clamp(16px, 2.2vw, 28px) clamp(20px, 3vw, 40px);
  box-sizing: border-box;
  gap: clamp(12px, 1.6vw, 18px);
  overflow-y: auto;
  color: var(--flow-ink);
}
.fs-spa-review-header { flex: 0 0 auto; }
.fs-spa-review-title {
  font-family: var(--flow-font-display);
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 600;
  line-height: 1.1;
  color: var(--flow-ink);
  margin: 0;
}
/* Held-treatment card - the hero of the cart. Therapist avatar + name on top,
   then label/value rows (service, date/time), then a prominent price + hold. */
.fs-spa-review-slot {
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.2vw, 14px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  padding: clamp(14px, 2vw, 22px) clamp(16px, 2.4vw, 26px);
}
.fs-spa-review-therapist {
  display: flex;
  align-items: center;
  gap: clamp(10px, 1.4vw, 14px);
  padding-bottom: clamp(10px, 1.4vw, 14px);
  border-bottom: 1px solid var(--flow-line);
}
.fs-spa-review-therapist-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(40px, 5vw, 54px);
  height: clamp(40px, 5vw, 54px);
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, var(--flow-gold-a30), var(--flow-gold-a10));
  border: 1.5px solid var(--flow-gold-a40);
  font-family: var(--flow-font-display);
  font-size: clamp(18px, 2.2vw, 24px);
  font-weight: 600;
  color: var(--flow-gold);
  flex-shrink: 0;
}
.fs-spa-review-therapist-name {
  font-family: var(--flow-font-display);
  font-size: clamp(17px, 2vw, 23px);
  font-weight: 600;
  color: var(--flow-ink-pure);
  line-height: 1.15;
}
/* Label/value rows mirror `.fs-review-row`. */
.fs-spa-review-service,
.fs-spa-review-datetime {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: clamp(8px, 1.4vw, 14px);
}
.fs-spa-review-service-name {
  font-family: var(--flow-font-display);
  font-size: clamp(15px, 1.7vw, 19px);
  font-weight: 600;
  color: var(--flow-ink);
}
.fs-spa-review-duration,
.fs-spa-review-time {
  font-size: clamp(10px, 1.1vw, 13px);
  font-weight: 500;
  color: var(--flow-ink-65);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fs-spa-review-date {
  font-family: var(--flow-font-ui);
  font-size: clamp(13px, 1.5vw, 16px);
  font-weight: 600;
  color: var(--flow-ink);
  font-variant-numeric: tabular-nums;
}
.fs-spa-review-price {
  font-family: var(--flow-font-display);
  font-size: clamp(24px, 3vw, 34px);
  font-weight: 600;
  color: var(--flow-gold);
  font-variant-numeric: tabular-nums;
  padding-top: clamp(6px, 0.9vw, 10px);
  border-top: 1px solid var(--flow-line);
}
.fs-spa-review-hold-status {
  font-size: clamp(9px, 1vw, 11px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-live-green);
}
/* Payment selector - 3 options as pill buttons. */
.fs-spa-review-payment {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.1vw, 12px);
}
.fs-spa-review-payment-label {
  font-size: clamp(11px, 1.2vw, 14px);
  font-weight: 500;
  color: var(--flow-ink-65);
  margin: 0;
}
.fs-spa-review-payment .fs-spa-payment-option,
.fs-spa-payment-option {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.3vw, 15px);
  font-weight: 600;
  color: var(--flow-ink);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: clamp(8px, 1.1vw, 11px);
  padding: clamp(11px, 1.5vw, 16px);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  box-sizing: border-box;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
.fs-spa-payment-option:hover {
  border-color: var(--flow-gold-a40);
  background: var(--flow-gold-a08);
}
.fs-spa-payment-option:active { transform: scale(.99); }

/* ── marina slip-booking (§5.10) ──────────────────────────────────────────
   Reuses the spa pill/card visuals; these rules add the selected-chip state
   (so a tapped vessel/stay chip reads as chosen, not inert) and lay the
   gathering chips out as an inline wrapping row instead of spa's stacked
   full-width payment options. The search/confirm CTAs already inherit
   `.fs-spa-conf-done`'s gold pill - they just need left alignment in the
   gathering/review column. */

/* No flat black panel. The reused fs-spa-* / fs-flow-gathering wrappers paint an
   opaque `var(--flow-bg)`, which reads as a black box over the widget's warm
   glass + hero. Marina goes TRANSPARENT like the dining scenes (the current UI
   scope - Mr. Cobb 2026-05-31: "we no longer use the black background"), so the
   resort ambiance shows through. Scoped via marina's marker classes so spa is
   untouched. */
.fs-marina-gathering,
.fs-marina-gathering .fs-flow-gathering-facts,
.fs-marina-slips,
.fs-marina-review,
.fs-marina-conf { background: transparent; }
/* …but the white vessel/nights chips + greeting washed out against the bright
   marina hero with no scrim. Restore contrast WITHOUT the removed flat-black
   panel (Mr. Cobb 2026-05-31): a feathered dark gradient behind only the facts
   column, reusing the .fs-spa-stage-scrim rgba(8,8,12,…) palette. The existing
   mask-image on the facts panel (display:block variant) feathers its right
   edge, so the photo still reads on the right. 2026-06-02 mobile-reflow. */
.fs-marina-gathering .fs-flow-gathering-facts {
  background: linear-gradient(105deg,
    rgba(8, 8, 12, 0.86) 0%,
    rgba(8, 8, 12, 0.66) 50%,
    rgba(8, 8, 12, 0.46) 100%);
}
.fs-marina-gathering .fs-marina-field { margin-top: clamp(10px, 1.4vw, 16px); }
.fs-marina-gathering .fs-spa-therapist-gender {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(6px, 0.9vw, 10px);
}
.fs-marina-gathering .fs-spa-payment-option {
  width: auto;
  flex: 0 0 auto;
  padding: clamp(8px, 1.1vw, 12px) clamp(12px, 1.6vw, 18px);
}
.fs-marina-gathering .fs-spa-payment-option.is-selected {
  border-color: var(--flow-gold-a40);
  background: var(--flow-gold-a08);
  box-shadow: inset 0 0 0 2px var(--flow-gold-a40);
}
.fs-marina-search-cta,
.fs-marina-confirm-cta { align-self: flex-start; }

/* Slip-card placard overlay (§5.10 R2) */
.fs-marina-slips .fs-spa-card-photo .fs-marina-slip-placard {
  position: absolute;
  top: 8px;
  left: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 4px 8px;
  background: rgba(10, 10, 16, 0.65);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid var(--flow-gold-a40);
  border-radius: 4px;
  z-index: 5;
}

.fs-marina-slips .fs-spa-card-photo .fs-marina-slip-placard-id {
  font-family: var(--flow-font-display);
  font-size: clamp(14px, 1.8vw, 18px);
  font-weight: 600;
  color: var(--flow-gold);
}

.fs-marina-slips .fs-spa-card-photo .fs-marina-slip-placard-label {
  font-family: var(--flow-font-ui);
  font-size: clamp(7px, 0.8vw, 8px);
  letter-spacing: 0.15em;
  color: var(--flow-ink-dim);
}

/* Review (Cart) & Confirmation custom image thread (§5.10 R3) */
.fs-marina-review-photo,
.fs-marina-conf-photo {
  display: flex;
  position: relative;
  width: 100%;
  height: clamp(100px, 15vw, 150px);
  border-radius: var(--flow-r-card);
  overflow: hidden;
  margin-bottom: clamp(10px, 1.4vw, 16px);
}

.fs-marina-review-photo .fs-marina-slip-placard,
.fs-marina-conf-photo .fs-marina-slip-placard {
  position: absolute;
  top: 10px;
  left: 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 4px 8px;
  background: rgba(10, 10, 16, 0.65);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--flow-gold-a40);
  border-radius: 6px;
  z-index: 5;
}

.fs-marina-review-photo .fs-marina-slip-placard-id,
.fs-marina-conf-photo .fs-marina-slip-placard-id {
  font-family: var(--flow-font-display);
  font-size: clamp(14px, 1.8vw, 18px);
  font-weight: 600;
  color: var(--flow-gold);
}

.fs-marina-review-photo .fs-marina-slip-placard-label,
.fs-marina-conf-photo .fs-marina-slip-placard-label {
  font-family: var(--flow-font-ui);
  font-size: clamp(7px, 0.8vw, 8px);
  letter-spacing: 0.15em;
  color: var(--flow-ink-dim);
}

/* ── spa/confirmation (terminal) ──────────────────────────────────────── */
.fs-spa-conf-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  min-height: 0;
  background: transparent;
  padding: clamp(16px, 2.2vw, 28px) clamp(20px, 3vw, 40px);
  box-sizing: border-box;
  gap: clamp(10px, 1.4vw, 16px);
  overflow-y: auto;
  color: var(--flow-ink);
  text-align: center;
}
.fs-spa-conf-header { flex: 0 0 auto; }
.fs-spa-conf-title {
  font-family: var(--flow-font-display);
  font-size: clamp(22px, 2.8vw, 34px);
  font-weight: 600;
  line-height: 1.1;
  color: var(--flow-ink-pure);
  margin: 0;
}
/* Confirmed-treatment card - terminal summary. */
.fs-spa-conf-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(6px, 0.9vw, 10px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  padding: clamp(16px, 2.2vw, 26px) clamp(20px, 3vw, 36px);
  width: min(440px, 90%);
  box-sizing: border-box;
}
.fs-spa-conf-therapist-name {
  font-family: var(--flow-font-display);
  font-size: clamp(18px, 2.2vw, 26px);
  font-weight: 600;
  color: var(--flow-ink-pure);
  line-height: 1.15;
}
.fs-spa-conf-service-name {
  font-family: var(--flow-font-ui);
  font-size: clamp(13px, 1.5vw, 16px);
  font-weight: 500;
  color: var(--flow-ink-65);
}
.fs-spa-conf-datetime { display: flex; align-items: baseline; gap: clamp(6px, 0.9vw, 10px); }
.fs-spa-conf-date {
  font-family: var(--flow-font-ui);
  font-size: clamp(13px, 1.5vw, 16px);
  font-weight: 600;
  color: var(--flow-ink);
  font-variant-numeric: tabular-nums;
}
.fs-spa-conf-time {
  font-size: clamp(11px, 1.2vw, 14px);
  font-weight: 500;
  color: var(--flow-ink-65);
  font-variant-numeric: tabular-nums;
}
.fs-spa-conf-price {
  font-family: var(--flow-font-display);
  font-size: clamp(24px, 3vw, 34px);
  font-weight: 600;
  color: var(--flow-gold);
  font-variant-numeric: tabular-nums;
  padding: clamp(6px, 0.9vw, 10px) 0;
  margin-top: clamp(2px, 0.4vw, 4px);
  border-top: 1px solid var(--flow-line);
  width: 100%;
}
/* Reference + payment - small label/value stacks. */
.fs-spa-conf-reference,
.fs-spa-conf-payment {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(2px, 0.3vw, 3px);
}
.fs-spa-conf-reference-label,
.fs-spa-conf-payment-label {
  font-size: clamp(8px, 0.9vw, 10px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
}
.fs-spa-conf-reference-value {
  font-family: var(--flow-font-mono);
  font-size: clamp(11px, 1.2vw, 13px);
  font-weight: 500;
  color: var(--flow-gold-ink);
  letter-spacing: .08em;
}
.fs-spa-conf-payment-value {
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.3vw, 14px);
  font-weight: 600;
  color: var(--flow-ink);
}
.fs-spa-conf-arrival {
  flex: 0 0 auto;
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.2vw, 13px);
  font-weight: 500;
  color: var(--flow-ink-7);
}
.fs-spa-conf-cancel {
  flex: 0 0 auto;
  font-size: clamp(10px, 1.1vw, 12px);
  font-style: italic;
  color: var(--flow-ink-65);
  max-width: 42ch;
  line-height: 1.45;
}
.fs-spa-conf-done {
  flex: 0 0 auto;
  margin-top: clamp(4px, 0.7vw, 8px);
  display: flex;
  align-items: center;
  justify-content: center;
  height: clamp(34px, 4vw, 42px);
  padding: 0 clamp(28px, 4vw, 44px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: linear-gradient(135deg, var(--flow-gold-a25), var(--flow-gold-a15));
  border: 1px solid var(--flow-gold-a40);
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.25vw, 13px);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--flow-gold);
}

/* ── spa/treatment_detail (§5.7 P4) ──────────────────────────────────────
   Mirrors .fs-room-detail-* token vocabulary; tokens only from the spa set. */
.fs-spa-detail {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
  background: transparent;
  box-sizing: border-box;
}
.fs-spa-detail-hero {
  position: relative;
  flex: 0 0 clamp(140px, 26vw, 210px);
  min-height: 0;
  overflow: hidden;
  border-bottom: 1px solid var(--flow-line);
}
.fs-spa-detail-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
}
.fs-spa-detail-gradient {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,.6) 100%);
  pointer-events: none;
}
.fs-spa-detail-overlay {
  position: absolute;
  left: clamp(12px, 2vw, 20px);
  bottom: clamp(10px, 1.6vw, 16px);
  right: clamp(12px, 2vw, 20px);
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.fs-spa-detail-name {
  font-family: var(--flow-font-display);
  font-size: clamp(18px, 2.6vw, 28px);
  font-weight: 600;
  color: var(--flow-ink-pure);
  line-height: 1.15;
  letter-spacing: -.005em;
  text-shadow: 0 1px 8px rgba(0,0,0,.6);
}
.fs-spa-detail-price {
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.4vw, 14px);
  font-weight: 700;
  color: var(--flow-live-green);
  text-shadow: 0 1px 4px rgba(0,0,0,.5);
}
.fs-spa-detail-gallery {
  flex: 0 0 auto;
  display: flex;
  gap: clamp(4px, 0.7vw, 7px);
  padding: clamp(6px, 0.9vw, 9px) clamp(12px, 1.8vw, 18px);
  border-bottom: 1px solid var(--flow-line);
  overflow-x: auto;
}
.fs-spa-detail-thumb {
  flex: 0 0 clamp(44px, 6vw, 60px);
  height: clamp(30px, 4.2vw, 44px);
  border-radius: clamp(4px, 0.6vw, 6px);
  overflow: hidden;
  border: 1px solid var(--flow-line);
  cursor: pointer;
  background: none;
  padding: 0;
  appearance: none;
  transition: border-color .2s ease;
}
.fs-spa-detail-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fs-spa-detail-thumb.active { border-color: var(--flow-gold); }
.fs-spa-detail-thumb:hover { border-color: var(--flow-gold-a40); }
.fs-spa-detail-body {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.4vw, 14px);
  padding: clamp(12px, 1.6vw, 18px) clamp(14px, 2vw, 22px);
  overflow-y: auto;
}
.fs-spa-detail-description {
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.4vw, 14px);
  font-weight: 400;
  color: var(--flow-ink-65);
  line-height: 1.55;
  margin: 0;
  max-width: 62ch;
}
.fs-spa-detail-facts {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(12px, 2vw, 20px) clamp(20px, 3vw, 32px);
  padding: clamp(8px, 1.2vw, 12px) 0;
  border-top: 1px solid var(--flow-line);
  border-bottom: 1px solid var(--flow-line);
}
.fs-spa-detail-fact { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fs-spa-detail-fact-label {
  font-size: clamp(8px, 0.9vw, 9px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: rgba(255,255,255,.42);
}
.fs-spa-detail-fact-value {
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.4vw, 14px);
  font-weight: 600;
  color: var(--flow-ink);
}
.fs-spa-detail-cta {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  height: clamp(34px, 4vw, 42px);
  padding: 0 clamp(28px, 4vw, 44px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: linear-gradient(135deg, var(--flow-gold-a25), var(--flow-gold-a15));
  border: 1px solid var(--flow-gold-a40);
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.25vw, 13px);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--flow-gold);
  cursor: pointer;
  appearance: none;
  transition: background .2s ease, box-shadow .2s ease;
  width: 100%;
  margin-top: auto;
}
.fs-spa-detail-cta:hover { box-shadow: 0 0 14px var(--flow-gold-a12); }

/* ── spa/enhancements (§5.7 P4) ──────────────────────────────────────────
   Mirrors .fs-enh-* token vocabulary with spa-scoped class names. */
.fs-spa-enh-wrap {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
  background: transparent;
  box-sizing: border-box;
}
.fs-spa-enh-context {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: clamp(6px, 0.9vw, 10px);
  padding: clamp(6px, 0.9vw, 10px) clamp(12px, 1.8vw, 18px);
  border-bottom: 1px solid var(--flow-line);
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.2vw, 13px);
  color: var(--flow-ink-65);
}
.fs-spa-enh-context-name {
  font-family: var(--flow-font-display);
  font-size: clamp(13px, 1.6vw, 17px);
  font-weight: 600;
  color: var(--flow-ink-pure);
  letter-spacing: -.005em;
}
.fs-spa-enh-context-sep { color: var(--flow-ink-3); font-weight: 400; }
.fs-spa-enh-context-price { font-weight: 700; color: var(--flow-live-green); font-variant-numeric: tabular-nums; }
.fs-spa-enh-context-tag {
  margin-left: auto;
  font-size: clamp(8px, 0.9vw, 10px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: 999px;
  padding: clamp(2px, 0.3vw, 3px) clamp(8px, 1vw, 10px);
}
.fs-spa-enh-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(6px, 1.2vw, 12px);
  padding: clamp(8px, 1.4vw, 14px) clamp(10px, 1.6vw, 16px);
  flex: 1;
  min-height: 0;
  align-content: start;
  overflow-y: auto;
}
/* Room/widget enhancements grid (id #room-enh-grid) carries exactly 4 add-ons,
   incl. the Celebration Package. At 3-col the 4th card lands alone in row 2 -
   below the fold in the widget panel, so the package + its image never show.
   Force 2x2 UNCONDITIONALLY for this scene so all four cards are above the fold
   (#2a). Scoped by id so the spa enhancements grid keeps its wide-width 3-col. */
#room-enh-grid.fs-spa-enh-grid {
  grid-template-columns: repeat(2, 1fr);
}
.fs-spa-enh-card {
  border-radius: var(--flow-r-pay);
  overflow: hidden;
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  display: flex;
  flex-direction: column;
  cursor: pointer;
  appearance: none;
  padding: 0;
  text-align: left;
  transition: border-color .2s ease, box-shadow .2s ease;
}
.fs-spa-enh-card:hover { border-color: var(--flow-gold-a40); box-shadow: 0 0 12px var(--flow-gold-a12); }
.fs-spa-enh-card.is-selected { border-color: var(--flow-gold); box-shadow: 0 0 0 1px var(--flow-gold); }
.fs-spa-enh-img { width: 100%; aspect-ratio: 4/3; position: relative; overflow: hidden; }
.fs-spa-enh-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.fs-spa-enh-body {
  padding: clamp(8px, 1.4vw, 14px) clamp(10px, 1.6vw, 16px);
  display: flex;
  flex-direction: column;
  gap: clamp(2px, 0.5vw, 5px);
}
.fs-spa-enh-name {
  font-size: clamp(13px, 1.5vw, 17px);
  font-weight: 600;
  color: var(--flow-ink-pure);
  line-height: 1.25;
  letter-spacing: -.005em;
}
.fs-spa-enh-desc { font-size: clamp(11px, 1.2vw, 14px); color: var(--flow-ink-65); line-height: 1.4; }
.fs-spa-enh-price {
  font-size: clamp(11px, 1.4vw, 15px);
  font-weight: 600;
  color: var(--flow-gold-ink);
  margin-top: clamp(4px, 0.7vw, 8px);
  font-variant-numeric: tabular-nums;
}

/* ── spa/searching - slot chip grid (§5.7 P4) ────────────────────────────
   Renders the slot picker (time · therapist · price). Mirrors .fs-spa-menu
   shell but with a chip grid instead of the card grid. */
.fs-spa-slot-wrap {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
  background: transparent;
  padding: clamp(14px, 2vw, 24px) clamp(18px, 2.6vw, 32px) clamp(12px, 1.8vw, 20px);
  box-sizing: border-box;
  gap: clamp(10px, 1.4vw, 16px);
}
.fs-spa-slot-header { flex: 0 0 auto; display: flex; flex-direction: column; gap: clamp(2px, 0.4vw, 4px); }
.fs-spa-slot-title {
  font-family: var(--flow-font-display);
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 600;
  line-height: 1.1;
  color: var(--flow-ink);
  margin: 0;
}
.fs-spa-slot-subtitle {
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.2vw, 14px);
  font-weight: 400;
  color: var(--flow-ink-65);
  margin: 0;
}
.fs-spa-slot-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(6px, 1vw, 10px);
  overflow-y: auto;
  align-content: start;
}
.fs-spa-slot-chip {
  display: flex;
  flex-direction: column;
  gap: clamp(3px, 0.5vw, 5px);
  padding: clamp(10px, 1.4vw, 14px) clamp(12px, 1.6vw, 16px);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  background: var(--flow-tint);
  cursor: pointer;
  appearance: none;
  text-align: left;
  font-family: var(--flow-font-ui);
  transition: border-color .2s ease, box-shadow .2s ease;
}
.fs-spa-slot-chip:hover { border-color: var(--flow-gold-a40); box-shadow: 0 0 10px var(--flow-gold-a12); }
.fs-spa-slot-chip.is-selected { border-color: var(--flow-gold); box-shadow: 0 0 0 1px var(--flow-gold); }
.fs-spa-slot-time {
  font-family: var(--flow-font-display);
  font-size: clamp(16px, 1.8vw, 20px);
  font-weight: 600;
  color: var(--flow-ink-pure);
  letter-spacing: -.005em;
}
.fs-spa-slot-therapist {
  display: flex;
  align-items: center;
  gap: clamp(4px, 0.6vw, 6px);
  font-size: clamp(11px, 1.2vw, 13px);
  color: var(--flow-ink-65);
}
.fs-spa-slot-therapist-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(18px, 2.2vw, 22px);
  height: clamp(18px, 2.2vw, 22px);
  border-radius: 50%;
  background: var(--flow-gold-a25);
  border: 1px solid var(--flow-gold-a40);
  font-size: clamp(9px, 1vw, 11px);
  font-weight: 600;
  color: var(--flow-gold-ink);
}
.fs-spa-slot-therapist-name { font-weight: 500; color: var(--flow-ink-65); }
.fs-spa-slot-price {
  font-size: clamp(11px, 1.3vw, 14px);
  font-weight: 700;
  color: var(--flow-gold-ink);
  font-variant-numeric: tabular-nums;
  margin-top: clamp(2px, 0.3vw, 4px);
}

/* ════════════════════════════════════════════════════════════════════════
   Dining scenes (§5.9 widget) - outlet_selection · availability_anchors ·
   searching · slot_selection · no_availability · enhancements ·
   contact_confirm · review_confirm · confirmation

   The `dining_*` components (scenes.ex) shipped as `.fs-dining-*` markup with
   ZERO backing CSS, so the scenes rendered unstyled. These rules give them the
   same premium look as the spa scenes - borrowing the spa's token vocabulary
   (--flow-* only; no new color/spacing primitives) so dining matches spa and
   the room scenes exactly.

   VISIBILITY MODEL - same as the spa block above: the top-level dining wrap
   classes are NOT in the `.fs-widget-body` hardcoded override list, so they
   must be visible-by-default fill layout (width/height 100%, flex column),
   NOT the hidden-by-default room `.fs-*-wrap` pattern. Each scene is a flex
   column with `min-height:0` + `overflow-y:auto` so content never overflows
   the fixed-height device frame.
   ════════════════════════════════════════════════════════════════════════ */

/* ── shared scene shell (every dining scene root) ─────────────────────────
   outlet_selection · anchors · slot_selection · no_availability ·
   enhancements · contact_confirm · review_confirm - all share this fill shell. */
.fs-dining-outlet-selection,
.fs-dining-anchors,
.fs-dining-slot-selection,
.fs-dining-no-availability,
.fs-dining-enhancements,
.fs-dining-contact-confirm,
.fs-dining-review-confirm {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
  /* Transparent: let the widget's translucent warm glass + hero show through,
     matching the room/spa scenes. A solid var(--flow-bg) here read as a flat
     black panel over the resort ambiance. */
  background: transparent;
  padding: clamp(14px, 2vw, 24px) clamp(18px, 2.6vw, 32px) clamp(12px, 1.8vw, 20px);
  box-sizing: border-box;
  gap: clamp(10px, 1.4vw, 16px);
  overflow-y: auto;
  color: var(--flow-ink);
}

/* Any tap target shows the pointer cursor - divs/images with phx-click default
   to the text/arrow cursor otherwise. (Disabled targets show not-allowed.) */
[phx-click]:not([disabled]) { cursor: pointer; }
[phx-click][disabled] { cursor: not-allowed; }

/* Thin, subtle scrollbar for the dining scroll panels (replaces the chunky
   default bar). Gold-tinted thumb on a transparent track; matches the dev-HUD. */
.fs-dining-outlet-selection, .fs-dining-anchors, .fs-dining-slot-selection,
.fs-dining-no-availability, .fs-dining-enhancements, .fs-dining-contact-confirm,
.fs-dining-review-confirm, .fs-dining-restaurant-detail {
  scrollbar-width: thin;
  scrollbar-color: rgba(212, 168, 83, 0.35) transparent;
}
.fs-dining-outlet-selection::-webkit-scrollbar, .fs-dining-anchors::-webkit-scrollbar,
.fs-dining-slot-selection::-webkit-scrollbar, .fs-dining-no-availability::-webkit-scrollbar,
.fs-dining-enhancements::-webkit-scrollbar, .fs-dining-contact-confirm::-webkit-scrollbar,
.fs-dining-review-confirm::-webkit-scrollbar, .fs-dining-restaurant-detail::-webkit-scrollbar { width: 7px; height: 7px; }
.fs-dining-outlet-selection::-webkit-scrollbar-thumb, .fs-dining-anchors::-webkit-scrollbar-thumb,
.fs-dining-slot-selection::-webkit-scrollbar-thumb, .fs-dining-no-availability::-webkit-scrollbar-thumb,
.fs-dining-enhancements::-webkit-scrollbar-thumb, .fs-dining-contact-confirm::-webkit-scrollbar-thumb,
.fs-dining-review-confirm::-webkit-scrollbar-thumb, .fs-dining-restaurant-detail::-webkit-scrollbar-thumb {
  background: rgba(212, 168, 83, 0.28); border-radius: 4px;
}
.fs-dining-outlet-selection::-webkit-scrollbar-track, .fs-dining-restaurant-detail::-webkit-scrollbar-track { background: transparent; }

/* ── shared header / title / subtitle ─────────────────────────────────── */
.fs-dining-header { flex: 0 0 auto; display: flex; flex-direction: column; gap: clamp(2px, 0.4vw, 4px); }
.fs-dining-title {
  font-family: var(--flow-font-display);
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 600;
  line-height: 1.1;
  color: var(--flow-ink);
  margin: 0;
}
.fs-dining-subtitle {
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.2vw, 14px);
  font-weight: 400;
  color: var(--flow-ink-65);
  margin: 0;
}

/* ── shared label/value field row (anchors · enhancements · contact) ──── */
.fs-dining-field {
  display: flex;
  flex-direction: column;
  gap: clamp(5px, 0.8vw, 9px);
  padding: clamp(10px, 1.4vw, 15px) 0;
  border-bottom: 1px solid var(--flow-line);
}
.fs-dining-field-label {
  font-size: clamp(8px, 0.9vw, 10px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
}
.fs-dining-field-value {
  font-family: var(--flow-font-display);
  font-size: clamp(15px, 1.7vw, 19px);
  font-weight: 600;
  color: var(--flow-ink);
  line-height: 1.15;
}

/* ── shared chip vocabulary (time · seating · occasion · dietary · date) ──
   One pill-button look mirroring `.fs-spa-therapist-gender-option`. */
.fs-dining-time-chip,
.fs-dining-seating-chip,
.fs-dining-occasion-chip,
.fs-dining-dietary-chip,
.fs-dining-date-pill {
  font-family: var(--flow-font-ui);
  font-size: clamp(10px, 1.1vw, 12px);
  font-weight: 500;
  color: var(--flow-ink-65);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: 999px;
  padding: clamp(5px, 0.7vw, 7px) clamp(11px, 1.4vw, 15px);
  white-space: nowrap;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.fs-dining-time-chip:hover,
.fs-dining-seating-chip:hover,
.fs-dining-occasion-chip:hover,
.fs-dining-dietary-chip:hover,
.fs-dining-date-pill:hover {
  border-color: var(--flow-gold-a40);
  color: var(--flow-ink);
}
.fs-dining-time-chip.active,
.fs-dining-seating-chip.active,
.fs-dining-occasion-chip.active,
.fs-dining-dietary-chip.active,
.fs-dining-date-pill.active {
  background: var(--flow-gold-a15);
  border-color: var(--flow-gold-a40);
  color: var(--flow-gold);
}
.fs-dining-time-chips,
.fs-dining-seating-chips,
.fs-dining-occasion-chips,
.fs-dining-dietary-chips,
.fs-dining-date-pills {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(6px, 0.8vw, 8px);
}

/* ── shared primary / secondary action buttons ───────────────────────────
   Primary (search · skip · confirm) mirrors `.fs-spa-conf-done`'s gold gradient.
   Secondary (back) is the quieter outline variant. */
.fs-dining-search-btn,
.fs-dining-skip-btn,
.fs-dining-confirm-btn {
  flex: 0 0 auto;
  align-self: flex-start;
  margin-top: clamp(4px, 0.7vw, 8px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: clamp(34px, 4vw, 42px);
  padding: 0 clamp(20px, 3vw, 32px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: linear-gradient(135deg, var(--flow-gold-a25), var(--flow-gold-a15));
  border: 1px solid var(--flow-gold-a40);
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.25vw, 13px);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--flow-gold);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, transform .15s ease, background .2s ease;
}
.fs-dining-search-btn:hover,
.fs-dining-skip-btn:hover,
.fs-dining-confirm-btn:hover { border-color: var(--flow-gold-a60); }
.fs-dining-search-btn:active,
.fs-dining-skip-btn:active,
.fs-dining-confirm-btn:active { transform: scale(.99); }
/* The skip button is intentionally quieter - it's the "no thanks" path. */
.fs-dining-skip-btn {
  background: var(--flow-tint);
  border-color: var(--flow-line);
  color: var(--flow-ink-65);
}
.fs-dining-skip-btn:hover { border-color: var(--flow-gold-a40); color: var(--flow-ink); }

.fs-dining-back-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: clamp(34px, 4vw, 42px);
  padding: 0 clamp(18px, 2.6vw, 28px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.25vw, 13px);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--flow-ink-65);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, color .2s ease, transform .15s ease;
}
.fs-dining-back-btn:hover { border-color: var(--flow-gold-a40); color: var(--flow-ink); }
.fs-dining-back-btn:active { transform: scale(.99); }

/* ── outlet_selection ─────────────────────────────────────────────────── */
.fs-dining-outlet-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(8px, 1.2vw, 14px);
  overflow-y: auto;
  align-content: start;
  padding-right: 2px;
}
/* Outlet card - vertical stack: name, cuisine, hours, badge. Mirrors
   `.fs-spa-card`'s border/radius/tint vocabulary. */
.fs-dining-outlet-card {
  display: flex;
  flex-direction: column;
  text-align: left;
  gap: clamp(2px, 0.5vw, 5px);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  background: var(--flow-tint);
  padding: clamp(12px, 1.6vw, 18px) clamp(13px, 1.8vw, 20px);
  min-width: 0;
  font-family: var(--flow-font-ui);
  color: inherit;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .25s ease, box-shadow .25s ease, transform .15s ease;
}
/* Reservable cards are the tappable hero - gold-leaning. */
.fs-dining-outlet-card--reservable { cursor: pointer; }
.fs-dining-outlet-card--reservable:hover {
  border-color: var(--flow-gold-a40);
  box-shadow: 0 0 12px var(--flow-gold-a12);
}
.fs-dining-outlet-card--reservable:active { transform: scale(.99); }
/* Walk-in cards are quieter (informational, not bookable). */
.fs-dining-outlet-card--walkin { opacity: .82; }
/* Photo-card variant - replaces the tint background with a hero image.
   The card becomes a fixed-height image container with a bottom-gradient
   overlay and text anchored to the bottom, mirroring fs-grid-tile but
   in the 2-up outlet grid. */
.fs-dining-outlet-card-photo{position:relative;overflow:hidden;padding:0;height:clamp(110px,16vw,150px);background:var(--flow-tint)}
.fs-dining-outlet-card-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;will-change:transform;transition:transform .35s ease}
.fs-dining-outlet-card--reservable .fs-dining-outlet-card-img:hover,.fs-dining-outlet-card--reservable:hover .fs-dining-outlet-card-img{transform:scale(1.04)}
.fs-dining-outlet-card-overlay{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 30%,rgba(0,0,0,.72) 100%);z-index:1;display:flex;flex-direction:column;justify-content:flex-end;padding:clamp(8px,1.2vw,12px) clamp(10px,1.4vw,14px);gap:1px}
.fs-dining-outlet-name {
  font-family: var(--flow-font-display);
  font-size: clamp(15px, 1.8vw, 20px);
  font-weight: 600;
  color: var(--flow-ink-pure);
  line-height: 1.15;
  letter-spacing: -.005em;
}
.fs-dining-outlet-cuisine {
  font-size: clamp(10px, 1.1vw, 12px);
  color: var(--flow-ink-65);
  line-height: 1.4;
}
.fs-dining-outlet-badge {
  align-self: flex-start;
  margin-top: clamp(4px, 0.6vw, 7px);
  font-size: clamp(8px, 0.9vw, 10px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-gold);
  background: var(--flow-gold-a15);
  border: 1px solid var(--flow-gold-a40);
  border-radius: 999px;
  padding: clamp(2px, 0.4vw, 4px) clamp(8px, 1.1vw, 12px);
}
.fs-dining-outlet-badge--walkin {
  color: var(--flow-ink-65);
  background: var(--flow-tint);
  border-color: var(--flow-line);
}

/* ── availability_anchors ─────────────────────────────────────────────── */
.fs-dining-anchors-form {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
/* Party-size stepper - two square nudge buttons. */
.fs-dining-stepper { display: flex; gap: clamp(6px, 0.8vw, 8px); }
.fs-dining-step-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(30px, 3.4vw, 38px);
  height: clamp(30px, 3.4vw, 38px);
  border-radius: clamp(7px, 0.9vw, 9px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  font-family: var(--flow-font-ui);
  font-size: clamp(15px, 1.8vw, 20px);
  font-weight: 600;
  color: var(--flow-ink);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  line-height: 1;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
.fs-dining-step-btn:hover { border-color: var(--flow-gold-a40); background: var(--flow-gold-a08); }
.fs-dining-step-btn:active { transform: scale(.96); }

/* ── slot_selection ───────────────────────────────────────────────────── */
.fs-dining-slot-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(78px, 10vw, 104px), 1fr));
  gap: clamp(8px, 1.2vw, 12px);
  overflow-y: auto;
  align-content: start;
  padding-right: 2px;
}
.fs-dining-slot-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: clamp(40px, 4.8vw, 52px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.4vw, 16px);
  font-weight: 600;
  color: var(--flow-ink);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
.fs-dining-slot-chip:hover { border-color: var(--flow-gold-a40); background: var(--flow-gold-a08); }
.fs-dining-slot-chip:active { transform: scale(.98); }

/* ── no_availability ──────────────────────────────────────────────────── */
.fs-dining-noavail-offers {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.1vw, 12px);
  overflow-y: auto;
}
/* Offer row - full-width pill; rendered as a <button> (tap) or <div> (voice),
   both pick up this look. Mirrors `.fs-spa-payment-option`. */
.fs-dining-noavail-offer {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  text-align: left;
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.3vw, 15px);
  font-weight: 600;
  color: var(--flow-ink);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: clamp(8px, 1.1vw, 11px);
  padding: clamp(11px, 1.5vw, 16px);
  width: 100%;
  box-sizing: border-box;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
/* Only the button variant is interactive. */
button.fs-dining-noavail-offer { cursor: pointer; }
button.fs-dining-noavail-offer:hover {
  border-color: var(--flow-gold-a40);
  background: var(--flow-gold-a08);
}
button.fs-dining-noavail-offer:active { transform: scale(.99); }
.fs-dining-noavail-actions { flex: 0 0 auto; display: flex; gap: clamp(8px, 1.1vw, 12px); }

/* ── enhancements / contact_confirm forms ────────────────────────────────
   Both reuse `.fs-dining-field`; the form wrapper just scrolls. */
.fs-dining-enhancements-form,
.fs-dining-contact-form {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* ── review_confirm ───────────────────────────────────────────────────── */
.fs-dining-review-summary {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.2vw, 12px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  padding: clamp(14px, 2vw, 22px) clamp(16px, 2.4vw, 26px);
}
/* Label/value rows mirror `.fs-spa-review-service`. */
.fs-dining-review-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: clamp(8px, 1.4vw, 14px);
}
.fs-dining-review-label {
  font-size: clamp(9px, 1vw, 11px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
  white-space: nowrap;
}
.fs-dining-review-value {
  font-family: var(--flow-font-display);
  font-size: clamp(14px, 1.6vw, 18px);
  font-weight: 600;
  color: var(--flow-ink);
  text-align: right;
}
.fs-dining-review-actions {
  flex: 0 0 auto;
  display: flex;
  gap: clamp(8px, 1.1vw, 12px);
  margin-top: clamp(4px, 0.7vw, 8px);
}

/* ── confirmation (terminal) ──────────────────────────────────────────── */
.fs-dining-conf-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  min-height: 0;
  background: var(--flow-bg);
  padding: clamp(16px, 2.2vw, 28px) clamp(20px, 3vw, 40px);
  box-sizing: border-box;
  gap: clamp(10px, 1.4vw, 16px);
  overflow-y: auto;
  color: var(--flow-ink);
  text-align: center;
}
.fs-dining-conf-details {
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.2vw, 12px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  padding: clamp(16px, 2.2vw, 26px) clamp(20px, 3vw, 36px);
  width: min(440px, 90%);
  box-sizing: border-box;
}
.fs-dining-conf-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(2px, 0.3vw, 3px);
}
.fs-dining-conf-label {
  font-size: clamp(8px, 0.9vw, 10px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
}
.fs-dining-conf-value {
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.3vw, 14px);
  font-weight: 600;
  color: var(--flow-ink);
}
/* The 7R- code is the hero - mono + gold, like `.fs-spa-conf-reference-value`. */
.fs-dining-conf-code {
  font-family: var(--flow-font-mono);
  font-size: clamp(15px, 1.9vw, 22px);
  font-weight: 500;
  color: var(--flow-gold-ink);
  letter-spacing: .08em;
}
.fs-dining-conf-note {
  flex: 0 0 auto;
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.2vw, 13px);
  font-weight: 500;
  color: var(--flow-ink-7);
  max-width: 42ch;
  line-height: 1.45;
}
.fs-dining-conf-done {
  flex: 0 0 auto;
  margin-top: clamp(4px, 0.7vw, 8px);
  display: flex;
  align-items: center;
  justify-content: center;
  height: clamp(34px, 4vw, 42px);
  padding: 0 clamp(28px, 4vw, 44px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: linear-gradient(135deg, var(--flow-gold-a25), var(--flow-gold-a15));
  border: 1px solid var(--flow-gold-a40);
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.25vw, 13px);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--flow-gold);
}

/* ─── Dining restaurant detail (§5.9-010 discovery scene) ───────────────────
   Mirrors fs-room-detail gallery layout. Hero + gallery strip + meta + menu
   highlights + Reserve CTA. Reuses flow_tokens.css variables throughout.
   ──────────────────────────────────────────────────────────────────────────── */

.fs-dining-restaurant-detail{display:flex;flex-direction:column;flex:1;min-height:0;overflow-y:auto}
.fs-dining-detail-hero{position:relative;flex:0 0 auto;height:clamp(140px,22vw,200px);overflow:hidden;border-radius:clamp(8px,1.2vw,12px) clamp(8px,1.2vw,12px) 0 0;border:1px solid var(--flow-line)}
.fs-dining-detail-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;will-change:transform;animation:fsKB1 8s ease-in-out infinite alternate;transition:transform .8s ease-in-out}
.fs-dining-detail-hero-gradient{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 35%,rgba(0,0,0,.65) 100%);pointer-events:none}
.fs-dining-detail-hero-overlay{position:absolute;left:clamp(12px,2vw,20px);bottom:clamp(10px,1.6vw,16px);right:clamp(12px,2vw,20px);z-index:2;display:flex;flex-direction:column;gap:2px}
.fs-dining-detail-name{font-family:'Cormorant Garamond',serif;font-size:clamp(18px,2.6vw,26px);font-weight:600;color:var(--flow-ink-pure);line-height:1.15;letter-spacing:-.005em;text-shadow:0 1px 8px rgba(0,0,0,.6)}
.fs-dining-detail-cuisine{font-family:var(--flow-font-ui);font-size:clamp(11px,1.3vw,13px);font-weight:500;color:rgba(255,255,255,.75);text-shadow:0 1px 4px rgba(0,0,0,.5)}
.fs-dining-detail-gallery{display:flex;gap:clamp(6px,1vw,8px);padding:clamp(6px,1vw,10px) clamp(10px,1.6vw,16px);overflow-x:auto;flex:0 0 auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.fs-dining-detail-gallery::-webkit-scrollbar{display:none}
.fs-dining-detail-gallery-thumb{appearance:none;-webkit-appearance:none;background:none;padding:0;margin:0;flex:0 0 auto;width:clamp(72px,12vw,100px);height:clamp(48px,8vw,68px);border-radius:clamp(5px,0.8vw,7px);overflow:hidden;border:1px solid var(--flow-line);cursor:pointer;transition:opacity .15s ease,transform .15s ease,border-color .15s ease,outline-color .15s ease;outline:2px solid transparent;outline-offset:0}
.fs-dining-detail-gallery-thumb:hover{opacity:.88;transform:translateY(-1px)}
.fs-dining-detail-gallery-thumb.is-active{border-color:var(--flow-gold);outline:2px solid var(--flow-gold);outline-offset:0}
.fs-dining-detail-gallery-img{width:100%;height:100%;object-fit:cover;display:block}
.fs-dining-detail-body{flex:1 1 0;min-height:0;display:flex;flex-direction:column;gap:clamp(10px,1.4vw,14px);padding:clamp(8px,1.4vw,14px) clamp(10px,1.6vw,16px)}
.fs-dining-detail-meta{display:flex;flex-wrap:wrap;gap:clamp(6px,1vw,10px);align-items:center;padding-bottom:clamp(6px,1vw,10px);border-bottom:1px solid var(--flow-line)}
.fs-dining-detail-hours{font-family:var(--flow-font-ui);font-size:clamp(11px,1.25vw,13px);font-weight:500;color:var(--flow-ink-65)}
.fs-dining-detail-dress{font-family:var(--flow-font-ui);font-size:clamp(11px,1.25vw,13px);font-weight:500;color:var(--flow-ink-65);padding-left:clamp(8px,1.2vw,12px);border-left:1px solid var(--flow-line)}
/* Signature menu - reads like a printed fine-dining menu: serif dish names,
   italic descriptions, gold prices, open rows separated by a hairline (not
   boxed form cards). */
.fs-dining-detail-menu{display:flex;flex-direction:column;gap:clamp(6px,0.9vw,10px)}
.fs-dining-detail-menu-title{font-family:var(--flow-font-ui);font-size:clamp(10px,1.1vw,11px);font-weight:600;color:var(--flow-gold);margin:0 0 2px;text-transform:uppercase;letter-spacing:var(--flow-tracking-caps)}
.fs-dining-detail-menu-items{display:flex;flex-direction:column}
.fs-dining-detail-menu-item{display:flex;align-items:center;gap:clamp(10px,1.4vw,14px);padding:clamp(9px,1.3vw,13px) 2px;border-bottom:1px solid var(--flow-line)}
.fs-dining-detail-menu-item:last-child{border-bottom:none}
.fs-dining-detail-dish-thumb{width:clamp(56px,7vw,76px);aspect-ratio:1;object-fit:cover;border-radius:clamp(6px,0.9vw,10px);flex:0 0 auto;cursor:pointer;transition:opacity .15s ease,transform .15s ease}
.fs-dining-detail-dish-thumb:hover{opacity:.85;transform:scale(1.03)}
.fs-dining-detail-dish-thumb-btn{flex:0 0 auto;display:block;line-height:0;padding:0;border:0;background:none;cursor:pointer;border-radius:clamp(6px,0.9vw,10px)}
.fs-dining-detail-dish-text{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:3px}
.fs-dining-detail-dish-row{display:flex;align-items:baseline;justify-content:space-between;gap:clamp(10px,1.6vw,16px)}
.fs-dining-detail-dish-name{font-family:'Cormorant Garamond',serif;font-size:clamp(16px,2vw,20px);font-weight:600;color:var(--flow-ink);line-height:1.1;letter-spacing:.2px}
.fs-dining-detail-dish-price{font-family:var(--flow-font-ui);font-size:clamp(11px,1.25vw,13px);font-weight:600;color:var(--flow-gold);white-space:nowrap;letter-spacing:.02em}
.fs-dining-detail-dish-desc{font-family:var(--flow-font-ui);font-style:italic;font-size:clamp(11px,1.2vw,12.5px);font-weight:400;color:var(--flow-ink-65);line-height:1.5;margin:0;max-width:52ch}
.fs-dining-detail-reserve-btn{flex:0 0 auto;width:100%;margin-top:clamp(6px,1vw,10px);display:flex;align-items:center;justify-content:center;height:clamp(38px,4.5vw,46px);border-radius:clamp(8px,1.1vw,11px);background:linear-gradient(135deg,var(--flow-gold-a25),var(--flow-gold-a15));border:1px solid var(--flow-gold-a40);font-family:var(--flow-font-ui);font-size:clamp(12px,1.4vw,14px);font-weight:600;letter-spacing:.04em;color:var(--flow-gold);cursor:pointer;transition:opacity 0.15s ease}
.fs-dining-detail-reserve-btn:hover{opacity:.85}
.fs-dining-detail-reserve-btn:active{transform:scale(.99)}

/* ════════════════════════════════════════════════════════════════════════
   GOLF SCENES (§5.10) - tee-time booking flow
   ────────────────────────────────────────────────────────────────────────
   The `golf_*` components (scenes.ex) shipped as `.fs-golf-*` markup with
   ZERO backing CSS, so the 8 golf scenes rendered as unstyled HTML while spa
   and dining were fully styled. These rules bring golf to parity, borrowing
   the SAME token vocabulary (--flow-* only) and design language as the dining
   block above - golf's scene structure (header, label/value fields, chips,
   stepper, slot grid, review rows, terminal confirmation) is a near mirror of
   dining, so the two read as one system.

   VISIBILITY MODEL - same as the spa/dining blocks: the top-level golf wrap
   classes are NOT in the `.fs-widget-body` hardcoded override list, so they
   must be visible-by-default fill layout (width/height 100%, flex column),
   NOT the hidden-by-default room `.fs-*-wrap` pattern. Each scene is a flex
   column with `min-height:0` + `overflow-y:auto` so content never overflows
   the fixed-height device frame.

   Booking wrappers are `background: transparent` (widget scene-bg standard,
   precedents at css:2760/3261/3419/3538) so the widget's warm glass + the
   El Galeón hero photo show through - the photo carries the scene.
   ════════════════════════════════════════════════════════════════════════ */

/* ── shared scene shell (every golf scene root) ───────────────────────────
   course_detail · availability_anchors · slot_selection · no_availability ·
   enhancements · review (cart) · confirmation - all share this fill shell. */
.fs-golf-course-detail,
.fs-golf-anchors,
.fs-golf-slot-selection,
.fs-golf-no-availability,
.fs-golf-enhancements,
.fs-golf-review-wrap,
.fs-golf-conf-wrap {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
  background: transparent;
  padding: clamp(14px, 2vw, 24px) clamp(18px, 2.6vw, 32px) clamp(12px, 1.8vw, 20px);
  box-sizing: border-box;
  gap: clamp(10px, 1.4vw, 16px);
  overflow-y: auto;
  color: var(--flow-ink);
}

/* Thin, subtle scrollbar for the golf scroll panels - matches the dining bar. */
.fs-golf-course-detail, .fs-golf-anchors, .fs-golf-slot-selection,
.fs-golf-no-availability, .fs-golf-enhancements, .fs-golf-review-wrap,
.fs-golf-conf-wrap {
  scrollbar-width: thin;
  scrollbar-color: rgba(212, 168, 83, 0.35) transparent;
}
.fs-golf-course-detail::-webkit-scrollbar, .fs-golf-anchors::-webkit-scrollbar,
.fs-golf-slot-selection::-webkit-scrollbar, .fs-golf-no-availability::-webkit-scrollbar,
.fs-golf-enhancements::-webkit-scrollbar, .fs-golf-review-wrap::-webkit-scrollbar,
.fs-golf-conf-wrap::-webkit-scrollbar { width: 7px; height: 7px; }
.fs-golf-course-detail::-webkit-scrollbar-thumb, .fs-golf-anchors::-webkit-scrollbar-thumb,
.fs-golf-slot-selection::-webkit-scrollbar-thumb, .fs-golf-no-availability::-webkit-scrollbar-thumb,
.fs-golf-enhancements::-webkit-scrollbar-thumb, .fs-golf-review-wrap::-webkit-scrollbar-thumb,
.fs-golf-conf-wrap::-webkit-scrollbar-thumb {
  background: rgba(212, 168, 83, 0.28); border-radius: 4px;
}

/* ── shared header / title / subtitle ─────────────────────────────────── */
.fs-golf-header { flex: 0 0 auto; display: flex; flex-direction: column; gap: clamp(2px, 0.4vw, 4px); }
.fs-golf-title {
  font-family: var(--flow-font-display);
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 600;
  line-height: 1.1;
  color: var(--flow-ink);
  margin: 0;
}
.fs-golf-subtitle {
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.2vw, 14px);
  font-weight: 400;
  color: var(--flow-ink-65);
  margin: 0;
}

/* ── shared label/value field row (anchors · enhancements) ────────────── */
.fs-golf-field {
  display: flex;
  flex-direction: column;
  gap: clamp(5px, 0.8vw, 9px);
  padding: clamp(10px, 1.4vw, 15px) 0;
  border-bottom: 1px solid var(--flow-line);
}
.fs-golf-field-label {
  font-size: clamp(8px, 0.9vw, 10px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
}
.fs-golf-field-meta {
  font-family: var(--flow-font-ui);
  font-size: clamp(10px, 1.1vw, 12px);
  font-weight: 500;
  color: var(--flow-ink-65);
  font-variant-numeric: tabular-nums;
}
.fs-golf-field-value {
  font-family: var(--flow-font-display);
  font-size: clamp(15px, 1.7vw, 19px);
  font-weight: 600;
  color: var(--flow-ink);
  line-height: 1.15;
}

/* ── shared chip vocabulary (date · guest-type · time · toggle) ─────────
   One pill-button look mirroring the dining chip set. */
.fs-golf-date-pill,
.fs-golf-guest-type-chip,
.fs-golf-time-chip,
.fs-golf-toggle-chip {
  font-family: var(--flow-font-ui);
  font-size: clamp(10px, 1.1vw, 12px);
  font-weight: 500;
  color: var(--flow-ink-65);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: 999px;
  padding: clamp(5px, 0.7vw, 7px) clamp(11px, 1.4vw, 15px);
  white-space: nowrap;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.fs-golf-date-pill:hover,
.fs-golf-guest-type-chip:hover,
.fs-golf-time-chip:hover,
.fs-golf-toggle-chip:hover {
  border-color: var(--flow-gold-a40);
  color: var(--flow-ink);
}
.fs-golf-date-pill.active,
.fs-golf-guest-type-chip.active,
.fs-golf-time-chip.active,
.fs-golf-toggle-chip.active {
  background: var(--flow-gold-a15);
  border-color: var(--flow-gold-a40);
  color: var(--flow-gold);
}
.fs-golf-date-pills,
.fs-golf-guest-type-chips,
.fs-golf-time-chips,
.fs-golf-toggle-chips {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(6px, 0.8vw, 8px);
}

/* ── shared primary / secondary action buttons ───────────────────────────
   Primary (reserve · search · confirm · skip) mirrors the dining CTA gold
   gradient; skip is the quieter "no thanks" variant; back is an outline.
   The gold "look" is shared with the confirmation done button; only the four
   buttons carry the interactive affordances (cursor / appearance / transition). */
.fs-golf-reserve-btn,
.fs-golf-search-btn,
.fs-golf-skip-btn,
.fs-golf-confirm-btn,
.fs-golf-conf-done {
  flex: 0 0 auto;
  align-self: flex-start;
  margin-top: clamp(4px, 0.7vw, 8px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: clamp(34px, 4vw, 42px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: linear-gradient(135deg, var(--flow-gold-a25), var(--flow-gold-a15));
  border: 1px solid var(--flow-gold-a40);
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.25vw, 13px);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--flow-gold);
}
.fs-golf-reserve-btn,
.fs-golf-search-btn,
.fs-golf-skip-btn,
.fs-golf-confirm-btn {
  padding: 0 clamp(20px, 3vw, 32px);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, transform .15s ease, background .2s ease;
}
.fs-golf-reserve-btn:hover,
.fs-golf-search-btn:hover,
.fs-golf-skip-btn:hover,
.fs-golf-confirm-btn:hover { border-color: var(--flow-gold-a60); }
.fs-golf-reserve-btn:active,
.fs-golf-search-btn:active,
.fs-golf-skip-btn:active,
.fs-golf-confirm-btn:active { transform: scale(.99); }
.fs-golf-skip-btn {
  background: var(--flow-tint);
  border-color: var(--flow-line);
  color: var(--flow-ink-65);
}
.fs-golf-skip-btn:hover { border-color: var(--flow-gold-a40); color: var(--flow-ink); }

.fs-golf-back-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: clamp(34px, 4vw, 42px);
  padding: 0 clamp(18px, 2.6vw, 28px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.25vw, 13px);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--flow-ink-65);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, color .2s ease, transform .15s ease;
}
.fs-golf-back-btn:hover { border-color: var(--flow-gold-a40); color: var(--flow-ink); }
.fs-golf-back-btn:active { transform: scale(.99); }

/* ── course_detail ────────────────────────────────────────────────────── */
.fs-golf-description {
  flex: 0 0 auto;
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.3vw, 15px);
  font-weight: 400;
  line-height: 1.55;
  color: var(--flow-ink-7);
  max-width: 60ch;
}
.fs-golf-included {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 0.9vw, 10px);
  padding-top: clamp(8px, 1.1vw, 12px);
  border-top: 1px solid var(--flow-line);
}
.fs-golf-included-label {
  font-size: clamp(8px, 0.9vw, 10px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
}
.fs-golf-included-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(6px, 0.8vw, 9px);
}
.fs-golf-included-item {
  font-family: var(--flow-font-ui);
  font-size: clamp(10px, 1.1vw, 12px);
  font-weight: 500;
  color: var(--flow-ink);
  background: var(--flow-surface-glass-06);
  border: 1px solid var(--flow-line);
  border-radius: 999px;
  padding: clamp(4px, 0.6vw, 6px) clamp(10px, 1.3vw, 14px);
  white-space: nowrap;
}

/* ── availability_anchors ─────────────────────────────────────────────── */
.fs-golf-anchors-form {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
/* Golfers stepper - two square nudge buttons. */
.fs-golf-stepper { display: flex; gap: clamp(6px, 0.8vw, 8px); }
.fs-golf-step-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(30px, 3.4vw, 38px);
  height: clamp(30px, 3.4vw, 38px);
  border-radius: clamp(7px, 0.9vw, 9px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  font-family: var(--flow-font-ui);
  font-size: clamp(15px, 1.8vw, 20px);
  font-weight: 600;
  color: var(--flow-ink);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  line-height: 1;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
.fs-golf-step-btn:hover { border-color: var(--flow-gold-a40); background: var(--flow-gold-a08); }
.fs-golf-step-btn:active { transform: scale(.96); }

/* ── slot_selection ───────────────────────────────────────────────────── */
.fs-golf-slot-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(88px, 11vw, 120px), 1fr));
  gap: clamp(8px, 1.2vw, 12px);
  overflow-y: auto;
  align-content: start;
  padding-right: 2px;
}
/* Each slot chip stacks the tee time over its rate (time is the hero). Renders
   as a <button> (tap) or <div> (voice) - both pick up this look. */
.fs-golf-slot-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(2px, 0.4vw, 4px);
  height: clamp(52px, 6.4vw, 68px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
button.fs-golf-slot-chip:hover { border-color: var(--flow-gold-a40); background: var(--flow-gold-a08); }
button.fs-golf-slot-chip:active { transform: scale(.98); }
.fs-golf-slot-time {
  font-family: var(--flow-font-display);
  font-size: clamp(14px, 1.6vw, 18px);
  font-weight: 600;
  color: var(--flow-ink);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.fs-golf-slot-rate {
  font-family: var(--flow-font-ui);
  font-size: clamp(10px, 1.1vw, 12px);
  font-weight: 600;
  color: var(--flow-gold-ink);
  font-variant-numeric: tabular-nums;
}

/* ── no_availability ──────────────────────────────────────────────────── */
.fs-golf-noavail-offers {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.1vw, 12px);
  overflow-y: auto;
}
/* Offer row - full-width pill; <button> (tap) or <div> (voice) both style. */
.fs-golf-noavail-offer {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  text-align: left;
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.3vw, 15px);
  font-weight: 600;
  color: var(--flow-ink);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: clamp(8px, 1.1vw, 11px);
  padding: clamp(11px, 1.5vw, 16px);
  width: 100%;
  box-sizing: border-box;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
button.fs-golf-noavail-offer { cursor: pointer; }
button.fs-golf-noavail-offer:hover {
  border-color: var(--flow-gold-a40);
  background: var(--flow-gold-a08);
}
button.fs-golf-noavail-offer:active { transform: scale(.99); }
.fs-golf-noavail-actions { flex: 0 0 auto; display: flex; gap: clamp(8px, 1.1vw, 12px); }

/* ── enhancements ─────────────────────────────────────────────────────── */
.fs-golf-enhancements-form {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
/* Each enhancement is one horizontal row: name + per-round price on the left,
   the current value and Yes/No toggle chips pushed to the right. */
.fs-golf-enhancement-row {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(6px, 1vw, 12px);
}
.fs-golf-enhancement-row .fs-golf-field-label { flex: 0 0 auto; }
.fs-golf-enhancement-row .fs-golf-field-meta { flex: 0 0 auto; }
.fs-golf-enhancement-row .fs-golf-field-value {
  flex: 1 1 auto;
  text-align: right;
  font-size: clamp(13px, 1.5vw, 16px);
  color: var(--flow-ink-65);
}
.fs-golf-enhancement-row .fs-golf-toggle-chips { flex: 0 0 auto; }

/* ── review (cart) ────────────────────────────────────────────────────── */
/* Held tee-time card - the hero of the cart. Date/time header, then
   label/value rows, then a prominent total + hold status. */
.fs-golf-review-slot {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.2vw, 14px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  padding: clamp(14px, 2vw, 22px) clamp(16px, 2.4vw, 26px);
}
.fs-golf-review-datetime {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: clamp(8px, 1.4vw, 14px);
  padding-bottom: clamp(8px, 1.2vw, 12px);
  border-bottom: 1px solid var(--flow-line);
}
.fs-golf-review-date {
  font-family: var(--flow-font-display);
  font-size: clamp(17px, 2vw, 23px);
  font-weight: 600;
  color: var(--flow-ink-pure);
  font-variant-numeric: tabular-nums;
}
.fs-golf-review-time {
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.4vw, 16px);
  font-weight: 600;
  color: var(--flow-gold-ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Label/value rows mirror the dining review-row vocabulary. */
.fs-golf-review-golfers,
.fs-golf-review-rate {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: clamp(8px, 1.4vw, 14px);
}
.fs-golf-review-golfers-label,
.fs-golf-review-rate-label {
  font-size: clamp(9px, 1vw, 11px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
  white-space: nowrap;
}
.fs-golf-review-golfers-value,
.fs-golf-review-rate-value {
  font-family: var(--flow-font-display);
  font-size: clamp(14px, 1.6vw, 18px);
  font-weight: 600;
  color: var(--flow-ink);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.fs-golf-review-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: clamp(8px, 1.4vw, 14px);
  padding-top: clamp(8px, 1.2vw, 12px);
  border-top: 1px solid var(--flow-line);
}
.fs-golf-review-total-label {
  font-size: clamp(10px, 1.1vw, 12px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-65);
}
.fs-golf-review-total-value {
  font-family: var(--flow-font-display);
  font-size: clamp(22px, 2.7vw, 30px);
  font-weight: 600;
  color: var(--flow-gold);
  font-variant-numeric: tabular-nums;
}
.fs-golf-review-hold-status {
  font-size: clamp(9px, 1vw, 11px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-live-green);
}
/* Payment selector - 3 options as full-width pill buttons. */
.fs-golf-review-payment {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.1vw, 12px);
}
.fs-golf-review-payment-label {
  font-size: clamp(11px, 1.2vw, 14px);
  font-weight: 500;
  color: var(--flow-ink-65);
  margin: 0;
}
.fs-golf-payment-option {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.3vw, 15px);
  font-weight: 600;
  color: var(--flow-ink);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: clamp(8px, 1.1vw, 11px);
  padding: clamp(11px, 1.5vw, 16px);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  box-sizing: border-box;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
button.fs-golf-payment-option:hover {
  border-color: var(--flow-gold-a40);
  background: var(--flow-gold-a08);
}
button.fs-golf-payment-option:active { transform: scale(.99); }
.fs-golf-payment-option.active {
  border-color: var(--flow-gold-a40);
  background: var(--flow-gold-a15);
  color: var(--flow-gold);
}

/* ── confirmation (terminal) ──────────────────────────────────────────── */
.fs-golf-conf-details {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.2vw, 12px);
  background: var(--flow-tint);
  border: 1px solid var(--flow-line);
  border-radius: var(--flow-r-card);
  padding: clamp(16px, 2.2vw, 26px) clamp(18px, 2.6vw, 28px);
}
.fs-golf-conf-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: clamp(8px, 1.4vw, 14px);
}
.fs-golf-conf-label {
  font-size: clamp(8px, 0.9vw, 10px);
  font-weight: 600;
  letter-spacing: var(--flow-tracking-caps);
  text-transform: uppercase;
  color: var(--flow-ink-3);
  white-space: nowrap;
}
.fs-golf-conf-value {
  font-family: var(--flow-font-ui);
  font-size: clamp(12px, 1.3vw, 15px);
  font-weight: 600;
  color: var(--flow-ink);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
/* The EZL- code is the hero - mono + gold, like the dining conf-code. */
.fs-golf-conf-code {
  font-family: var(--flow-font-mono);
  font-size: clamp(15px, 1.9vw, 22px);
  font-weight: 500;
  color: var(--flow-gold-ink);
  letter-spacing: .08em;
}
.fs-golf-conf-total {
  font-family: var(--flow-font-display);
  font-size: clamp(16px, 1.9vw, 21px);
  font-weight: 600;
  color: var(--flow-gold);
}
.fs-golf-conf-note,
.fs-golf-conf-arrival,
.fs-golf-conf-cancel {
  flex: 0 0 auto;
  font-family: var(--flow-font-ui);
  font-size: clamp(11px, 1.2vw, 13px);
  font-weight: 500;
  color: var(--flow-ink-7);
  max-width: 52ch;
  line-height: 1.45;
}
.fs-golf-conf-cancel { color: var(--flow-ink-65); }
.fs-golf-conf-done { padding: 0 clamp(28px, 4vw, 44px); }

/* ── Golf photography ─────────────────────────────────────────────────────
   Photo carries the scene: a prominent course hero on course_detail, a banner
   on slot_selection, and small package thumbs on the enhancement rows. Glass
   over photo via the scrim; minimal chrome, mirroring the spa stage treatment. */
.fs-golf-hero {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: clamp(10px, 1.4vw, 16px);
  overflow: hidden;
  margin-bottom: clamp(14px, 2vw, 22px);
}
.fs-golf-hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 46%;
  display: block;
}
.fs-golf-hero-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(8, 8, 12, 0.72) 0%,
    rgba(8, 8, 12, 0.28) 34%,
    rgba(8, 8, 12, 0.02) 62%,
    rgba(8, 8, 12, 0.18) 100%
  );
}
.fs-golf-slot-photo {
  position: relative;
  width: 100%;
  aspect-ratio: 21 / 9;
  border-radius: clamp(10px, 1.4vw, 16px);
  overflow: hidden;
  margin-bottom: clamp(12px, 1.6vw, 18px);
}
.fs-golf-slot-photo-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 46%;
  display: block;
}
.fs-golf-enh-photo {
  flex: 0 0 auto;
  width: clamp(56px, 8vw, 88px);
  aspect-ratio: 1 / 1;
  border-radius: clamp(8px, 1vw, 12px);
  overflow: hidden;
}
.fs-golf-enh-photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

@media (prefers-reduced-motion: reduce) {
  .fs-golf-reserve-btn, .fs-golf-search-btn, .fs-golf-skip-btn,
  .fs-golf-confirm-btn, .fs-golf-back-btn, .fs-golf-step-btn,
  .fs-golf-slot-chip, .fs-golf-noavail-offer, .fs-golf-payment-option,
  .fs-golf-date-pill, .fs-golf-guest-type-chip, .fs-golf-time-chip,
  .fs-golf-toggle-chip { transition: none; }
}

/* Slot A - Scene/Modal body rules relocated 2026-05-05 to
   priv/static/assets/css/flow_components.css (canonical body layer). */


/* Fade to black */










/* Live Call Card */










/* Explore Mode Visual Overlay */
.fs-explore-overlay {
  position: absolute;
  inset: 0;
  background: rgba(10, 10, 15, 0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Above the in-modal call HUD (captions z:210, progress z:190) so the explore
     surface fully covers the modal - topbar, body, and footer - until the ✕. */
  z-index: 220;
  padding: 0;
  animation: fs-fade-in 0.3s ease-out forwards;
}

.fs-explore-card {
  width: 100%;
  max-width: 440px;
  /* Cool slate glass, harmonized with --flow-bg (#0a0a0f) and the navy photo
     scrim (rgb 20,30,50) - channel order B>G>R. The old rgba(25,20,20) was a
     WARM near-black (R>G=B) that, under heavy blur + gold accents, read sepia/
     brown and clashed with the otherwise cool El Galeón palette. */
  background: var(--flow-explore-card);
  backdrop-filter: blur(28px) saturate(130%);
  -webkit-backdrop-filter: blur(28px) saturate(130%);
  border: 1px solid var(--flow-surface-glass-08);
  border-radius: 24px;
  padding: 36px 32px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.65), inset 0 1px 0 rgba(255, 255, 255, 0.12);
  text-align: center;
  transform: translateY(12px);
  animation: fs-slide-up 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.fs-explore-badge {
  display: inline-block;
  font-family: var(--flow-font-ui, sans-serif);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--flow-gold);
  background: var(--flow-gold-a08);
  border: 1px solid var(--flow-gold-a20);
  padding: 4px 14px;
  border-radius: 100px;
  margin-bottom: 20px;
}

.fs-explore-title {
  font-family: Georgia, serif;
  font-size: 26px;
  font-weight: 600;
  color: #ffffff;
  margin: 0 0 16px 0;
  letter-spacing: 0.2px;
}

.fs-explore-details {
  font-family: var(--flow-font-ui, sans-serif);
  font-size: 13.5px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.85);
  font-weight: 400;
}

.fs-explore-back {
  margin-top: 24px;
  font-family: var(--flow-font-ui, sans-serif);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--flow-gold);
  background: var(--flow-gold-a08);
  border: 1px solid var(--flow-gold-a28);
  padding: 9px 22px;
  border-radius: 100px;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.fs-explore-back:hover {
  background: var(--flow-gold-a16);
  border-color: var(--flow-gold-a45);
}

/* Primary booking CTA rendered on bookable explore cards (offerings → room_booking;
   dining_venues → dining). Solid gold fill signals "this starts a transaction"
   vs the ghost back button. Placed above .fs-explore-back so actions read
   top-to-bottom: primary CTA → dismiss. */
.fs-explore-cta {
  display: block;
  width: 100%;
  /* margin-top:auto pins the Book button to the bottom of the body (consistent
     footer position across cards); content above stays top-aligned. */
  margin-top: auto;
  margin-bottom: 0;
  font-family: var(--flow-font-ui, sans-serif);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--flow-gold-champagne-ink);
  /* Champagne-gold fill - brighter + a touch lighter than --flow-gold (#d4a853),
     which as a large slab read mustard/brown next to the yellow-gold text accents.
     The vertical gradient gives a soft metallic sheen without going muddy. */
  background: linear-gradient(180deg, var(--flow-gold-champagne-top) 0%, var(--flow-gold-champagne-bot) 100%);
  border: none;
  padding: 11px 24px;
  border-radius: 100px;
  cursor: pointer;
  box-shadow: 0 2px 14px var(--flow-gold-champagne-glow);
  transition: filter var(--flow-dur-sm, 0.15s) var(--flow-ease-out, ease),
              box-shadow var(--flow-dur-sm, 0.15s) var(--flow-ease-out, ease);
}

.fs-explore-cta:hover {
  box-shadow: 0 4px 20px var(--flow-gold-champagne-glow-strong);
  filter: brightness(1.05);
}

/* Explore Mode - rich detail card (§11.2-036/037). Mirrors the dining
   restaurant-detail layout (hero + gallery + body) inside the explore overlay.
   Height-bounded with a scrolling body so it never overflows the widget. */
/* Explore-modal accent = champagne gold, matching the Book CTA so the labels,
   badge, and gallery active-ring read as one bright gold (not the darker, more
   brown #d4a853). Scoped to the explore surfaces - the global --flow-gold used
   by every other scene/tenant is intentionally left at #d4a853. */
/* Re-point the gold accent to champagne for the explore surfaces, INCLUDING the
   precomputed alpha stops - otherwise `var(--flow-gold-aXX)` references (badge
   tint, etc.) would keep resolving to the old gold and clash with the champagne
   solids. Scoped here so the global tokens stay put. */
.fs-explore-detail, .fs-explore-card {
  --flow-gold: var(--flow-gold-champagne);
  --flow-gold-a08: var(--flow-gold-champagne-a08);
  --flow-gold-a16: var(--flow-gold-champagne-a16);
  --flow-gold-a28: var(--flow-gold-champagne-a28);
  --flow-gold-a34: var(--flow-gold-champagne-a34);
  --flow-gold-a45: var(--flow-gold-champagne-a45);
}
.fs-explore-detail{width:100%;height:100%;max-width:none;max-height:none;display:flex;flex-direction:row;background:var(--flow-explore-surface);backdrop-filter:blur(30px) saturate(125%);-webkit-backdrop-filter:blur(30px) saturate(125%);overflow:hidden;animation:fs-slide-up 0.42s cubic-bezier(0.16,1,0.3,1) both}
.fs-explore-detail-media{flex:0 0 46%;min-width:0;min-height:0;display:flex;flex-direction:column;background:#0a0a0f;border-right:1px solid rgba(255,255,255,0.06)}
.fs-explore-detail-hero{position:relative;flex:1 1 auto;min-height:0;overflow:hidden}
.fs-explore-detail-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;will-change:transform;animation:fsKB1 14s ease-in-out infinite alternate;transition:transform .8s ease-in-out}
.fs-explore-detail-hero-gradient{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 38%,rgba(0,0,0,.78) 100%);pointer-events:none}
/* The explore page's single close ✕ - a direct child of .fs-explore-overlay
   (the positioned, full-cover container), so it anchors to the OVERLAY's true
   top-right corner and floats above whichever card (rich or fallback) is shown.
   Fixed 16px corner inset (not --flowstay-chrome-inset-right): when embedded, the
   loader hides its own host close ✕ while explore is open, so this ✕ takes the
   corner outright instead of insetting to dodge it. */
.fs-explore-overlay-close{position:absolute;top:16px;right:16px;z-index:5;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:100px;background:rgba(10,10,15,0.5);border:1px solid rgba(255,255,255,0.18);color:#fff;font-size:15px;line-height:1;cursor:pointer;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);transition:background .18s ease,border-color .18s ease}
.fs-explore-overlay-close:hover{background:rgba(10,10,15,0.74);border-color:rgba(255,255,255,0.3)}
.fs-explore-overlay-close:focus-visible{outline:2px solid var(--flow-gold);outline-offset:2px}
.fs-explore-detail-hero-overlay{position:absolute;left:clamp(20px,2.4vw,32px);right:clamp(20px,2.4vw,32px);bottom:clamp(18px,2vw,28px);z-index:2;display:flex;flex-direction:column;gap:8px}
.fs-explore-detail-badge{align-self:flex-start;font-family:var(--flow-font-ui,sans-serif);font-size:9.5px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;color:#e7d3ad;background:var(--flow-gold-a16);border:1px solid var(--flow-gold-a34);padding:4px 13px;border-radius:100px;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
.fs-explore-detail-name{font-family:'Cormorant Garamond',Georgia,serif;font-size:clamp(30px,3.1vw,42px);font-weight:600;color:#fff;line-height:1.06;letter-spacing:.2px;text-shadow:0 2px 16px rgba(0,0,0,.7)}
.fs-explore-detail-tagline{font-family:var(--flow-font-ui,sans-serif);font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.78);text-shadow:0 1px 8px rgba(0,0,0,.6)}
/* ── Explore hero carousel (e.g. dining) ──────────────────────────────────
   Each .fs-explore-hero-slide couples a photo + its venue name and cross-fades
   as ONE unit (opacity), so the name can never drift onto the wrong photo.
   Pure CSS: slide i is delayed by i×slide. A keyframe can't read --n for its
   percentages, so the opaque window is baked per slide-count and selected via
   [data-n]: fade4 (default, 4 slides) and fade6 (amenities, 6 slides). Badge +
   page title ride .fs-explore-hero-static ABOVE the slides so they stay put
   instead of flickering at each hand-off. */
/* Shared Ken Burns Viewport Animation */
.fs-kenburns-viewport {
  animation: fs-kenburns-zoom 16s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes fs-kenburns-zoom {
  0% { transform: scale(1.0); }
  100% { transform: scale(1.12); }
}
@media (prefers-reduced-motion: reduce) {
  .fs-kenburns-viewport {
    animation: none !important;
  }
}

.fs-explore-hero--carousel{position:relative}
.fs-explore-hero-viewport {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.fs-explore-hero-slide{position:absolute;inset:0;opacity:0;animation:fs-explore-carousel-fade4 calc(var(--n,4) * 6s) ease-in-out infinite;animation-delay:calc(var(--i,0) * 6s)}
.fs-explore-hero-slide-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.fs-explore-hero-slide-grad{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 34%,rgba(0,0,0,.84) 100%);pointer-events:none}
.fs-explore-hero-slide-name{position:absolute;left:clamp(20px,2.4vw,32px);right:clamp(20px,2.4vw,32px);bottom:clamp(18px,2vw,28px);z-index:2;font-family:var(--flow-font-ui,sans-serif);font-size:13px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--flow-gold-champagne);text-shadow:0 1px 10px rgba(0,0,0,.75)}
.fs-explore-hero-static{position:absolute;left:clamp(20px,2.4vw,32px);right:clamp(20px,2.4vw,32px);bottom:clamp(50px,5.2vw,66px);z-index:3;display:flex;flex-direction:column;gap:8px;pointer-events:none}
/* n=4 cross-fade: each slide owns a 25% slot, visible ~4–25% with a ~5% fade
   overlap into the next slide so there is no black gap at the hand-off. */
@keyframes fs-explore-carousel-fade4{
  0%   {opacity:0}
  4%   {opacity:1}
  25%  {opacity:1}
  30%  {opacity:0}
  100% {opacity:0}
}
/* n=6 cross-fade (amenities): each slide owns a ~16.7% slot, visible ~3–17%
   with a ~3% fade overlap into the next slide. Same 4.2s-per-slide cadence as
   n=4 - the cycle is calc(var(--n) * 4.2s), only this opaque window differs. */
.fs-explore-hero--carousel[data-n="6"] .fs-explore-hero-slide{animation-name:fs-explore-carousel-fade6}
@keyframes fs-explore-carousel-fade6{
  0%   {opacity:0}
  3%   {opacity:1}
  17%  {opacity:1}
  20%  {opacity:0}
  100% {opacity:0}
}
@media (prefers-reduced-motion: reduce){
  .fs-explore-hero-slide{animation:none}
  .fs-explore-hero-slide:first-child{opacity:1}
}
.fs-explore-detail-gallery{display:flex;gap:10px;padding:14px 18px 18px;overflow-x:auto;flex:0 0 auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.fs-explore-detail-gallery::-webkit-scrollbar{display:none}
.fs-explore-detail-gallery-thumb{appearance:none;-webkit-appearance:none;background:none;padding:0;margin:0;flex:0 0 auto;width:clamp(76px,7vw,98px);height:clamp(52px,4.6vw,66px);border-radius:8px;overflow:hidden;border:1px solid rgba(255,255,255,0.14);cursor:pointer;transition:opacity .15s ease,transform .15s ease,border-color .15s ease,outline-color .15s ease;outline:2px solid transparent;outline-offset:0}
.fs-explore-detail-gallery-thumb:hover{opacity:.9;transform:translateY(-1px)}
.fs-explore-detail-gallery-thumb.is-active{border-color:var(--flow-gold);outline:2px solid var(--flow-gold)}
.fs-explore-detail-gallery-thumb:focus-visible{outline:2px solid var(--flow-gold)}
.fs-explore-detail-gallery-img{width:100%;height:100%;object-fit:cover;display:block}
.fs-explore-detail-body{flex:1 1 0;min-width:0;min-height:0;overflow-y:auto;overscroll-behavior:contain;display:flex;flex-direction:column;justify-content:flex-start;gap:clamp(10px,1.4vw,15px);padding:clamp(18px,2.4vw,28px) clamp(22px,2.6vw,34px);scrollbar-width:thin;scrollbar-color:rgba(255,255,255,0.2) transparent}
.fs-explore-detail-body::-webkit-scrollbar{width:8px}
.fs-explore-detail-body::-webkit-scrollbar-track{background:transparent}
.fs-explore-detail-body::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.16);border-radius:100px;border:2px solid transparent;background-clip:padding-box}
.fs-explore-detail-body::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,0.3);background-clip:padding-box}
.fs-explore-detail-blurb{font-family:var(--flow-font-ui,sans-serif);font-size:13px;line-height:1.5;color:rgba(255,255,255,0.82);font-weight:400;margin:0;max-width:64ch}
.fs-explore-detail-facts{display:flex;flex-direction:column;gap:9px;padding-top:clamp(10px,1.2vw,14px);border-top:1px solid rgba(255,255,255,0.1)}
.fs-explore-detail-fact{display:flex;gap:16px;align-items:baseline}
.fs-explore-detail-fact-label{flex:0 0 clamp(84px,8vw,104px);font-family:var(--flow-font-ui,sans-serif);font-size:10px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:var(--flow-gold);padding-top:2px}
.fs-explore-detail-fact-value{flex:1 1 0;font-family:var(--flow-font-ui,sans-serif);font-size:13.5px;line-height:1.55;color:rgba(255,255,255,0.88)}
.fs-explore-detail-highlights{display:flex;flex-direction:column;gap:4px;padding-top:clamp(10px,1.2vw,14px);border-top:1px solid rgba(255,255,255,0.1)}
.fs-explore-detail-highlights-title{font-family:var(--flow-font-ui,sans-serif);font-size:10px;font-weight:700;color:var(--flow-gold);margin:0 0 6px;text-transform:uppercase;letter-spacing:0.14em}
.fs-explore-detail-highlights-items{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;row-gap:2px}
.fs-explore-detail-highlight{display:flex;gap:12px;align-items:flex-start;padding:8px 0;border-bottom:none}
.fs-explore-detail-highlight-thumb{width:52px;height:52px;object-fit:cover;border-radius:10px;flex:0 0 auto}
.fs-explore-detail-highlight-text{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:2px}
.fs-explore-detail-highlight-name{font-family:'Cormorant Garamond',Georgia,serif;font-size:16.5px;font-weight:600;color:#fff;line-height:1.16;letter-spacing:.2px}
.fs-explore-detail-highlight-desc{font-family:var(--flow-font-ui,sans-serif);font-size:11.5px;line-height:1.42;color:rgba(255,255,255,0.64);margin:0}
button.fs-explore-detail-highlight--clickable {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  display: flex;
  width: 100%;
  cursor: pointer;
  align-items: center;
  outline: none;
  border: 1px solid transparent;
  border-radius: 12px;
  padding: 12px 10px;
  color: inherit;
  font-family: inherit;
  text-align: left;
  transition: background 0.25s ease, border-color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
button.fs-explore-detail-highlight--clickable:hover,
button.fs-explore-detail-highlight--clickable:focus-visible {
  transform: scale(1.015);
  background: var(--flow-tint-03, rgba(255, 255, 255, 0.03));
  border-color: var(--flow-gold-a40, rgba(201, 169, 110, 0.4));
  box-shadow: 0 4px 20px var(--flow-gold-a15, rgba(201, 169, 110, 0.15));
  outline: none;
}
.fs-explore-detail-highlight-arrow {
  margin-left: auto;
  font-size: 18px;
  color: var(--flow-gold);
  transition: transform 0.25s ease;
}
button.fs-explore-detail-highlight--clickable:hover .fs-explore-detail-highlight-arrow,
button.fs-explore-detail-highlight--clickable:focus-visible .fs-explore-detail-highlight-arrow {
  transform: translateX(4px);
}
.fs-explore-detail-back{align-self:flex-start;margin-top:8px;font-family:var(--flow-font-ui,sans-serif);font-size:12px;font-weight:600;letter-spacing:0.04em;color:var(--flow-gold);background:var(--flow-gold-a08);border:1px solid var(--flow-gold-a28);padding:10px 24px;border-radius:100px;cursor:pointer;transition:background 0.15s ease,border-color 0.15s ease}
.fs-explore-detail-back:hover{background:var(--flow-gold-a16);border-color:var(--flow-gold-a45)}
.fs-explore-detail-back:focus-visible{outline:2px solid var(--flow-gold);outline-offset:2px}
/* Narrow/portrait widget: stack the media pane on top of the body. */
@media (max-width: 720px){
  .fs-explore-detail{flex-direction:column}
  .fs-explore-detail-media{flex:0 0 auto}
  .fs-explore-detail-hero{height:clamp(160px,30vh,240px);flex:0 0 auto}
  .fs-explore-detail-body{padding:18px 22px 24px;gap:14px}
}
@media (prefers-reduced-motion: reduce){
  .fs-explore-detail,.fs-explore-detail-hero-img{animation:none}
  .fs-explore-detail-gallery-thumb,.fs-explore-overlay-close,.fs-explore-detail-back{transition:none}
}
}

@keyframes fs-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes fs-slide-up {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}


/* fs-dev-hud - flowstay dev HUD drawer (ported from flow/) */
/* ──────────────────────────────────────────────────────────────────
   Fixed right-edge sliding dev HUD. Replaces the old inline
   ".fs-dev-panel" Flo DevConsole <style> blocks in widget_live.ex +
   phone_live.ex. Class family ".fs-dev-hud*"; legacy ".fs-dev-*" /
   ".fs-ctx-*" / ".fs-result-*" / "fs-config-form" etc. are kept as
   co-classes so the §5.8 tests' selectors + the rendered text contract
   survive. Dev-only: the component renders this markup only when
   dev_console? is true.
   ────────────────────────────────────────────────────────────────── */

/* Slide-out toggle - pure CSS, connection-independent. A hidden checkbox
   drives the drawer; the DEV pill is its <label>. Closed by default so dev
   mode never alters the host widget's design; opening overlays the drawer. */
.fs-dev-hud-root {
  display: contents;
}

.fs-dev-hud-switch {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  pointer-events: none;
}

.fs-dev-hud-toggle {
  position: fixed;
  /* Bottom-right corner - clears the widget's top-right close (✕) control. */
  bottom: 14px;
  right: 14px;
  z-index: 2147483647;
  display: inline-flex;
  align-items: center;
  padding: 5px 11px;
  background: #1a1a1a;
  border: 1px solid var(--flow-line, rgba(255, 255, 255, 0.18));
  border-radius: 999px;
  color: #d4a853;
  font-family: var(--flow-font-mono, "JetBrains Mono", ui-monospace, monospace);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  user-select: none;
  transition: right 240ms cubic-bezier(0.22, 1, 0.36, 1),
              background 150ms ease, color 150ms ease, border-color 150ms ease;
}

.fs-dev-hud-toggle:hover {
  background: #242424;
  color: #e8c373;
}

/* Open: drawer slides in; the pill rides just left of the drawer edge so it
   stays clickable to close, and flips to the accent fill. */
.fs-dev-hud-switch:checked ~ .fs-dev-hud {
  transform: translateX(0);
}

.fs-dev-hud-switch:checked ~ .fs-dev-hud-toggle {
  right: calc(var(--fs-dev-hud-width, 360px) + 12px);
  background: #d4a853;
  border-color: #d4a853;
  color: #1a1a1a;
}

/* Widget surface: pill rides top-right, just left of the embed loader's
   host-rendered close (✕) control, on the same baseline as the brand mark.
   Anchored to --flowstay-chrome-inset-right (the same band the ✕ reserves;
   56px embedded, 22px standalone) so it adapts to both contexts.
   The open-state rule above (higher specificity) still overrides `right`
   to slide the pill to the drawer edge; `top` here keeps it pinned up top. */
.fs-dev-hud-root--top .fs-dev-hud-toggle {
  top: 16px;
  bottom: auto;
  right: var(--flowstay-chrome-inset-right, 56px);
}

/* In the widget dev view, the DEV pill claims the top-right corner where the
   stage label sat. Hide the now-redundant label (the dev HUD's Session Context
   already shows the current Scene) so the pill never overlaps it. Scoped to
   .fs-widget-dev-wrapper → only when dev_console? is on; production keeps the
   label. */
.fs-widget-dev-wrapper .fs-stage-label {
  display: none;
}

.fs-dev-hud {
  position:        fixed;
  top:             0;
  right:           0;
  bottom:          0;
  width:           var(--fs-dev-hud-width, 360px);
  display:         flex;
  flex-direction:  column;
  gap:             var(--flow-space-3);
  padding:         var(--flow-space-4);
  background:      var(--flow-bg-elevated);
  color:           var(--flow-ink);
  border-left:     1px solid var(--flow-gold-a30);
  box-shadow:      -8px 0 32px rgba(0, 0, 0, 0.5);
  font-family:     var(--flow-font-mono);
  font-size:       11px;
  line-height:     1.45;
  z-index:         var(--flow-z-status);
  user-select:     text;
  overflow-y:      auto;
  /* Hidden off the right edge by default; the toggle reveals it. The drawer
     OVERLAYS the host surface (it never reflows the widget). */
  transform:       translateX(100%);
  transition:      transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change:     transform;
}

/* Docked / chromeless mode (the host-side DevPanelLive iframe). The panel lives
   in its OWN iframe beside the demo modal, so it must fill that iframe rather
   than slide off a viewport edge: drop the fixed positioning + slide transform
   and let it flow full-bleed. The host page owns show/hide of the iframe, so the
   self-toggle pill is not rendered here. */
.fs-dev-hud-root--docked .fs-dev-hud {
  position:    static;
  width:       100%;
  /* Pin to the iframe viewport height (NOT min-height): the base rule scrolls
     via `overflow-y: auto`, which only engages when height is CONSTRAINED. With
     min-height the panel would grow to content height, overflow-y would no-op,
     and widget_root's `body { overflow: hidden }` would clip a busy demo's
     tool-call/memory rows with no scrollbar. height:100vh keeps it scrollable. */
  height:      100vh;
  transform:   none;
  border-left: none;
  box-shadow:  none;
}

.fs-dev-hud::-webkit-scrollbar { width: 6px; }
.fs-dev-hud::-webkit-scrollbar-track { background: transparent; }
.fs-dev-hud::-webkit-scrollbar-thumb {
  background:      var(--flow-line);
  border-radius:   3px;
}

/* Header */
.fs-dev-hud__header {
  display:         flex;
  justify-content: space-between;
  align-items:     center;
  padding-bottom:  var(--flow-space-3);
  border-bottom:   1px solid var(--flow-line);
  user-select:     none;
}
.fs-dev-hud__title {
  margin:          0;
  font-family:     var(--flow-font-ui);
  font-size:       14px;
  font-weight:     600;
  letter-spacing:  0.04em;
  color:           var(--flow-accent);
}
.fs-dev-hud__badge {
  font-family:     var(--flow-font-ui);
  font-size:       9px;
  font-weight:     600;
  text-transform:  uppercase;
  letter-spacing:  0.12em;
  color:           var(--flow-accent);
  background:      var(--flow-accent-soft);
  border:          1px solid var(--flow-gold-a30);
  padding:         3px 8px;
  border-radius:   var(--flow-r-pill);
}

/* Sections - divider-led, mono caps title (the "collapsible" look) */
.fs-dev-hud__section {
  border-top:      1px solid var(--flow-line);
  padding-top:     var(--flow-space-3);
}
.fs-dev-hud__section-title {
  margin:          0 0 var(--flow-space-2) 0;
  font-family:     var(--flow-font-ui);
  font-size:       10px;
  font-weight:     700;
  text-transform:  uppercase;
  letter-spacing:  0.1em;
  color:           var(--flow-ink-65);
}
.fs-dev-hud__section-header {
  display:         flex;
  justify-content: space-between;
  align-items:     center;
  margin-bottom:   var(--flow-space-2);
}

/* Session-context grid */
.fs-dev-hud__grid {
  display:         flex;
  flex-direction:  column;
  gap:             var(--flow-space-2);
}
.fs-dev-hud__row {
  display:         flex;
  justify-content: space-between;
  align-items:     flex-start;
  gap:             var(--flow-space-2);
  line-height:     1.4;
}
.fs-dev-hud__label {
  color:           var(--flow-ink-65);
  font-weight:     500;
  min-width:       96px;
}
.fs-dev-hud__val {
  color:           var(--flow-ink);
  text-align:      right;
  word-break:      break-word;
  font-family:     var(--flow-font-mono);
}
.fs-ctx-val-highlight {
  color:           var(--flow-accent);
  font-weight:     600;
  background:      var(--flow-accent-soft);
  border:          1px solid var(--flow-gold-a25);
  padding:         1px 6px;
  border-radius:   var(--flow-r-xs);
}
.fs-cart-val {
  display:         flex;
  flex-direction:  column;
  gap:             var(--flow-space-1);
  text-align:      right;
}

/* Count chip */
.fs-dev-hud__count {
  font-family:     var(--flow-font-mono);
  font-size:       10px;
  font-weight:     600;
  background:      var(--flow-surface-glass-06);
  border:          1px solid var(--flow-line);
  padding:         1px 6px;
  border-radius:   var(--flow-r-xs);
  color:           var(--flow-ink-65);
}

/* Timeline (tool calls + memory rows) */
.fs-dev-logs-section {
  display:         flex;
  flex-direction:  column;
}
.fs-dev-hud__timeline {
  display:         flex;
  flex-direction:  column;
  gap:             var(--flow-space-2);
  max-height:      320px;
  overflow-y:      auto;
}
.fs-dev-hud__empty {
  color:           var(--flow-ink-3);
  font-style:      italic;
  padding:         var(--flow-space-3) 0;
}
.fs-dev-hud__item {
  background:      var(--flow-surface-glass-06);
  border:          1px solid var(--flow-line);
  border-radius:   var(--flow-r-card);
  border-left:     3px solid var(--flow-accent);
  padding:         var(--flow-space-2) var(--flow-space-3);
  display:         flex;
  flex-direction:  column;
  gap:             var(--flow-space-1);
}
.fs-tool-log  { border-left-color: var(--flow-accent); }
.fs-memory-log { border-left-color: var(--flow-warning); }
.fs-dev-hud__item-meta {
  display:         flex;
  justify-content: space-between;
  font-weight:     600;
}
.fs-dev-hud__item-type { color: var(--flow-ink); }
.fs-dev-hud__item-time {
  color:           var(--flow-ink-3);
  font-variant-numeric: tabular-nums;
}
.fs-dev-hud__item-args {
  font-family:     var(--flow-font-mono);
  font-size:       10px;
  color:           var(--flow-ink-65);
  word-break:      break-all;
}
.fs-dev-hud__item-result { font-size: 11px; }
.fs-dev-hud__item-body {
  color:           var(--flow-ink-2);
  font-size:       11px;
  line-height:     1.5;
}

/* Honest result colors - failure NEVER green */
.fs-result-ok      { color: var(--flow-success); font-weight: 600; }
.fs-result-error   { color: var(--flow-danger);  font-weight: 600; }
.fs-result-unknown { color: var(--flow-ink-3); }

/* Footer */
.fs-dev-hud__footer {
  margin-top:      auto;
  display:         flex;
  justify-content: flex-end;
  padding-top:     var(--flow-space-3);
  border-top:      1px solid var(--flow-line);
}
.fs-dev-hud__btn {
  font-family:     var(--flow-font-ui);
  background:      var(--flow-surface-glass-06);
  border:          1px solid var(--flow-line-2);
  color:           var(--flow-ink-65);
  font-weight:     600;
  padding:         6px 14px;
  font-size:       11px;
  border-radius:   var(--flow-r-xs);
  cursor:          pointer;
  transition:      background 150ms ease-out, color 150ms ease-out;
}
.fs-dev-hud__btn:hover {
  background:      var(--flow-surface-glass-10);
  color:           var(--flow-ink);
}

/* Feature-flag ON/OFF toggle (dev panel leading section). OFF inherits the
   neutral fs-dev-hud__btn look; ON tints success-green like fs-result-ok. */
.fs-dev-flag-toggle { padding: 3px 10px; min-width: 44px; text-align: center; letter-spacing: .06em; }
.fs-dev-flag-toggle.on {
  color:           var(--flow-success);
  border-color:    var(--flow-success);
  background:      color-mix(in srgb, var(--flow-success) 12%, transparent);
}

/* ── Leading-slot sections (phone-only: Identity Config + Sim Harness) ── */
.fs-config-form {
  display:         flex;
  flex-direction:  column;
  gap:             var(--flow-space-3);
}
.fs-form-group {
  display:         flex;
  flex-direction:  column;
  gap:             var(--flow-space-1);
}
.fs-form-group label {
  font-family:     var(--flow-font-ui);
  font-size:       10px;
  font-weight:     600;
  text-transform:  uppercase;
  letter-spacing:  0.05em;
  color:           var(--flow-ink-3);
}
.fs-dev-input {
  background:      var(--flow-bg-chip-dark);
  border:          1px solid var(--flow-line);
  border-radius:   var(--flow-r-xs);
  padding:         8px 12px;
  color:           var(--flow-ink);
  font-size:       12px;
  font-family:     var(--flow-font-mono);
  transition:      border-color 150ms ease-out, box-shadow 150ms ease-out;
}
.fs-dev-input:focus {
  outline:         none;
  border-color:    var(--flow-accent);
  box-shadow:      0 0 0 1px var(--flow-gold-a30);
}
.fs-dev-input:disabled { opacity: 0.5; cursor: not-allowed; }

.fs-harness-actions {
  display:         flex;
  flex-direction:  column;
  gap:             var(--flow-space-2);
  font-size:       12px;
}
.fs-harness-row {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
}
.fs-harness-label {
  color:           var(--flow-ink-65);
  font-weight:     500;
  min-width:       80px;
}
.fs-harness-btn-group { display: flex; gap: 6px; }
.fs-harness-btn {
  background:      var(--flow-surface-glass-08);
  border:          1px solid var(--flow-line-2);
  border-radius:   var(--flow-r-xs);
  color:           var(--flow-ink);
  padding:         4px 8px;
  cursor:          pointer;
  font-size:       11px;
  font-weight:     500;
  transition:      background 150ms ease-out, opacity 150ms ease-out;
}
.fs-harness-btn:hover:not(:disabled) { background: var(--flow-surface-glass-14); }
.fs-harness-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.fs-btn-danger {
  color:           var(--flow-danger);
  border-color:    var(--flow-danger-shadow);
  background:      transparent;
}
.fs-btn-danger:hover:not(:disabled) { background: rgba(255, 59, 48, 0.12); }

/* ─── Premium checkout form input and textarea styling ─── */
.fs-pay-input {
  background: transparent !important;
  border: none !important;
  outline: none !important;
  color: var(--flow-ink-pure, #fff) !important;
  font-family: inherit;
  font-size: clamp(11px, 1.3vw, 13px);
  width: 100%;
  height: 100%;
  padding: 0 !important;
  box-shadow: none !important;
}
.fs-pay-input::placeholder {
  color: rgba(255, 255, 255, 0.22);
}
.fs-pay-textarea {
  resize: none;
  padding: clamp(6px, 1vw, 10px) 0 !important;
  line-height: 1.4;
}
#pf-special-requests.fs-pay-field {
  height: auto;
  min-height: clamp(60px, 8vw, 84px);
  align-items: flex-start;
  padding: clamp(8px, 1.2vw, 12px) clamp(8px, 1.4vw, 14px);
}
#pf-special-requests.fs-pay-field .fs-pay-field-label {
  margin-top: 2px;
}

/* ─── Premium enhancements continue button styling ─── */
.fs-spa-enh-continue {
  align-self: center;
  margin: clamp(10px, 1.8vw, 18px) auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(200px, 35vw, 320px);
  height: clamp(40px, 4.8vw, 48px);
  border-radius: clamp(8px, 1.1vw, 11px);
  background: linear-gradient(135deg, var(--flow-gold-a25), var(--flow-gold-a15));
  border: 1px solid var(--flow-gold-a40);
  font-family: var(--flow-font-ui);
  font-size: clamp(13px, 1.5vw, 15px);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--flow-gold);
  cursor: pointer;
  transition: opacity .15s ease, transform .1s ease;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.fs-spa-enh-continue:hover {
  opacity: .85;
}
.fs-spa-enh-continue:active {
  transform: scale(.99);
}

/* ════════════════════════════════════════════════════════════════════════
   MOBILE / NARROW-WIDTH REFLOW  (2026-06-02)
   ────────────────────────────────────────────────────────────────────────
   Multi-column "desktop" scenes weren't collapsing on a narrow widget →
   cramping / title-truncation / in-container clipping (a clipped booking
   price is a blocker). Strategy = ADDITIVE overrides at the canonical 720px
   widget breakpoint (already used at L1049 / L1494 / L2508 / L4779). Every
   base rule is left UNCHANGED, so widths > 720px (including the un-baselined
   desktop) stay byte-for-byte identical = zero regression by construction.
   In production the widget renders inside an iframe, so @media here resolves
   against the iframe's own width (the widget's true box) - correct on phone,
   iPad, and host pages. A later phase may migrate these to @container on
   .fs-modal once the stacking-context check passes.

   Decision doc: docs/discussions/2026-06-02-mobile-reflow-fix-strategy.html
   Tile/chip grids (home-grid, submenu, spa-slot-picker) reflow fine at 2-col
   and are intentionally NOT touched (baseline-verified, 2026-06-02).
   ════════════════════════════════════════════════════════════════════════ */
@media (max-width: 720px) {
  /* BLOCKER - marina-slip-selection clipped "$280.00/night". Slip cards render
     in .fs-spa-menu-grid (base `1fr 1fr`); a horizontal card needs the full
     row to fit "duration + $XXX.00/night". Single column gives it that. Shared
     by weddings-packages + meetings-spaces (same horizontal-card geometry →
     same desirable collapse). */
  .fs-spa-menu-grid { grid-template-columns: 1fr; }

  /* enhance - 3-up room add-ons crammed to ~110px; .fs-enh-name/-desc are
     nowrap + ellipsis so titles truncated. Two columns AND let the title wrap
     so full names show. */
  .fs-enh-grid { grid-template-columns: repeat(2, 1fr); }
  .fs-enh-name, .fs-enh-desc { white-space: normal; overflow: visible; text-overflow: clip; }

  /* spa-enhancement - same 3-up cram, but .fs-spa-enh-name already wraps, so
     two columns alone suffice (no nowrap to undo). */
  .fs-spa-enh-grid { grid-template-columns: repeat(2, 1fr); }

  /* spa-service-selection - master-detail split starved the right treatment
     list to ~70px (treatment names invisible). Stack the stage above the
     full-width list. .fs-spa-stage is all absolutely-positioned children, so
     an `auto` row would collapse it to 0 - give it an explicit height
     (mirrors the .fs-explore-detail-hero stacked-hero precedent, L4779). */
  .fs-spa-menu.fs-spa-split { grid-template-columns: 1fr; grid-template-rows: auto 1fr; overflow-y: auto; }
  .fs-spa-menu.fs-spa-split .fs-spa-stage { height: clamp(160px, 30vh, 240px); }

  /* payment - 2-col (summary | card form) crammed fields to ~150px. Stack
     full-width and let the taller stacked content scroll inside the fixed
     frame (base .fs-pay-wrap is overflow:hidden + align-items:center). */
  .fs-pay-wrap { flex-direction: column; align-items: stretch; justify-content: flex-start; overflow-y: auto; }
  .fs-pay-wrap > .fs-pay-left, .fs-pay-wrap > .fs-pay-right { max-height: none; overflow: visible; }

  /* room-detail - hero | body flex row → stacked column. */
  .fs-room-detail-content { flex-direction: column; overflow-y: auto; }

  /* review / cart (room-booking :enhancements → :cart → :checkout step,
     scenes.ex def review) - .fs-review-content is the SAME hero | body flex
     row as .fs-room-detail-content (identical declaration), so it has the same
     phone cram; same collapse. (Not a storyboard state, so validated by parity
     with room-detail, not its own capture.) */
  .fs-review-content { flex-direction: column; overflow-y: auto; }

  /* room-select - .fs-split hero(60%) | alternates(40%) truncated the card
     names. Stack: hero on top (fixed aspect so it doesn't eat the column),
     full-width alternates below with the desktop 44px side padding relaxed. */
  .fs-split { flex-direction: column; }
  .fs-split .fs-hero-wrap { flex: 0 0 auto; aspect-ratio: 16 / 9; margin: clamp(7px, 2vw, 12px); }
  .fs-split .fs-cards-col { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 clamp(10px, 4vw, 16px) clamp(6px, 1vw, 10px); }

  /* marina context_gathering ONLY: it has more facts content (vessel-length +
     nights chip rows) than the room/spa greeting, so it needs the full panel
     width - and its background is a SEE-THROUGH gradient scrim, so going
     full-width keeps the photo visible behind it. Kill the right-edge mask
     feather (else the full-width text half-fades) and re-anchor the caption
     (its calc(50% + …) offset would push it off-canvas at full width).
     NOTE: do NOT apply this to room/spa context - their facts panel is an
     OPAQUE dark background, so width:100% there hid the hero photo entirely
     (vision-review regression). Their 50%-panel + photo layout reads fine on
     a phone (short one-line greeting), so it is intentionally left untouched. */
  .fs-flow-gathering.fs-marina-gathering:not(.fs-searching-with-context) .fs-flow-gathering-facts {
    width: 100%;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .fs-flow-gathering.fs-marina-gathering:not(.fs-searching-with-context) .fs-flow-gathering-caption {
    left: clamp(12px, 4vw, 20px);
  }

  /* progress rail - FLO-153's 7-step room-booking rail packs seven labels
     into flex:1 columns; below ~400px each column is only ~40px, so the
     uppercase nowrap labels ("Select rate", "Payment") overflowed into their
     neighbors. Shrink the type only as the iframe narrows (11px holds to
     ~460px, then eases to 8px) and let multi-word labels wrap so all seven
     fit. Width-adaptive: wider rails (the 5-step storyboard, tablets) are
     visually unchanged because the clamp stays at 11px and one-line labels
     never wrap. */
  .fs-prog-step span {
    font-size: clamp(8px, 2.4vw, 11px);
    letter-spacing: .03em;
    white-space: normal;
    line-height: 1.2;
    text-align: center;
  }

  /* comparison cards - side-by-side grid crams 2-3 cards at narrow widths;
     force a single column so each card uses the full width and prices/facts
     remain readable. minmax(0, 1fr) prevents a grid track from refusing to
     shrink below card content. */
  .fs-comparison-grid { grid-template-columns: minmax(0, 1fr); }
  .fs-comparison-card { min-width: 0; }
  .fs-comparison-chip { white-space: normal; }
}

