/* 5680 Pass 19: the City section upgrade (markup from 5680-internal/tools/city-html.py, motion in js/city.js) and the
   distances table's group labels. New photos: the river (parallax), the lagoon's second beat, the preserve
   photo plate, the boardwalks rail, the pinned city sequence and the coast rail. Motion is transform/opacity only
   (the credits drawer animates grid-template-rows). Scroll-linked motion uses animation-timeline inside @supports with
   an rAF/IO fallback in js. Reduced motion: no timelines, final frames, 150ms opacity fades. */
.cy{--cy-in:cubic-bezier(.25,1,.5,1);--cy-dr:cubic-bezier(.32,.72,0,1)}

/* 2 distinctions index: each line rises in its mask from .6em, 60ms stagger (--d from js) */
.cy-ix-m{display:block;overflow:clip;padding-bottom:.12em;margin-bottom:-.12em}
.cy-ix-i{display:block}
html.js .cy-ix-i{opacity:0;transform:translate3d(0,.6em,0)}
html.js .cy-ix.in .cy-ix-i{opacity:1;transform:none;transition:opacity 700ms var(--cy-in) var(--d,0s),transform 700ms var(--cy-in) var(--d,0s)}

/* side entrances: the lagoon beat (plate from the right, caption from the left) and the House of Refuge pair (L, R) */
html.js .cy-rv-l{transform:translate3d(-32px,0,0)}
html.js .cy-rv-r{transform:translate3d(32px,0,0)}
html.js .cy-rv-l.in,html.js .cy-rv-r.in{transform:none;transition:opacity 700ms var(--cy-in) var(--d,0s),transform 700ms var(--cy-in) var(--d,0s)}

/* 3 the lagoon's second beat: a half-width plate (C07) */
.cy-beat{margin-top:clamp(40px,7vw,88px)}
.cy-beat-f{margin:0;display:flex;flex-direction:column;align-items:flex-end}
.cy-beat .cy-frame{width:88%;aspect-ratio:4/3;border-radius:3px}
.cy-beat .cy-cap{align-self:stretch;max-width:44ch}
@media (max-width:820px){.cy-beat .cy-cap{padding-right:calc(var(--rail-g,16px) + 16px)}}
@media (min-width:821px){
  .cy-beat-f{display:grid;grid-template-columns:minmax(0,1fr) 50%;column-gap:48px;align-items:end}
  .cy-beat .cy-frame{grid-column:2;grid-row:1;width:auto;aspect-ratio:3/2}
  .cy-beat .cy-cap{grid-column:1;grid-row:1;justify-self:end;max-width:340px;padding:0 0 4px;text-align:right}
}

/* full-bleed photo plates with type over the sky (river, preserve): the scrim is a CSS layer, not a baked edit */
.cy-river,.cy-sav{margin-top:clamp(64px,12vw,140px)}
.cy-bleed>.cy-frame{position:relative;height:var(--cy-h)}
.cy-scrim-t{position:absolute;left:0;right:0;top:0;height:64%;pointer-events:none;
  background:linear-gradient(to bottom,rgba(29,32,33,.8) 0%,rgba(29,32,33,.66) 42%,rgba(29,32,33,0) 100%)}
.cy-over{position:absolute;left:0;right:0;top:0;padding-top:clamp(28px,6vw,72px)}
.cy-over .eyebrow{color:var(--paper)}
@media (max-width:899px){.cy-over{padding-right:calc(var(--rail-g,16px) + 16px)}}

/* 4 St. Lucie River: parallax -6% -> 6% (the photo layer is 14% taller than the frame) */
.cy-river .cy-over .cy-h{font-size:clamp(48px,13vw,112px);line-height:.95}
.cy-px{position:absolute;left:0;right:0;top:-7%;bottom:-7%;will-change:transform}
.cy-px img{position:absolute;inset:0}
@supports (animation-timeline:view()){
  .cy-px{animation:cyPx linear both;animation-timeline:view();animation-range:entry 0% exit 100%}
  @keyframes cyPx{from{transform:translate3d(0,-6%,0)}to{transform:translate3d(0,6%,0)}}
}
html.no-sda .cy-px{transform:translate3d(0,calc(var(--q,.5) * 12% - 6%),0)}
.cy-river .cy-t{padding-top:clamp(20px,3vw,32px)}

/* 5 Preserve: Ken Burns 1 -> 1.06 (cyZoom, site-p14.css), then "0.1 mi" rises over the sky band */
.cy-sav .cy-over-big{margin-top:0;color:var(--paper)}
html.js .cy-sav .cy-over-big.cy-rv{transform:translate3d(0,32px,0)}
html.js .cy-sav .cy-over-big.cy-rv.in{transform:none;transition:opacity 900ms var(--cy-e) 250ms,transform 900ms var(--cy-e) 250ms}
.cy-sav-t{margin-top:clamp(24px,4vw,40px);padding-block:clamp(40px,7vw,88px)}
.cy-sav-t .cy-t{padding-top:0}

/* 8 + 11 rails: native horizontal scroll, mandatory x snap, centred 4:5 cards, no auto-scroll, no scroll-jacking */
.cy-railsc{margin-top:clamp(64px,12vw,140px)}
.cy-rail-h{display:flex;align-items:flex-end;justify-content:space-between;gap:16px}
.cy-rail-h>div{max-width:620px}
.cy-rail{display:flex;gap:12px;overflow-x:auto;overscroll-behavior-x:contain;scroll-snap-type:x mandatory;
  padding:24px 9vw 4px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.cy-rail::-webkit-scrollbar{display:none}
.cy-rail>li{flex:0 0 82vw;max-width:82vw;scroll-snap-align:center}
.cy-rail .cy-card{display:block;width:100%;border-radius:3px;overflow:clip;text-align:left}
.cy-rail .cy-frame{display:block;aspect-ratio:4/5}
.cy-rail .cy-cap{padding-right:4px}
@media (min-width:821px){
  .cy-rail{gap:20px;padding-inline:max(var(--pad),calc((100% - 1280px) / 2 + var(--pad)))}
  .cy-rail>li{flex-basis:360px;max-width:360px}
}
@supports (animation-timeline:view(inline)){
  .cy-rail .cy-card{animation:cyCard linear both;animation-timeline:view(inline);animation-range:cover 0% cover 100%}
  @keyframes cyCard{0%{transform:scale(.94)}50%{transform:scale(1)}100%{transform:scale(.94)}}
}
.cy-dots{display:flex;justify-content:center;gap:10px;margin-top:16px}
.cy-dots li{width:6px;height:6px;border-radius:50%;background:rgba(215,232,188,.3);transition:transform .3s var(--cy-in),background-color .3s}
.cy-dots li.on{background:var(--paper);transform:scale(1.4)}
.cy-rail-ctl{display:none;gap:8px;flex:none}
@media (min-width:821px){.cy-rail-ctl:not([hidden]){display:flex}}
.cy-rail-b:disabled{opacity:.62;cursor:default}

/* 10 "Your city" pinned sequence. Static (no JS, reduced motion): hero, card, inset, the No. 1 line, stacked. */
.cy-stu{margin-top:clamp(64px,12vw,140px)}
.cy-pin:not(.cy-pin-on) .cy-pin-run,.cy-pin:not(.cy-pin-on) .cy-pin-stick{display:contents}
.cy-pin-hero .cy-frame{height:var(--cy-h)}
.cy-pin-card{padding-top:clamp(28px,5vw,48px)}
.cy-pin-big{display:flex;flex-direction:column;margin-top:16px}
.cy-pin-pre{font:500 13px/1.4 var(--sans);color:var(--body)}
.cy-pin-big .cy-big{margin-top:4px}
.cy-pin-inset .cy-frame{aspect-ratio:4/3;border-radius:3px;box-shadow:0 18px 40px rgba(0,0,0,.35)}
.cy-pin:not(.cy-pin-on) .cy-pin-inset{width:62%;margin:28px var(--pad) 0 auto}
.cy-pin:not(.cy-pin-on) .cy-pin-aw .cy-award{margin-top:28px}
.cy-stu .cy-cap2{padding-top:14px}
.cy-stu .cy-t{padding-top:clamp(20px,3vw,32px)}
.cy-stu .cy-detail{padding-top:16px;border-top:1px solid var(--line)}
/* pinned (js adds .cy-pin-on; .p1 card, .p2 inset at ~45%, .p3 the No. 1 line) */
.cy-pin-on .cy-pin-run{position:relative;height:170vh;height:170svh}
.cy-pin-on .cy-pin-stick{position:sticky;top:0;height:100vh;height:100svh;overflow:clip}
.cy-pin-on .cy-pin-hero,.cy-pin-on .cy-pin-hero .cy-frame{position:absolute;inset:0;height:100%}
.cy-pin-on .cy-pin-card{position:absolute;left:0;right:0;top:calc(var(--navh) + 58px);padding-top:0}
.cy-pin-on .cy-card-in{max-width:440px;background:rgba(29,32,33,.94);border-radius:4px;padding:20px 20px 22px}
.cy-pin-on .cy-card-in .cy-h{font-size:clamp(30px,8vw,52px)}
.cy-pin-on .cy-pin-big .cy-big{font-size:clamp(80px,24vw,160px)}
.cy-pin-on .cy-pin-inset{position:absolute;right:max(var(--pad),calc(var(--rail-g,16px) + 16px));bottom:calc(env(safe-area-inset-bottom) + 196px);width:min(56vw,420px);z-index:2}
.cy-pin-on .cy-pin-aw{position:absolute;left:0;right:0;bottom:calc(env(safe-area-inset-bottom) + 84px)}
.cy-pin-on .cy-pin-aw .cy-award{max-width:440px;margin:0;padding:14px 18px;background:rgba(29,32,33,.94);border-radius:4px;font-size:clamp(18px,4.6vw,24px)}
@media (max-width:899px){.cy-pin-on .cy-pin-card,.cy-pin-on .cy-pin-aw{padding-right:calc(var(--rail-g,16px) + 16px)}}
@media (min-width:821px){
  .cy-pin-on .cy-pin-stick{top:calc(var(--navh) + 46px);height:calc(100vh - var(--navh) - 46px)}
  .cy-pin-on .cy-pin-run{height:calc(100vh - var(--navh) - 46px + 70vh)}
  .cy-pin-on .cy-pin-card{top:auto;bottom:112px}
  .cy-pin-on .cy-pin-inset{top:56px;bottom:auto;right:max(var(--pad),calc((100% - 1280px) / 2 + var(--pad)))}
  .cy-pin-on .cy-pin-aw{left:auto;width:420px;bottom:112px;right:max(var(--pad),calc((100% - 1280px) / 2 + var(--pad)));padding:0}
}
html.js .cy-pin-on .cy-card-in,html.js .cy-pin-on .cy-pin-aw .cy-award{opacity:0;transform:translate3d(0,40px,0);transition:opacity 700ms var(--cy-in),transform 700ms var(--cy-in)}
html.js .cy-pin-on .cy-pin-inset{opacity:0;transform:translate3d(0,20%,0);transition:opacity 700ms var(--cy-in),transform 700ms var(--cy-in)}
html.js .cy-pin-on.p1 .cy-card-in,html.js .cy-pin-on.p2 .cy-pin-inset,html.js .cy-pin-on.p3 .cy-pin-aw .cy-award{opacity:1;transform:none}

/* Pass 20b. Lagoon card: solid (the city card treatment, no translucency over the sky) and brought in by the pan's own
   progress: transform + opacity finish by 0.18, so every captured frame from 0.2 shows it at full strength (no 520ms
   class transition to be caught half-way). The Pass 15 fade-out (.85 -> 1, on .cy-card-t) still applies on top. */
html.js .cy-pan-on .cy-card-in,html.js .cy-pan-on.t-in .cy-card-in{background:rgb(29,32,33);
  opacity:clamp(0,calc(var(--p,0) / .18),1);transform:translate3d(0,calc((1 - clamp(0,calc(var(--p,0) / .18),1)) * 24px),0);transition:none}
/* City pin on a phone: the card fades out (and lifts a little) over pin progress .8 -> .85 (--pp from js; short, so no
   frame lingers half-transparent over the photo), so it is gone before the pinned frame unsticks and scrolls up under the nav. The inset and the No. 1 line stay with the photo. */
@media (max-width:820px){
  .cy-pin-on .cy-pin-card{opacity:clamp(0,calc((.85 - var(--pp,0)) / .05),1);transform:translate3d(0,calc(clamp(0,calc((var(--pp,0) - .8) / .05),1) * -16px),0)}
}
/* Desktop: the pinned frames (lagoon pan, city pin) start at the top of the viewport, under the fixed nav and the
   translucent tab bar, like the phone, so there is no strip of page between the bar and the photo whether the nav is
   shown or hidden (the bar slides up 56px when the nav hides on scroll). Cards and the inset keep their old places. */
@media (min-width:821px){
  .cy-pan-on .cy-stick,.cy-pin-on .cy-pin-stick{top:0;height:100vh;height:100svh}
  .cy-pan-on .cy-run{height:160vh;height:160svh}
  .cy-pin-on .cy-pin-run{height:170vh;height:170svh}
  /* the C02 inset: an 8px charcoal frame and a soft shadow so it never melts into C01's sky */
  .cy-pin-on .cy-pin-inset{top:calc(var(--navh) + 46px + 56px)}
  .cy-pin-on .cy-pin-inset .cy-frame{border:8px solid #2c2f32;border-radius:4px;box-shadow:0 24px 56px rgba(0,0,0,.5),0 4px 12px rgba(0,0,0,.3)}
}

/* 13 photo credits: a closed drawer that opens by grid-template-rows 0fr -> 1fr (js toggles .op around [open]) */
.cy-cred summary{transition:color .2s}
.cy-cred-b{display:grid;grid-template-rows:1fr}
.cy-cred-b>div{min-height:0;overflow:hidden}
html.js .cy-cred-b{grid-template-rows:0fr;transition:grid-template-rows 450ms var(--cy-dr)}
html.js .cy-cred.op .cy-cred-b{grid-template-rows:1fr}

/* 12 distances (Neighborhood tab): big serif group labels, sentence case, a 24x2 acid tick, the row count in Inter.
   The words are sage, not acid. On a phone the label sticks under the tab bar while its rows scroll by (the sticky box
   is the group's row, inside its own tbody; its top padding slides under the translucent tab bar). */
.dist-g th{padding:72px 0 12px;border-top:0;font:400 clamp(56px,5vw,72px)/1 var(--serif);letter-spacing:-.01em;text-transform:none;color:#d7e8bc}
.dist-gl{display:flex;align-items:baseline;flex-wrap:wrap;gap:6px 14px}
.dist-gl::before{content:"";flex:0 0 24px;height:2px;background:var(--acid);align-self:center}
.dist-gm{display:block;overflow:clip;padding-bottom:.1em;margin-bottom:-.1em}
.dist-gw{display:block}
.dist-gc{font:400 11px/1.4 var(--sans);letter-spacing:.02em;color:rgba(215,232,188,.6);font-variant-numeric:tabular-nums}
@media (max-width:560px){
  .dist-g th{font-size:clamp(40px,11vw,48px);padding:48px 0 12px}
  .dist-t tr.dist-g{position:sticky;z-index:2;top:calc(var(--navh) + 46px - 40px);padding:0;background:var(--bg);transition:top .5s var(--ease)}
  html.hdr-hide .dist-t tr.dist-g{top:6px}
}
html.js .dist-t .dist-gw{transform:translate3d(0,105%,0)}
html.js .dist-t tbody.in .dist-gw{transform:none;transition:transform 700ms cubic-bezier(.25,1,.5,1)}
html.js .dist-t tr:not(.dist-g){opacity:0;transform:translate3d(0,8px,0)}
html.js .dist-t tbody.in tr:not(.dist-g){opacity:1;transform:none;transition:opacity 520ms cubic-bezier(.25,1,.5,1) var(--d,0s),transform 520ms cubic-bezier(.25,1,.5,1) var(--d,0s)}

@media (prefers-reduced-motion:reduce){
  html.js .cy-ix-i,html.js .cy-rv-l,html.js .cy-rv-r,html.js .cy-sav .cy-over-big.cy-rv,html.js .dist-t .dist-gw,html.js .dist-t tr:not(.dist-g){transform:none!important}
  html.js .cy-ix.in .cy-ix-i,html.js .cy-rv-l.in,html.js .cy-rv-r.in,html.js .cy-sav .cy-over-big.cy-rv.in,html.js .dist-t tbody.in tr:not(.dist-g){transition:opacity 150ms linear!important}
  html.js .dist-t tbody.in .dist-gw{transition:none}
  .cy-px{animation:none!important;transform:none!important;top:0;bottom:0}
  .cy-rail .cy-card{animation:none!important;transform:none!important}
  .cy-dots li{transition:none}
  html.js .cy-cred-b{transition:none}
  .dist-t tr.dist-g{transition:none}
}
/* Pass 20b follow-up: no opacity fade-out on the lagoon card. It stays solid through progress 1 and leaves with the
   photo when the sticky frame unsticks, so every frame from 0.2 to 1 keeps full text contrast. */
html.js .cy-pan-on .cy-card-t{opacity:1}

/* ===== Pass 21 ===== */
/* S1: the City reveals slide in from +/-32px; clip them so the page never scrolls sideways at 390 (clip, not hidden,
   so the sticky lagoon and city pin frames keep working). */
#st-city{overflow-x:clip}
/* DD 3: the Inquire/Call pill never renders as an empty box. The whole pill (background included) fades and slides
   as one; no backdrop-filter, whose layer could paint without the buttons (empty charcoal box at lagoon 0.5). */
.ctabar{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgb(29,32,33);opacity:0;
  transition:transform 350ms var(--e-ui),opacity 250ms linear,visibility 0s linear 350ms}
.ctabar.on{opacity:1;transition:transform 350ms var(--e-ui),opacity 250ms linear}
/* B5: down payment chips + "type your own %" box */
.cf-down .seg{margin-bottom:4px}
.cf-down .cf-or{font-size:14px;color:var(--muted)}
.calc-ask .mt-v,.calc-ask #oPI,.calc-ask #oDown{color:var(--muted)}
.calc-ask .mt-v{font-size:clamp(32px,4.4vw,48px)}
#oDown{white-space:nowrap}

/* Pass 24: gallery captions. Each tile is a figure: the photo button, then a short caption under it (the room
   label stays on the photo). In the masonry the tile's row span already counts the caption (gallery.js spans()),
   so the button takes the remaining height. The lightbox sheet is a figure too, its story line the figcaption. */
.gf{margin:0;display:flex;flex-direction:column;height:100%}
.gcap{margin-top:8px;font:400 13px/1.45 var(--sans);color:var(--body);text-wrap:pretty}
@media (min-width:800px){.gcap{font-size:14px}}
.gal.mas .gi{display:flex;flex-direction:column}
.gal.mas .gf{flex:1 1 auto;min-height:0;padding-bottom:10px}
.gal.mas .gt{flex:1 1 auto;height:auto;min-height:0}
.gal.mas .gcap{flex:none}
figure.lb-sheet{margin:0}

/* Travel cards */
.travel-cards{display:grid;gap:24px;margin-top:24px}
@media (min-width:800px){.travel-cards{grid-template-columns:repeat(2,1fr)}}
.travel-card{padding:20px;border:1px solid var(--line,rgba(215,232,188,.12));border-radius:8px;background:var(--surface,#2c2f32)}
.travel-card h3{font:400 22px/1.15 var(--serif);color:var(--paper,#f4f1ec);margin:0 0 6px}
.travel-dist{font:500 12px/1.3 var(--sans);letter-spacing:.1em;text-transform:uppercase;color:var(--acid,#e9f056);margin-bottom:8px}
.travel-card p{font-size:14px;line-height:1.5;color:var(--text,#d7e8bc)}
