/* Sabor Flow Da Nang — Tropical Heat design system
   Ported from Claude Design handoff (Direction B).
   Fonts are self-hosted, see fonts.css. */

:root {
  --sf-coral: #F26B6B;
  --sf-orange: #F2994A;
  --sf-gold: #F2C94C;
  --sf-teal: #2E8B95;
  --sf-teal-deep: #1A5560;
  --sf-ink: #0E0B0E;
  --sf-ink-2: #15101A;
  --sf-paper: #F7EFE3;
  --sf-max-w: 1280px;
  --sf-pad: 40px;
}

/* ── Reset ── */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
}

body {
  background: #0B0512;
  color: var(--sf-paper);
  font-family: 'Plus Jakarta Sans', system-ui, sans-serif;
  min-height: 100vh;
  overflow-x: hidden;
}

/* Read by screen readers, not shown. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Cross-fade between Turbo Drive page visits (top-nav tab clicks etc.), via
   the browser's native View Transition API — see the `view-transition` meta
   tag in the layout head. Old and new pages fade together in the same
   frame (unlike a hand-rolled hide-old-then-show-new sequence), so there's
   never a moment with nothing on screen, and it degrades gracefully to an
   instant swap on browsers/visits it doesn't apply to. Tuned down from the
   ~0.25s browser default to match the rest of the site's transitions. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: .18s;
  animation-timing-function: ease;
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

button {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}

/* Without `appearance: none` above, some browsers still paint a native
   pressed/focus look on click (a dark overlay, unreadable against our own
   dark-on-gradient button text) on top of a button's own background —
   this keeps every button's own :hover styling as the active/focus look
   too, instead of falling back to that native chrome. */
button:active {
  transform: translateY(0);
}

button:focus-visible {
  outline: 2px solid var(--sf-gold);
  outline-offset: 2px;
}

*[onclick],
*[role="button"] {
  -webkit-tap-highlight-color: transparent;
}

/* ── Background blobs (fixed, full page) ── */
.sfB-bg {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
}

@keyframes blob-pulse {

  0%,
  100% {
    opacity: 0.22;
  }

  50% {
    opacity: 0.85;
  }
}

/* 5 blobs in non-overlapping screen zones, each pulsing at its own pace */
.sfB-bg>span {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  animation: blob-pulse ease-in-out infinite;
}

/* coral — top-right */
.sfB-bg>span:nth-child(1) {
  width: 44vw;
  height: 42vh;
  right: -8%;
  top: -10%;
  background: rgba(242, 107, 107, 0.38);
  animation-duration: 11s;
  animation-delay: 0s;
}

/* teal — left, upper-mid */
.sfB-bg>span:nth-child(2) {
  width: 37vw;
  height: 48vh;
  left: -8%;
  top: 36%;
  background: rgba(46, 139, 149, 0.32);
  animation-duration: 14s;
  animation-delay: -3s;
}

/* gold — bottom-center-left */
.sfB-bg>span:nth-child(3) {
  width: 32vw;
  height: 30vh;
  left: 16%;
  bottom: -8%;
  background: rgba(242, 201, 76, 0.28);
  animation-duration: 9s;
  animation-delay: -6s;
}

/* orange — top-left */
.sfB-bg>span:nth-child(4) {
  width: 33vw;
  height: 34vh;
  left: -5%;
  top: -8%;
  background: rgba(232, 87, 42, 0.30);
  animation-duration: 16s;
  animation-delay: -1s;
}

/* pink — bottom-right */
.sfB-bg>span:nth-child(5) {
  width: 38vw;
  height: 37vh;
  right: -5%;
  bottom: 2%;
  background: rgba(224, 91, 126, 0.26);
  animation-duration: 12s;
  animation-delay: -8s;
}

.sfB-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px);
  background-size: 4px 4px;
  opacity: 0.7;
  mix-blend-mode: overlay;
}

/* Excludes full-screen overlays (mobile nav, the poster lightbox on the
   schedule page, the songs modal on the playlists page) that declare their
   own position:fixed + high z-index below — this selector's specificity (2
   :not() classes + the body type) beats their single-class rules, so
   without the exclusion it would silently strip their fixed positioning
   and z-index back down to relative/1, trapping them inside whatever
   stacking context their DOM position happens to give them (e.g. below the
   sticky topbar, or behind the footer). */
body>*:not(.sfB-bg):not(.sfB-topbar):not(.sfB-mobile-nav):not(.sfB-lightbox):not(.sfB-modal) {
  position: relative;
  z-index: 1;
}

/* ── Topbar ── */
.sfB-topbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 max(var(--sf-pad), calc((100% - var(--sf-max-w)) / 2));
  border-bottom: 1px solid rgba(255, 246, 232, 0.06);
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(11, 5, 18, 0.85);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.topbar-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.sfB-topbar .logo {
  display: flex;
  align-items: center;
  gap: 10px;
}

.sfB-admin-off {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: rgba(255, 246, 232, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: rgba(255, 246, 232, 0.7);
  cursor: pointer;
  transition: all .18s;
}

.sfB-admin-off:hover {
  background: var(--sf-coral);
  border-color: var(--sf-coral);
  color: #1a0d0d;
}

.sfB-admin-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: rgba(255, 246, 232, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: rgba(255, 246, 232, 0.7);
  cursor: pointer;
  transition: all .18s;
}

.sfB-admin-go:hover {
  background: var(--sf-teal);
  border-color: var(--sf-teal);
  color: #fff;
}

.sfB-topbar .logo .mark {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.1);
  flex-shrink: 0;
}

.sfB-topbar .logo .mark img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.sfB-topbar .logo .name {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 16px;
  letter-spacing: -0.5px;
  line-height: 1;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.sfB-topbar .logo .name .city {
  font-size: 8px;
  letter-spacing: 3px;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--sf-coral);
}

.sfB-nav {
  display: flex;
  gap: 4px;
  background: rgba(255, 246, 232, 0.05);
  padding: 5px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.sfB-nav a {
  padding: 8px 15px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2px;
  border-radius: 999px;
  color: rgba(255, 246, 232, 0.7);
  transition: all .18s;
  white-space: nowrap;
}

.sfB-nav a.active {
  background: linear-gradient(135deg, var(--sf-coral), var(--sf-orange));
  color: #1a0d0d;
  box-shadow: 0 4px 12px rgba(242, 107, 107, 0.35);
}

.sfB-nav a:hover:not(.active) {
  color: #fff;
  background: rgba(255, 255, 255, 0.05);
}

.sfB-topbar .topbar-right {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 12px;
}

.sfB-ig {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 13px;
  border-radius: 999px;
  background: rgba(255, 246, 232, 0.08);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.4px;
  white-space: nowrap;
}

.sfB-ig:hover {
  background: rgba(255, 246, 232, 0.15);
}

/* hamburger */
.sfB-hamburger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: rgba(255, 246, 232, 0.08);
  padding: 10px;
  border: 0;
  cursor: pointer;
}

.sfB-hamburger span {
  display: block;
  width: 100%;
  height: 2px;
  background: var(--sf-paper);
  border-radius: 2px;
}

/* mobile nav overlay */
.sfB-mobile-nav {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(11, 5, 18, 0.97);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.sfB-mobile-nav.open {
  display: flex;
}

.sfB-mobile-nav a {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 28px;
  letter-spacing: -0.5px;
  padding: 10px 30px;
  border-radius: 14px;
  color: rgba(255, 246, 232, 0.85);
  transition: all .15s;
}

.sfB-mobile-nav a:hover,
.sfB-mobile-nav a.active {
  color: var(--sf-coral);
  background: rgba(242, 107, 107, 0.1);
}

.sfB-mobile-nav .mnav-close {
  position: absolute;
  top: 22px;
  right: 22px;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: rgba(255, 246, 232, 0.08);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  cursor: pointer;
  color: var(--sf-paper);
  border: 0;
}

/* ── Animations ── */
@keyframes sfB-dot-pulse {

  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }

  50% {
    opacity: 0.4;
    transform: scale(0.65);
  }
}

@keyframes sfB-mq {
  to {
    transform: translateX(-25%);
  }
}

/* ── Hero ── */
.sfB-hero {
  padding: 48px var(--sf-pad) 30px;
  max-width: var(--sf-max-w);
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 40px;
  align-items: center;
}

.sfB-hero .left {
  position: relative;
}

.sfB-hero .kicker {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-radius: 999px;
  background: rgba(255, 246, 232, 0.06);
  border: 1px solid rgba(255, 246, 232, 0.1);
  font-size: 10px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  font-weight: 600;
  color: rgba(255, 246, 232, 0.85);
}

.sfB-hero .kicker .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--sf-gold);
  box-shadow: 0 0 10px var(--sf-gold);
  animation: sfB-dot-pulse 1.6s ease-in-out infinite;
}

.sfB-hero h1 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 118px;
  line-height: 0.87;
  letter-spacing: -4px;
  margin-top: 18px;
  padding-right: 6px;
  color: var(--sf-paper);
}

.sfB-hero h1 .glow {
  background: linear-gradient(120deg, var(--sf-coral), var(--sf-gold) 50%, var(--sf-orange));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-style: italic;
  font-family: 'Caveat Brush', cursive;
  letter-spacing: 0;
  font-weight: 400;
  display: inline-block;
  transform: rotate(-3deg) translateY(6px);
  margin: 0 -4px;
  padding-right: 6px;
}

.sfB-hero h1 .vn {
  display: block;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 8px;
  color: var(--sf-teal);
  margin-top: 18px;
  text-transform: uppercase;
  font-family: 'Plus Jakarta Sans', sans-serif;
}

.sfB-hero h1 .vn span {
  color: var(--sf-coral);
}

.sfB-hero .lead {
  margin-top: 26px;
  font-size: 15px;
  line-height: 1.55;
  color: rgba(255, 246, 232, 0.7);
  max-width: 460px;
}

.sfB-hero .ctas {
  display: flex;
  gap: 12px;
  margin-top: 28px;
  align-items: center;
  flex-wrap: wrap;
}

/* buttons */
.sfB-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 13px 22px;
  border-radius: 14px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.3px;
  transition: transform .2s, box-shadow .2s;
  white-space: nowrap;
}

.sfB-btn.primary {
  background: linear-gradient(135deg, var(--sf-coral), var(--sf-orange));
  color: #1a0d0d;
  box-shadow: 0 10px 28px rgba(242, 107, 107, 0.35);
}

.sfB-btn.primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 32px rgba(242, 107, 107, 0.45);
}

.sfB-btn.ghost {
  background: rgba(255, 246, 232, 0.08);
  color: var(--sf-paper);
  border: 1px solid rgba(255, 246, 232, 0.12);
}

.sfB-btn.ghost:hover {
  background: rgba(255, 246, 232, 0.14);
}

.sfB-btn.dark {
  background: #1a0d0d;
  color: var(--sf-paper);
}

.sfB-btn.dark:hover {
  background: #000;
}

.sfB-hero .meta-row {
  display: flex;
  gap: 26px;
  margin-top: 34px;
  padding-top: 26px;
  border-top: 1px solid rgba(255, 246, 232, 0.08);
}

.sfB-hero .meta-row .item .v {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 30px;
  line-height: 1;
  background: linear-gradient(135deg, var(--sf-coral), var(--sf-gold));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.sfB-hero .meta-row .item .l {
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: rgba(255, 246, 232, 0.5);
  margin-top: 6px;
}

/* hero right — card stack */
.sfB-hero .hero-right {
  position: relative;
  height: 460px;
}

.sfB-stack-card {
  position: absolute;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.sfB-stack-card.c1 {
  top: 0;
  right: 0;
  width: 230px;
  height: 300px;
  background: linear-gradient(160deg, var(--sf-coral), #8B2A2A);
  z-index: 3;
  animation: card-sway-1 4.2s ease-in-out infinite alternate;
}

.sfB-stack-card.c2 {
  top: 60px;
  right: 200px;
  width: 200px;
  height: 260px;
  background: linear-gradient(160deg, var(--sf-teal), var(--sf-teal-deep));
  z-index: 2;
  animation: card-sway-2 5.1s ease-in-out infinite alternate;
  animation-delay: -2.3s;
}

.sfB-stack-card.c3 {
  top: 220px;
  right: 80px;
  width: 220px;
  height: 220px;
  background: linear-gradient(160deg, var(--sf-orange), #B85A1F);
  z-index: 4;
  animation: card-sway-3 3.7s ease-in-out infinite alternate;
  animation-delay: -1.1s;
}

.sfB-stack-card.c1:hover {
  animation-duration: 1.6s;
}

.sfB-stack-card.c2:hover {
  animation-duration: 1.9s;
}

.sfB-stack-card.c3:hover {
  animation-duration: 1.4s;
}

@keyframes card-sway-1 {
  from {
    transform: rotate(4deg) translateY(2px);
  }

  to {
    transform: rotate(8deg) translateY(-10px);
  }
}

@keyframes card-sway-2 {
  from {
    transform: rotate(-10deg) translateY(-3px);
  }

  to {
    transform: rotate(-6deg) translateY(-13px);
  }
}

@keyframes card-sway-3 {
  from {
    transform: rotate(1deg) translateY(0px);
  }

  to {
    transform: rotate(5deg) translateY(-9px);
  }
}

.sfB-stack-card .ph {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
}

.sfB-stack-card.c1 .ph {
  background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.45)), url("/assets/hero-salsa-050fb874.webp");
}

.sfB-stack-card.c2 .ph {
  background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.45)), url("/assets/hero-kizomba-edf3e494.webp");
}

.sfB-stack-card.c3 .ph {
  background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.45)), url("/assets/hero-bachata-c31812ba.webp");
}

.sfB-stack-card .tag {
  position: absolute;
  top: 14px;
  left: 14px;
  font-family: 'Caveat Brush', cursive;
  font-size: 28px;
  color: rgba(255, 255, 255, 0.9);
  line-height: 1;
}

.sfB-stack-card .ph-label {
  position: absolute;
  bottom: 12px;
  left: 14px;
  right: 14px;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 9px;
  letter-spacing: 1px;
  color: rgba(255, 255, 255, 0.80);
  text-transform: uppercase;
}

.sfB-hero .hero-right .badge {
  position: absolute;
  bottom: 0;
  left: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 17px;
  background: rgba(11, 5, 18, 0.88);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: 16px;
  border: 1px solid rgba(255, 246, 232, 0.1);
  z-index: 5;
}

.sfB-hero .hero-right .badge .ic {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--sf-gold), var(--sf-orange));
  display: flex;
  align-items: center;
  justify-content: center;
  color: #1a0d0d;
  font-size: 18px;
}

.sfB-hero .hero-right .badge .t {
  font-size: 12px;
  font-weight: 700;
}

.sfB-hero .hero-right .badge .s {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.6);
}

/* ── Marquee ── */
.sfB-marquee {
  padding: 18px 0;
  margin-top: 30px;
  border-top: 1px solid rgba(255, 246, 232, 0.06);
  border-bottom: 1px solid rgba(255, 246, 232, 0.06);
  overflow: hidden;
  max-width: 1300px;
  margin-inline: auto;
  border-radius: 0;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 7%, black 93%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, black 7%, black 93%, transparent 100%);
}

.sfB-marquee .track {
  display: flex;
  gap: 50px;
  animation: sfB-mq 32s linear infinite;
  white-space: nowrap;
  width: max-content;
}

.sfB-marquee .track span {
  font-family: 'Caveat Brush', cursive;
  font-size: 28px;
  color: rgba(255, 246, 232, 0.85);
  display: inline-flex;
  align-items: center;
  gap: 50px;
}

.sfB-marquee .track span::after {
  content: '✦';
  color: var(--sf-coral);
  font-size: 20px;
}

/* ── Pillars trio ── */
.sfB-pillars {
  padding: 60px var(--sf-pad) 30px;
  max-width: var(--sf-max-w);
  margin-inline: auto;
}

.sfB-pillars .head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-bottom: 28px;
  gap: 40px;
}

.sfB-pillars .head h2 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 52px;
  line-height: 0.95;
  letter-spacing: -1.5px;
  max-width: 540px;
}

.sfB-pillars .head h2 em {
  font-family: 'Caveat Brush', cursive;
  color: var(--sf-coral);
  font-style: normal;
  font-weight: 400;
  letter-spacing: 0;
}

.sfB-pillars .head .num {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 11px;
  letter-spacing: 1.5px;
  color: rgba(255, 246, 232, 0.6);
  white-space: nowrap;
}

.sfB-grid3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}

.sfB-pcard {
  position: relative;
  padding: 20px 20px;
  border-radius: 22px;
  overflow: hidden;
  min-height: auto;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  transition: transform .2s;
}

.sfB-pcard:hover {
  transform: translateY(-4px);
}

.sfB-pcard.c1 {
  background: linear-gradient(165deg, #C84747, #6B1818);
  color: var(--sf-paper);
}

.sfB-pcard.c2 {
  background: linear-gradient(165deg, var(--sf-teal), var(--sf-teal-deep));
  color: var(--sf-paper);
}

.sfB-pcard.c3 {
  background: linear-gradient(165deg, var(--sf-gold), #B57A12);
  color: #2a1a04;
}

.sfB-pcard .num {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 11px;
  letter-spacing: 2px;
  opacity: 0.65;
}

.sfB-pcard h3 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 30px;
  line-height: 1;
  margin-top: 28px;
  letter-spacing: -0.8px;
}

.sfB-pcard h3 em {
  font-family: 'Caveat Brush', cursive;
  font-style: normal;
  font-weight: 400;
}

.sfB-pcard p {
  font-size: 13px;
  margin-top: 12px;
  opacity: 0.85;
  line-height: 1.5;
}

.sfB-pcard .arr {
  position: absolute;
  top: 24px;
  right: 24px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
}

/* ── Schedule teaser ── */
.sfB-coming {
  padding: 30px var(--sf-pad) 60px;
  max-width: var(--sf-max-w);
  margin-inline: auto;
}

.sfB-coming .head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-bottom: 24px;
  gap: 20px;
}

.sfB-coming .head h2 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 52px;
  letter-spacing: -1.5px;
  line-height: 0.95;
}

.sfB-coming .head h2 em {
  font-family: 'Caveat Brush', cursive;
  color: var(--sf-gold);
  font-style: normal;
  font-weight: 400;
}

.sfB-coming .head a {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.5px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--sf-coral);
  white-space: nowrap;
}

.sfB-coming .head a:hover {
  color: var(--sf-orange);
}

.sfB-coming-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}

/* teaser card */
.sfB-tcard {
  padding: 18px 18px 20px;
  border-radius: 16px;
  background: rgba(255, 246, 232, 0.04);
  border: 1px solid rgba(255, 246, 232, 0.08);
  transition: all .2s;
  cursor: pointer;
  overflow: hidden;
}

.sfB-tcard:hover {
  background: rgba(255, 246, 232, 0.07);
  border-color: var(--sf-coral);
  transform: translateY(-2px);
}

.sfB-tcard .day {
  font-family: 'Caveat Brush', cursive;
  font-size: 26px;
  line-height: 1;
  background: linear-gradient(135deg, var(--sf-coral), var(--sf-gold));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.sfB-tcard .day-date {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 14px;
  letter-spacing: 0;
  vertical-align: middle;
}

.sfB-tcard .when {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 13px;
  letter-spacing: 1px;
  color: rgba(255, 255, 255, 0.5);
  margin-top: 4px;
}

.sfB-tcard h3 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 17px;
  margin-top: 12px;
  line-height: 1.1;
  letter-spacing: -0.3px;
}

.sfB-tcard .organizer {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 10px;
  letter-spacing: 0.5px;
  color: rgba(255, 255, 255, 0.6);
  margin-top: 4px;
  text-transform: uppercase;
}

.sfB-tcard .at {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.6);
  margin-top: 5px;
}

.sfB-tcard .chips {
  display: flex;
  gap: 5px;
  margin-top: 12px;
  flex-wrap: wrap;
}

/* ── Music chips ── */
.sfB-chip {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 3px 7px;
  border-radius: 4px;
}

.sfB-chip.salsa {
  background: rgba(242, 107, 107, 0.2);
  color: var(--sf-coral);
}

.sfB-chip.bachata {
  background: rgba(242, 201, 76, 0.2);
  color: var(--sf-gold);
}

.sfB-chip.kizomba {
  background: rgba(46, 139, 149, 0.25);
  color: #7ed4dd;
}

.sfB-chip.zouk {
  background: rgba(242, 153, 74, 0.2);
  color: var(--sf-orange);
}

/* A neutral chip for anything that isn't a dance style (a studio's
   amenities). */
.sfB-chip.plain {
  background: rgba(255, 246, 232, 0.08);
  color: rgba(255, 246, 232, 0.75);
}

/* Plain-text style names (e.g. the music-ratio example in the schedule page
   intro) colored to match .sfB-chip above, minus the pill background. */
.style-word.salsa { color: var(--sf-coral); }
.style-word.bachata { color: var(--sf-gold); }
.style-word.kizomba { color: #7ed4dd; }
.style-word.zouk { color: var(--sf-orange); }

/* ── CTA block ── */
.sfB-cta {
  position: relative;
  max-width: calc(var(--sf-max-w) - 2 * var(--sf-pad));
  margin: 0 auto 50px;
  padding: 40px;
  border-radius: 28px;
  background:
    linear-gradient(135deg, rgba(242, 107, 107, 0.9), rgba(242, 153, 74, 0.9)),
    radial-gradient(circle at 80% 30%, rgba(242, 201, 76, 0.5), transparent 50%);
  color: #1a0d0d;
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 30px;
  align-items: center;
  overflow: hidden;
}

.sfB-cta::before {
  content: '';
  position: absolute;
  top: -40px;
  right: -40px;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  border: 2px dashed rgba(26, 13, 13, 0.2);
  pointer-events: none;
}

.sfB-cta .quote {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 34px;
  line-height: 1.05;
  letter-spacing: -1px;
}

.sfB-cta .quote em {
  font-family: 'Caveat Brush', cursive;
  font-style: normal;
  font-weight: 400;
}

.sfB-cta .who {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  margin-top: 14px;
  opacity: 0.7;
}

.sfB-cta .cta-right {
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
  z-index: 2;
}

.sfB-cta .cta-right a {
  background: #1a0d0d;
  color: var(--sf-paper);
  padding: 15px 22px;
  border-radius: 14px;
  font-weight: 700;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  letter-spacing: 0.3px;
}

.sfB-cta .cta-right a:hover {
  background: #000;
}

.sfB-cta .cta-right a.alt {
  background: rgba(26, 13, 13, 0.12);
  color: #1a0d0d;
  border: 1px solid rgba(26, 13, 13, 0.22);
}

/* ── Footer ── */
.sfB-foot {
  padding: 28px max(var(--sf-pad), calc((100% - var(--sf-max-w)) / 2));
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  border-top: 1px solid rgba(255, 246, 232, 0.06);
  font-size: 11px;
  letter-spacing: 0.5px;
  color: rgba(255, 246, 232, 0.5);
  flex-wrap: wrap;
}

.sfB-foot .foot-links {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}

.sfB-foot .foot-links a:hover {
  color: var(--sf-coral);
}

.sfB-foot .foot-social {
  display: flex;
  gap: 14px;
}

.sfB-foot .foot-social a:hover {
  color: var(--sf-coral);
}

.sfB-foot strong {
  color: var(--sf-coral);
  font-weight: 700;
}

/* ── Page head (inner pages) ── */
.sfB-page {
  padding: 28px var(--sf-pad) 40px;
  max-width: var(--sf-max-w);
  margin-inline: auto;
}

.sfB-page-head {
  margin-top: 28px;
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 30px;
  align-items: end;
}

.sfB-page-head h1 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 88px;
  line-height: 0.9;
  letter-spacing: -3px;
}

.sfB-page-head h1 em {
  font-family: 'Caveat Brush', cursive;
  font-style: normal;
  font-weight: 400;
  background: linear-gradient(120deg, var(--sf-coral), var(--sf-gold));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.sfB-page-head .info {
  font-size: 13px;
  color: rgba(255, 246, 232, 0.80);
  line-height: 1.55;
  padding: 16px 18px;
  border-radius: 14px;
  background: rgba(255, 246, 232, 0.04);
  border: 1px solid rgba(255, 246, 232, 0.08);
}

.sfB-page-head .info a {
  color: var(--sf-teal);
}

.sfB-page-head .info a:hover {
  color: var(--sf-coral);
}

.sfB-page-head .info b {
  color: var(--sf-gold);
}

/* filter toolbar */
.sfB-toolbar {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 28px 0 16px;
  flex-wrap: wrap;
  gap: 12px;
}

.sfB-pills {
  display: flex;
  gap: 6px;
  background: rgba(255, 246, 232, 0.04);
  padding: 5px;
  border-radius: 999px;
  border: 1px solid rgba(255, 246, 232, 0.06);
  flex-wrap: wrap;
}

.sfB-pills .filter-pill {
  padding: 8px 14px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: rgba(255, 246, 232, 0.80);
  transition: all .18s;
  border: 0;
  cursor: pointer;
  background: transparent;
  outline: none;
}

.sfB-pills .filter-pill:focus-visible {
  outline: 2px solid var(--sf-coral);
  outline-offset: 2px;
}

.sfB-pills .filter-pill.active {
  background: linear-gradient(135deg, var(--sf-coral), var(--sf-orange));
  color: #1a0d0d;
}

.sfB-pills .filter-pill:hover:not(.active) {
  color: #fff;
}

.filterable-card {
  transition: opacity .18s ease, transform .18s ease;
}

.filterable-card.sfB-hiding {
  opacity: 0;
  transform: scale(.96);
}

.filterable-card.hidden {
  display: none;
}

/* ── Schedule list ── */
.sfB-list {
  display: flex;
  flex-direction: column;
  /* Wider than a plain list gap needs, on purpose — .sfB-row-more (the
     blinking "there's more" badge) hangs 12px below each collapsed card,
     and this leaves clearance so it never touches the card underneath. */
  gap: 18px;
}

/* Wraps .sfB-row (the clickable card) + .sfB-row-expand (the accordion
   panel toggled by main.js) as one unit for filtering, and gives the admin
   edit button below a positioning context so it can overlay the card
   without taking part in either's layout. */
.sfB-row-wrap {
  position: relative;
}

.sfB-row {
  display: grid;
  /* Positioning context for .sfB-row-more below — an absolutely positioned
     grid child is pulled out of grid layout entirely, so it doesn't fight
     the columns for space. */
  position: relative;
  /* .col-music is `auto` rather than `1fr` — it only ever holds a couple of
     small pill chips, so giving it an equal share left them floating with a
     lot of dead space around them and read as a big gap between the social
     and venue columns either side; shrinking it to its content hands that
     space back to those two. */
  grid-template-columns: 46px 140px 130px 1fr auto 1fr;
  align-items: center;
  gap: 14px;
  padding: 18px 22px;
  border-radius: 16px;
  background: rgba(255, 246, 232, 0.03);
  border: 1px solid rgba(255, 246, 232, 0.06);
  transition: all .15s;
  cursor: pointer;
}

/* Gated to devices that actually support hover — on touch, :hover applies
   on tap and then has no "leave" event to clear it, so without this guard
   the coral border stuck around after collapsing a row (or tapping a link
   inside it, e.g. the venue address or host name) on mobile. */
@media (hover: hover) {
  .sfB-row:hover {
    background: rgba(255, 246, 232, 0.06);
    border-color: var(--sf-coral);
    transform: translateX(4px);
  }
}

.sfB-row.today {
  background: linear-gradient(90deg, rgba(242, 107, 107, 0.14), rgba(255, 246, 232, 0.03) 60%);
  border-color: rgba(242, 107, 107, 0.45);
}

/* Flatten the card's bottom corners and let its border carry straight into
   .sfB-row-expand-content below, so the two read as one continuous card
   instead of two stacked ones — see .sfB-row-expand-content further down. */
.sfB-row-wrap.expanded .sfB-row {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  border-color: var(--sf-coral);
}

/* Matches the row's own bottom corner flattening above — the poster bleeds
   flush against the bottom-left corner on desktop and the bottom-right one
   on mobile (see .col-poster's margin in both places), so it needs to
   square off in step or it'd show a stray rounded notch. Resetting both is
   harmless: whichever corner wasn't rounded to begin with is already 0. */
.sfB-row-wrap.expanded .sfB-row .col-poster img {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.sfB-row-wrap.expanded .sfB-row:hover {
  transform: none;
}

/* "There's more" hint: a blinking circular badge hanging off the bottom
   center of each collapsed card. It's a child of .sfB-row, so a click on
   it (including the half poking out below the card) bubbles to the row's
   toggle — it's part of the card, not a second interactive target
   (aria-hidden). Only shown while collapsed; it disappears once the card
   is expanded, since the "more" it was pointing at is now shown. */
.sfB-row-more {
  position: absolute;
  bottom: -12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #1a1a1a;
  border: 1px solid var(--sf-coral);
  color: var(--sf-coral);
  cursor: pointer;
}

/* Only the chevrons blink — the circle/border stay fully opaque the whole
   time, so it never fades into looking like a rendering glitch the way
   blinking the whole badge did. */
.sfB-row-more svg {
  animation: sfB-tonight-blink 2.4s ease-in-out infinite;
}

.sfB-row-wrap.expanded .sfB-row-more {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .sfB-row-more svg {
    animation: none;
  }
}

/* Groups col-day/col-when so mobile can turn them into one full-width
   header row (see the @media 960px block) without disturbing desktop, where
   `contents` drops it from layout entirely and lets its children slot back
   in as independent grid columns, exactly where they'd sit if this wrapper
   didn't exist. */
.sfB-row .row-header {
  display: contents;
}

.sfB-row .col-poster {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Grid's own `align-items: center` (see .sfB-row) would otherwise size
     this box to its intrinsic (image) height and center that within the
     row's full height, leaving visible margin above/below the poster.
     Stretching it here lets the image below fill the row's actual height. */
  align-self: stretch;
  /* Pulls the poster out past the row's own padding (18px 22px) on the
     three sides that border the card edge, so the thumbnail bleeds flush
     against the card's border instead of sitting inset like every other
     column — the right side keeps the normal gap to .col-day. */
  margin: -18px 0 -18px -22px;
}

.sfB-row .col-poster img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Only the left corners round now — they sit right against the card's
     own rounded border (radius minus the 1px border width), while the
     right corners butt squarely against .col-day. */
  border-radius: 15px 0 0 15px;
  /* Signals it opens the fullscreen lightbox rather than the row's own
     accordion, like the rest of the card (cursor: pointer there). */
  cursor: zoom-in;
}

.sfB-row .col-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.sfB-row .col-day .day-line {
  display: flex;
  align-items: baseline;
  gap: 7px;
}

.sfB-row .col-day .date-num {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 15px;
  font-weight: 500;
  color: var(--sf-gold);
  opacity: 0.65;
  letter-spacing: -0.5px;
  flex-shrink: 0;
}

.sfB-row .col-day .name {
  font-family: 'Caveat Brush', cursive;
  font-size: 28px;
  /* Caveat Brush's descenders (the tail on "y" in Monday/Friday/Sunday...)
     sit outside a line-height:1 box; since the gradient below is only
     painted within that box (background-clip: text), anything the box
     doesn't cover comes out invisible instead of just tight — reads as the
     glyph getting cut off at the bottom. A bit of headroom fixes it. */
  line-height: 1.25;
  background: linear-gradient(135deg, var(--sf-coral), var(--sf-gold));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.sfB-row .col-day .when {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 9px;
  letter-spacing: 1px;
  color: rgba(255, 246, 232, 0.45);
  text-transform: uppercase;
}

.sfB-row .col-when {
  display: flex;
  align-items: center;
  /* Its 130px grid column is wider than the time text itself — without this
     the block (even now that when-times centers its own two lines) sits
     flush against the column's left edge, leaving a lot of dead space
     before the gap to col-social and reading as a bigger gap on that side
     than the one on col-day's side. */
  justify-content: center;
  gap: 10px;
}

.sfB-row .col-when .when-times {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  text-align: center;
}

/* Desktop-only bump (see the @media 960px block for the mobile-size
   reset) — larger than the rest of the row's small print since the time is
   one of the first things someone scans a row for. */
.sfB-row .col-when .when-start {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 0.3px;
  white-space: nowrap;
  color: var(--sf-gold);
}

.sfB-row .col-when .when-end {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.3px;
  white-space: nowrap;
  color: rgba(255, 246, 232, 0.5);
}

.sfB-row .col-venue {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 2px;
}

.sfB-row .col-venue .venue-name-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.sfB-row .col-venue a {
  /* 24px+ tap target; the negative margin keeps the row's height as it was. */
  padding-block: 2px;
  margin-block: -2px;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 500;
  font-size: 20px;
  letter-spacing: -0.3px;
  white-space: nowrap;
  background: linear-gradient(120deg, var(--sf-orange), var(--sf-gold));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.sfB-row .col-venue a:hover {
  background: none;
  -webkit-background-clip: unset;
  background-clip: unset;
  color: var(--sf-coral);
}

.sfB-row .col-venue .venue-city {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 15px;
  font-weight: 500;
  font-style: italic;
  letter-spacing: 0.2px;
  white-space: nowrap;
  color: rgba(255, 246, 232, 0.8);
}

.sfB-row .col-social {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 3px;
}

.sfB-row .col-social .event-name {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 600;
  font-size: 18px;
  letter-spacing: -0.2px;
  color: var(--sf-gold);
  text-shadow: 0 0 2px rgba(242, 201, 76, 0.9), 0 0 1px rgba(242, 201, 76, 0.9);
  white-space: nowrap;
}

/* Flags a night with news (EventOccurrence highlight); the news itself is
   in the expanded card. */
.sfB-row .col-social .event-special {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--sf-coral);
}

.sfB-row .col-org {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 700;
  font-size: 15px;
  color: rgba(255, 246, 232, 0.75);
}

.sfB-row .col-org a {
  color: inherit;
  /* A taller tap target (24px+) without moving the text: vertical padding
     on an inline link doesn't change the line box. */
  padding-block: 4px;
}

.host-separator {
  font-size: 0.75em;
}

/* Still one chip per line (not a grid/wrap) — min-height reserves a
   two-chip-tall space (20px chip + 4px gap + 20px chip, see .sfB-chip's
   line-height:1 below) and centers the stack within it, so an event with
   just one chip doesn't read shorter than one with two or three. Three (the
   practical max) would overflow that reserved height at full size, so the
   :has() rule below shrinks them to fit instead of growing a third full-size
   row — see that rule for the desktop-only scoping reasoning. */
.sfB-row .col-music {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 44px;
}

/* Pill-shaped chips matching the poster's .style-badge (same palette as the
   base .sfB-chip already used elsewhere — studios/festivals/classes pages,
   the event modal — so only size/shape are overridden here, scoped to the
   schedule row, rather than changing that shared class everywhere). */
.sfB-row .col-music .sfB-chip {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2px;
  line-height: 1;
  padding: 4px 11px;
  border-radius: 999px;
}

/* Scoped to desktop (mobile lays chips out in its own left-aligned wrapping
   row below, sized independently per grid-area — see the @media 960px
   block) so this doesn't fight that block's own chip sizing: :has() gives
   this more specificity than a plain class selector, which would otherwise
   win here despite coming later in the file, breaking the normal
   source-order override every other mobile rule in this file relies on. */
@media (min-width: 961px) {
  .sfB-row .col-music:has(.sfB-chip:nth-child(3)) {
    gap: 2px;
  }

  .sfB-row .col-music:has(.sfB-chip:nth-child(3)) .sfB-chip {
    font-size: 10px;
    padding: 2px 9px;
  }
}

.sfB-row .col-city {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 6px;
  text-align: center;
  width: fit-content;
}

.sfB-row .col-city.danang {
  background: rgba(242, 107, 107, 0.18);
  color: var(--sf-coral);
}

.sfB-row .col-city.hoian {
  background: rgba(46, 139, 149, 0.22);
  color: #7ed4dd;
}

.sfB-row.today .tonight-label {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1.5px;
  color: var(--sf-coral);
  text-transform: uppercase;
  margin-top: 3px;
  animation: sfB-tonight-blink 2.4s ease-in-out infinite;
}

@keyframes sfB-tonight-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

@media (prefers-reduced-motion: reduce) {
  .sfB-row.today .tonight-label {
    animation: none;
  }
}

/* Mobile-only "Tonight" stamp (see _row.html.erb) — the desktop label
   above stays as the only "today" marker at that breakpoint; this image
   badge replaces it on mobile instead of showing both. Positioned and
   animated in the @media 960px block below. */
.sfB-row-stamp {
  display: none;
}

.sfB-page .footnote {
  margin-top: 20px;
  font-size: 11px;
  color: rgba(255, 246, 232, 0.6);
  letter-spacing: 0.5px;
}

/* ── Cards grid (studios / classes) ── */
.sfB-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  margin-top: 24px;
}

.sfB-cards.two {
  grid-template-columns: 1fr 1fr;
}

.sfB-card-x {
  position: relative;
  padding: 22px 22px 24px;
  border-radius: 18px;
  background: rgba(255, 246, 232, 0.04);
  border: 1px solid rgba(255, 246, 232, 0.08);
  overflow: hidden;
  transition: all .2s;
}

.sfB-card-x:hover {
  background: rgba(255, 246, 232, 0.06);
  border-color: var(--sf-coral);
  transform: translateY(-2px);
}

.sfB-card-x .stripe {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
}

.sfB-card-x .stripe.salsa {
  background: var(--sf-coral);
}

.sfB-card-x .stripe.bachata {
  background: var(--sf-gold);
}

.sfB-card-x .stripe.kizomba {
  background: var(--sf-teal);
}

.sfB-card-x .stripe.zouk {
  background: var(--sf-orange);
}

.sfB-card-x .stripe.multi {
  background: linear-gradient(90deg, var(--sf-coral), var(--sf-gold), var(--sf-teal), var(--sf-orange));
}

.sfB-card-x h2,
.sfB-card-x h3 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 21px;
  letter-spacing: -0.5px;
  line-height: 1.1;
  margin-top: 10px;
}

.sfB-card-x .ts {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 12px;
}

.sfB-card-x .info {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 14px;
  font-size: 12px;
  color: rgba(255, 246, 232, 0.7);
  line-height: 1.4;
}

.sfB-card-x .info .row {
  display: flex;
  gap: 8px;
  align-items: flex-start;
}

.sfB-card-x .info .ic {
  display: inline-flex;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--sf-coral);
  align-items: center;
  justify-content: center;
}

.sfB-card-x .info a {
  color: var(--sf-orange);
}

.sfB-card-x .links {
  display: flex;
  gap: 8px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 246, 232, 0.08);
  flex-wrap: wrap;
}

.sfB-card-x .links a {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 6px 10px;
  border-radius: 8px;
  background: rgba(255, 246, 232, 0.06);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.sfB-card-x .links a:hover {
  background: rgba(242, 107, 107, 0.18);
  color: var(--sf-coral);
}

/* Class card poster: a portrait thumbnail floated top-right, the title and
   info rows wrapping beside it; click opens the poster lightbox (main.js). */
.sfB-card-x .sfB-card-poster {
  float: right;
  margin: 10px 0 10px 14px;
}

.sfB-card-x .sfB-card-poster img {
  display: block;
  width: 92px;
  height: 128px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid rgba(255, 246, 232, 0.14);
  cursor: zoom-in;
}

.sfB-card-x .links {
  clear: both;
}

.sfB-suggest {
  margin-top: 24px;
  padding: 24px;
  border-radius: 18px;
  background: rgba(255, 246, 232, 0.04);
  border: 1px solid rgba(255, 246, 232, 0.08);
  text-align: center;
}

.sfB-suggest p {
  color: rgba(255, 246, 232, 0.6);
  margin-bottom: 16px;
  font-size: 14px;
}

/* ── Festival posters ── */
.sfB-fest {
  position: relative;
  border-radius: 24px;
  overflow: hidden;
  margin-top: 20px;
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  min-height: 320px;
  border: 1px solid rgba(255, 246, 232, 0.08);
}

.sfB-fest .poster {
  position: relative;
  padding: 32px 30px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
}

.sfB-fest .poster.coral {
  background: linear-gradient(160deg, var(--sf-coral) 0%, #8B2A2A 70%, #4A0F0F);
  color: var(--sf-paper);
}

.sfB-fest .poster.teal {
  background: linear-gradient(160deg, var(--sf-teal) 0%, var(--sf-teal-deep) 60%, #0A2A30);
  color: var(--sf-paper);
}

.sfB-fest .poster::after {
  content: '';
  position: absolute;
  bottom: -60px;
  right: -60px;
  width: 280px;
  height: 280px;
  border-radius: 50%;
  border: 2px dashed rgba(255, 255, 255, 0.18);
  pointer-events: none;
}

.sfB-fest .poster::before {
  content: '';
  position: absolute;
  bottom: -40px;
  right: -40px;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  border: 2px dashed rgba(255, 255, 255, 0.12);
  pointer-events: none;
}

.sfB-fest .poster .pill {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  padding: 6px 12px;
  background: rgba(0, 0, 0, 0.25);
  border-radius: 999px;
  width: fit-content;
}

.sfB-fest .poster .name {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 46px;
  letter-spacing: -2px;
  line-height: 0.95;
  margin-top: 26px;
  position: relative;
  z-index: 1;
}

.sfB-fest .poster .name em {
  font-family: 'Caveat Brush', cursive;
  font-style: normal;
  font-weight: 400;
}

.sfB-fest .poster .dates {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 12px;
  letter-spacing: 2px;
  text-transform: uppercase;
  margin-top: 14px;
  opacity: 0.85;
  position: relative;
  z-index: 1;
}

.sfB-fest .poster .big {
  position: absolute;
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 180px;
  line-height: 0.85;
  top: 40px;
  right: 20px;
  letter-spacing: -10px;
  opacity: 0.18;
  z-index: 0;
}

.sfB-fest .body {
  padding: 28px;
  background: rgba(11, 5, 18, 0.7);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.sfB-fest .body .meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 12px;
  color: rgba(255, 246, 232, 0.75);
}

.sfB-fest .body .meta .item {
  display: flex;
  gap: 6px;
  align-items: center;
}

.sfB-fest .body .meta .item b {
  color: var(--sf-paper);
}

.sfB-fest .body .styles {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.sfB-fest .body p {
  font-size: 14px;
  color: rgba(255, 246, 232, 0.8);
  line-height: 1.55;
}

.sfB-fest .body .acts {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 246, 232, 0.08);
}

.sfB-fest .body .acts a {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  padding: 10px 16px;
  border-radius: 10px;
  background: rgba(255, 246, 232, 0.06);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.sfB-fest .body .acts a:hover {
  background: rgba(255, 246, 232, 0.1);
}

.sfB-fest .body .acts a.primary {
  background: linear-gradient(135deg, var(--sf-coral), var(--sf-orange));
  color: #1a0d0d;
}

/* Past festivals: their own heading, cards toned down. Also a dance style
   page's sections (styles/show). */
.sfB-fest-section,
.sfB-section-title {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 28px;
  letter-spacing: -1px;
  margin-top: 48px;
}

.sfB-fest .poster[data-full-src] {
  cursor: zoom-in;
}

.sfB-fest.past .poster {
  /* Only the poster fades: dimming the whole card took its text and style
     chips below a readable contrast. */
  opacity: 0.7;
  filter: saturate(0.6);
}

.sfB-fest .body p.prices {
  font-size: 12px;
  color: var(--sf-gold);
}

.sfB-fest-empty {
  margin-top: 28px;
  font-size: 14px;
  color: rgba(255, 246, 232, 0.7);
}

.sfB-fest-empty a {
  color: var(--sf-gold);
}

/* A dance style page's links to the other styles (styles/show). */
.sfB-style-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}

/* ── Connect page ── */
.sfB-connect-hero {
  margin-top: 28px;
  padding: 40px;
  border-radius: 24px;
  background:
    radial-gradient(ellipse at 80% 30%, rgba(242, 107, 107, 0.25), transparent 55%),
    rgba(255, 246, 232, 0.04);
  border: 1px solid rgba(255, 246, 232, 0.08);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  align-items: center;
}

.sfB-connect-hero .ch-left {
  display: flex;
  align-items: center;
  gap: 22px;
}

.sfB-connect-hero .ava {
  width: 110px;
  height: 110px;
  border-radius: 50%;
  border: 3px solid var(--sf-gold);
  overflow: hidden;
  flex-shrink: 0;
}

.sfB-connect-hero .ava img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.sfB-connect-hero h2 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 34px;
  letter-spacing: -1px;
}

.sfB-connect-hero .h {
  font-family: 'Caveat Brush', cursive;
  font-size: 26px;
  background: linear-gradient(120deg, var(--sf-coral), var(--sf-gold));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  margin-bottom: 4px;
}

.sfB-connect-hero p {
  font-size: 13px;
  color: rgba(255, 246, 232, 0.80);
  margin-top: 8px;
  line-height: 1.5;
}

.sfB-connect-hero .ch-right {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sfB-igrid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-top: 24px;
}

.sfB-igrid .ig {
  aspect-ratio: 1;
  border-radius: 12px;
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(255, 246, 232, 0.08);
  background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.04) 0 8px, transparent 8px 16px);
  cursor: pointer;
  transition: transform .2s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sfB-igrid .ig:hover {
  transform: scale(1.02);
}

.sfB-igrid .ig:nth-child(1) {
  background-color: rgba(242, 107, 107, 0.2);
}

.sfB-igrid .ig:nth-child(2) {
  background-color: rgba(46, 139, 149, 0.2);
}

.sfB-igrid .ig:nth-child(3) {
  background-color: rgba(242, 201, 76, 0.18);
}

.sfB-igrid .ig:nth-child(4) {
  background-color: rgba(242, 153, 74, 0.2);
}

.sfB-igrid .ig:nth-child(5) {
  background-color: rgba(46, 139, 149, 0.2);
}

.sfB-igrid .ig:nth-child(6) {
  background-color: rgba(242, 107, 107, 0.2);
}

.sfB-igrid .ig:nth-child(7) {
  background-color: rgba(242, 153, 74, 0.2);
}

.sfB-igrid .ig:nth-child(8) {
  background-color: rgba(242, 201, 76, 0.18);
}

.sfB-igrid .ig .lbl {
  position: absolute;
  bottom: 8px;
  left: 10px;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 9px;
  color: rgba(255, 255, 255, 0.85);
  letter-spacing: 0.5px;
}

.sfB-collab {
  margin-top: 24px;
  padding: 36px;
  border-radius: 24px;
  background: linear-gradient(135deg, var(--sf-teal), var(--sf-teal-deep));
  text-align: center;
}

.sfB-collab .l {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 11px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--sf-gold);
}

.sfB-collab h2 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 44px;
  letter-spacing: -1.5px;
  margin-top: 10px;
  line-height: 1;
}

.sfB-collab h2 em {
  font-family: 'Caveat Brush', cursive;
  font-style: normal;
  font-weight: 400;
  color: var(--sf-coral);
}

.sfB-collab p {
  font-size: 14px;
  color: rgba(255, 246, 232, 0.85);
  margin-top: 12px;
  max-width: 500px;
  margin-left: auto;
  margin-right: auto;
  line-height: 1.5;
}

.sfB-collab .acts {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin-top: 22px;
  flex-wrap: wrap;
}

/* ── Reduced motion ── */
@media (prefers-reduced-motion: reduce) {
  .sfB-marquee .track {
    animation: none;
  }

  .sfB-hero .kicker .dot {
    animation: none;
  }

  * {
    transition-duration: 0.01ms !important;
  }
}

/* ── Responsive: tablet ── */
@media (max-width: 960px) {
  :root {
    --sf-pad: 20px;
  }

  .sfB-topbar {
    grid-template-columns: 1fr auto;
    padding: 0 20px;
  }

  .sfB-topbar .sfB-nav {
    display: none;
  }

  .sfB-topbar .topbar-right .sfB-ig {
    display: none;
  }

  .sfB-hamburger {
    display: flex;
  }

  .sfB-hero {
    grid-template-columns: 1fr;
    padding: 30px 20px 0;
    gap: 0;
  }

  .sfB-hero .hero-right {
    display: none;
  }

  .sfB-hero h1 {
    font-size: 72px;
    letter-spacing: -2.5px;
  }

  .sfB-hero h1 .vn {
    font-size: 14px;
    margin-top: 14px;
  }

  .sfB-marquee .track span {
    font-size: 22px;
  }

  .sfB-pillars {
    padding: 40px 20px 20px;
  }

  .sfB-pillars .head h2 {
    font-size: 38px;
  }

  .sfB-grid3 {
    grid-template-columns: 1fr;
  }

  .sfB-pcard {
    min-height: auto;
  }

  .sfB-pcard h3 {
    font-size: 26px;
    margin-top: 24px;
  }

  .sfB-coming {
    padding: 20px 20px 40px;
  }

  .sfB-coming .head h2 {
    font-size: 38px;
  }

  .sfB-coming-row {
    grid-template-columns: 1fr 1fr;
  }

  .sfB-cta {
    max-width: none;
    margin: 0 20px 36px;
    padding: 28px;
    grid-template-columns: 1fr;
  }

  .sfB-cta .quote {
    font-size: 26px;
  }

  .sfB-foot {
    padding: 20px;
    flex-direction: column;
    text-align: center;
    font-size: 10px;
  }

  .sfB-foot .foot-links {
    justify-content: center;
  }

  .sfB-foot .foot-social {
    justify-content: center;
  }

  .sfB-page {
    padding: 20px 20px 30px;
  }

  .sfB-page-head {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  .sfB-page-head h1 {
    font-size: 56px;
    letter-spacing: -2px;
  }

  .sfB-toolbar {
    flex-direction: column;
    align-items: center;
  }

  .sfB-pills {
    flex-wrap: wrap;
    justify-content: center;
    border-radius: 14px;
    width: 100%;
  }

  /* Day + time run as one full-width header row on top; below that, the
     rest of the info (social/music/venue) stacks in a left column with the
     poster thumbnail spanning that stack as one grid area on the right
     (vertically centered, via .col-poster below) instead of sitting above it. */
  .sfB-row {
    grid-template-columns: 1fr 76px;
    grid-template-areas:
      "header header"
      "social poster"
      "music poster"
      "venue poster";
    padding: 14px 16px;
    gap: 8px 12px;
  }

  /* Real flex box here instead of `contents` (the desktop default) — day and
     time become the row's own full-width header, sitting above the body
     (info left / poster thumbnail right) instead of sharing a column with
     the poster. */
  .sfB-row .row-header {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    position: relative;
    grid-area: header;
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(255, 246, 232, 0.08);
  }

  .sfB-row .col-poster {
    grid-area: poster;
    align-self: stretch;
    /* Same bleed as desktop (see the base .col-poster rule) but mirrored —
       here the poster sits on the right/bottom of the card, so it's those
       two sides (this row's own padding is 14px 16px) that get pulled past
       the padding to touch the card edge; the left keeps its gap to the
       text. The top also pulls up by the grid's row-gap (8px, see .sfB-row)
       so the poster reaches the header's bottom border instead of leaving a
       sliver of card background between them. */
    margin: -8px -16px -14px 0;
  }

  .sfB-row .col-poster img {
    width: 100%;
    height: 100%;
    /* Only the bottom-right corner sits against an actual rounded corner of
       the card (bottom edge + right edge both bled to) — the rest border
       either the header row above or the text column to the left. */
    border-radius: 0 0 15px 0;
  }

  .sfB-row .col-day {
    flex-direction: row;
    align-items: baseline;
    gap: 8px;
  }

  /* On mobile the header is just day + time (see grid-template-areas
     above) — the text "Tonight" label under the date is desktop-only; the
     stamp graphic below is the mobile equivalent. */
  .sfB-row.today .tonight-label--day {
    display: none;
  }

  /* Stamped onto the card's top-left corner, tilted like it was actually
     stamped there, with a slow scale "breathe" to catch the eye without
     being as busy as the fast opacity blink used elsewhere (.tonight-label,
     .sfB-row-more). Unlike .tonight-label--day it isn't scoped under
     .sfB-row.today in the selector — see _row.html.erb, where the <img> is
     only rendered at all for today's events, so no such guard is needed
     here. */
  .sfB-row-stamp {
    display: block;
    position: absolute;
    top: -14px;
    left: -10px;
    width: 60px;
    height: auto;
    z-index: 3;
    pointer-events: none;
    transform: rotate(-12deg);
    animation: sfB-stamp-breathe 3s ease-in-out infinite;
  }

  @keyframes sfB-stamp-breathe {
    0%, 100% { transform: rotate(-12deg) scale(1); }
    50% { transform: rotate(-12deg) scale(1.1); }
  }

  @media (prefers-reduced-motion: reduce) {
    .sfB-row-stamp {
      animation: none;
    }
  }

  .sfB-row .col-social { grid-area: social; }
  .sfB-row .col-music { grid-area: music; }
  .sfB-row .col-venue { grid-area: venue; }

  .sfB-row .col-day .name {
    font-size: 25px;
  }

  /* Resets the desktop-only bump above (.sfB-row .col-when .when-start/-end)
     back to its original size — mobile's header is tighter on space and
     already has the day name doing the heavy lifting. */
  .sfB-row .col-when .when-start {
    font-size: 15px;
  }

  .sfB-row .col-when .when-end {
    font-size: 13px;
  }

  .sfB-row .col-social .event-name {
    font-size: 15px;
    white-space: normal;
  }

  .sfB-row .col-org {
    font-size: 13px;
    text-align: left;
  }

  /* Desktop centers .col-music/.col-venue within their own grid column, which
     reads fine sitting between other centered columns — but stacked in this
     single left-hand column on mobile, centering just those two rows while
     everything else stays left-aligned is what made the layout feel off.
     Back to a plain left-aligned wrapping flex row here — the desktop-only
     fixed-height column stack (see the base .col-music rule, and the
     min-width:961px rule right after it) exists to keep row height stable
     across a horizontal row of centered columns; mobile's rows are already
     sized independently per grid-area (see grid-template-areas above), so
     no such column shares its height with .col-music here and the chip
     count growing it by a line is harmless. */
  .sfB-row .col-music {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-start;
    min-height: 0;
  }

  .sfB-row .col-music .sfB-chip {
    font-size: 10px;
    padding: 3px 9px;
  }

  .sfB-row .col-venue {
    align-items: flex-start;
    text-align: left;
  }

  /* .col-venue a's font-size is otherwise unset at this breakpoint (same
     20px as desktop), which is too wide for the narrower stacked column on
     small phones — see venue names like "Hi Coffee & Restaurant". */
  .sfB-row .col-venue a {
    font-size: 16px;
  }

  .sfB-row .col-venue .venue-city {
    font-size: 13px;
  }

  .sfB-row .col-city {
    width: fit-content;
  }

  /* Smaller + tucked in tighter to take up less of the card on a narrow
     screen. */
  .sfB-row-edit {
    width: 24px;
    height: 24px;
    top: 8px;
    right: 8px;
  }

  .sfB-cards {
    grid-template-columns: 1fr 1fr;
  }

  .sfB-cards.two {
    grid-template-columns: 1fr;
  }

  .sfB-fest {
    grid-template-columns: 1fr;
  }

  .sfB-fest .poster .big {
    font-size: 110px;
  }

  .sfB-connect-hero {
    grid-template-columns: 1fr;
    gap: 24px;
    padding: 24px;
  }

  .sfB-connect-hero .ch-left {
    flex-direction: column;
    text-align: center;
    align-items: center;
  }

  .sfB-igrid {
    grid-template-columns: repeat(2, 1fr);
  }

  .sfB-collab h2 {
    font-size: 34px;
  }

  .sfB-collab {
    padding: 28px;
  }
}

@media (max-width: 600px) {
  .sfB-hero h1 {
    font-size: 54px;
    letter-spacing: -1.5px;
  }

  .sfB-coming-row {
    grid-template-columns: 1fr;
  }

  .sfB-cards {
    grid-template-columns: 1fr;
  }

  .sfB-igrid {
    grid-template-columns: repeat(2, 1fr);
  }

  .sfB-page-head h1 {
    font-size: 44px;
    letter-spacing: -1.5px;
  }

  .sfB-collab h2 {
    font-size: 28px;
  }
}

/* ── Palm-frond background layer ── */
.sfB-palms {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.sfB-palm {
  position: absolute;
  /* 40vw total width → 10vw off-screen (matching -10% offset) → 30vw visible per side */
  width: clamp(100px, 40vw, 620px);
  height: clamp(100px, 40vw, 620px);
  object-fit: contain;
  opacity: 0.22;
  filter: saturate(0.75) brightness(0.95) hue-rotate(-6deg);
  mix-blend-mode: lighten;
  --flip: ;
  /* empty default so keyframes resolve to rotate(...) not "none rotate(...)" */
  animation-name: sfB-palm-sway;
  animation-duration: 6s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
  animation-timing-function: ease-in-out;
  will-change: transform;
}

.sfB-palm.corner-tl {
  top: -8%;
  left: -10vw;
  transform-origin: 0% 0%;
  animation-duration: 7s;
}

.sfB-palm.corner-tr {
  top: -8%;
  right: -10vw;
  transform-origin: 100% 0%;
  animation-duration: 5s;
}

.sfB-palm.corner-bl {
  bottom: -8%;
  left: -10vw;
  transform-origin: 0% 100%;
  animation-duration: 8s;
}

.sfB-palm.corner-br {
  bottom: -8%;
  right: -10vw;
  transform-origin: 100% 100%;
  animation-duration: 6.5s;
}

.sfB-palm.corner-ml {
  top: 32%;
  left: -10vw;
  width: clamp(120px, 49vw, 760px);
  height: clamp(120px, 49vw, 760px);
  opacity: 0.28;
  transform-origin: 0% 50%;
  animation-duration: 9s;
}

.sfB-palm.corner-mr {
  top: 22%;
  right: -10vw;
  width: clamp(110px, 44vw, 680px);
  height: clamp(110px, 44vw, 680px);
  opacity: 0.26;
  transform-origin: 100% 50%;
  animation-duration: 7.5s;
}

@keyframes sfB-palm-sway {
  from {
    transform: var(--flip, none) rotate(calc(var(--sway, 14deg) * -0.25));
  }

  to {
    transform: var(--flip, none) rotate(calc(var(--sway, 14deg) * 0.25));
  }
}

@media (prefers-reduced-motion: reduce) {
  .sfB-palm {
    animation: none !important;
  }
}

/* ── Schedule: organizer links inside row ── */
.sfB-row .col-org a {
  text-decoration: none;
}

.sfB-row .col-org a:hover {
  color: var(--sf-teal);
}

/* ── Event row accordion (schedule page) ──
   .sfB-row-expand animates open/closed via the "grid-template-rows: 0fr to
   1fr" trick instead of max-height: it tracks the content's real height
   with no fixed cap to guess at, still transitions smoothly, and needs no
   JS to measure anything. .sfB-row-expand-inner is the part that actually
   clips (min-height: 0 is required for the row track to be able to
   collapse all the way — grid items default to a min-height of their
   content otherwise); .sfB-row-expand-content carries the visible padding
   and border so those never show through when collapsed. */
.sfB-row-expand {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .3s ease;
}

.sfB-row-wrap.expanded .sfB-row-expand {
  grid-template-rows: 1fr;
}

.sfB-row-expand-inner {
  overflow: hidden;
  min-height: 0;
}

/* No boxes inside the card: that night's news, when there is any (rare),
   as one line on top (.sfB-exp-night), then the practical facts as a
   label/value sheet in two columns of rows (.sfB-exp-facts). Every value
   shares one style — only the price stands out. */
.sfB-row-expand-content {
  padding: 18px 24px 20px;
  border: 1px solid var(--sf-coral);
  border-top: none;
  border-radius: 0 0 16px 16px;
  background: rgba(255, 246, 232, 0.03);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.sfB-exp-label {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: rgba(255, 246, 232, 0.45);
}

/* That night's EventOccurrence highlight (dress code, guest teacher…). */
.sfB-exp-night {
  margin: 0;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(255, 246, 232, 0.07);
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 14px;
  line-height: 1.45;
  color: var(--sf-paper);
}

.sfB-exp-night .sfB-exp-label {
  margin-right: 10px;
  color: var(--sf-coral);
}

.sfB-exp-facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 40px;
  margin: 0;
}

.sfB-exp-row {
  display: grid;
  grid-template-columns: 84px 1fr;
  gap: 12px;
  align-items: baseline;
  padding: 10px 0;
  border-bottom: 1px solid rgba(255, 246, 232, 0.07);
}

.sfB-exp-row:last-child {
  border-bottom: none;
}

.sfB-exp-row:nth-last-child(2):nth-child(odd) {
  border-bottom: none;
}

.sfB-exp-val {
  margin: 0;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 14px;
  line-height: 1.45;
  color: rgba(255, 246, 232, 0.88);
}

.sfB-exp-val a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid rgba(93, 214, 223, 0.5);
}

.sfB-exp-val a:hover {
  color: #a8eef2;
  border-bottom-color: currentColor;
}

.sfB-exp-fee {
  font-size: 17px;
  font-weight: 700;
  color: var(--sf-gold);
}

.sfB-exp-sub {
  margin-left: 8px;
  font-size: 12px;
  color: rgba(255, 246, 232, 0.55);
}

.sfB-exp-muted {
  color: rgba(255, 246, 232, 0.7);
}

/* One program part per line (Workshop / Social, say) instead of a single
   run-on string — see program_lines in events_helper.rb. */
.sfB-exp-lines {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Mobile: one column of rows. Kept here rather than in the 960px block
   further up, which comes before the base rules above and so would lose to
   them. Padding matches .sfB-row's own mobile padding so the expanded
   content's edges line up with the card's. */
@media (max-width: 960px) {
  .sfB-row-expand-content {
    padding: 12px 16px 10px;
  }

  .sfB-exp-facts {
    grid-template-columns: 1fr;
  }

  .sfB-exp-row {
    grid-template-columns: 68px 1fr;
  }

  .sfB-exp-row:nth-last-child(2):nth-child(odd) {
    border-bottom: 1px solid rgba(255, 246, 232, 0.07);
  }
}

/* Admin-only edit button, absolutely positioned over the row so it never
   takes part in either .sfB-row's grid or .sfB-row-expand's layout — being
   signed in as admin must never change the composition a public visitor
   sees, only overlay this on top of it. Pinned to the top-right corner
   (rather than vertically centered) so its position holds steady whether
   the card is collapsed or expanded. */
.sfB-row-edit {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(26, 26, 26, 0.85);
  border: 1px solid var(--sf-coral);
  color: rgba(255, 246, 232, 0.85);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
  transition: all .18s;
}

.sfB-row-edit:hover {
  background: var(--sf-coral);
  color: #1a0d0d;
}

/* ── Poster lightbox: fullscreen view opened from a click on a row's poster
   thumbnail (see .col-poster img in schedules/_row.html.erb) ── */
.sfB-lightbox {
  display: flex;
  position: fixed;
  inset: 0;
  z-index: 9500;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease, visibility 0s linear .2s;
}

.sfB-lightbox.open {
  opacity: 1;
  visibility: visible;
  transition: opacity .2s ease;
}

.sfB-lightbox-frame {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  max-width: min(90vw, 640px);
}

.sfB-lightbox img {
  max-width: 100%;
  max-height: 90vh;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  transform: scale(.96);
  transition: transform .2s ease;
}

.sfB-lightbox.open img {
  transform: scale(1);
}

/* Shown only for a dated poster whose date has passed without a new one
   replacing it yet (see Event#poster_outdated? and main.js's openPosterLightbox) */
.sfB-lightbox-caption {
  margin: 0;
  padding: 10px 16px;
  border-radius: 8px;
  background: rgba(26, 26, 26, 0.85);
  border: 1px solid var(--sf-coral);
  color: rgba(255, 246, 232, 0.9);
  font-size: 14px;
  text-align: center;
}

.sfB-lightbox-close {
  position: fixed;
  top: 20px;
  right: 24px;
  z-index: 2;
  font-size: 20px;
  background: rgba(0, 0, 0, 0.45);
}

/* ── Playlists page ── */
.sfB-pl-section {
  margin-top: 40px;
}

.sfB-pl-section+.sfB-pl-section {
  padding-top: 32px;
  border-top: 1px solid rgba(255, 246, 232, 0.06);
}

.sfB-pl-section-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 20px;
}

.sfB-pl-title {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 48px;
  letter-spacing: -1.5px;
  line-height: 1;
}

.sfB-pl-platform-group {
  margin-bottom: 14px;
}

.sfB-pl-grid5 {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
  margin-bottom: 16px;
}

.sfB-pl-card {
  padding: 16px;
  border-radius: 16px;
  background: rgba(255, 246, 232, 0.04);
  border: 1px solid rgba(255, 246, 232, 0.08);
  display: flex;
  flex-direction: column;
  gap: 0;
  transition: all .2s;
  text-decoration: none;
  min-height: 140px;
}

.sfB-pl-card:hover {
  background: rgba(255, 246, 232, 0.07);
  transform: translateY(-3px);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}

.sfB-pl-card.spotify:hover {
  border-color: rgba(29, 185, 84, 0.5);
}

.sfB-pl-card.ytmusic:hover {
  border-color: rgba(255, 68, 68, 0.45);
}

.sfB-pl-header {
  display: flex;
  align-items: center;
  gap: 10px;
}

.sfB-pl-logo {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.sfB-pl-logo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.sfB-pl-name {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: -0.2px;
  line-height: 1.2;
  color: var(--sf-paper);
}

.sfB-pl-spacer {
  flex: 1;
}

.sfB-pl-meta {
  display: flex;
  gap: 6px;
  margin-top: 10px;
}

.sfB-pl-meta span {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.3px;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(255, 246, 232, 0.07);
  color: rgba(255, 246, 232, 0.6);
}

.sfB-pl-card.spotify .sfB-pl-meta span,
.sfB-pl-card.ytmusic .sfB-pl-meta span {
  background: rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.75);
}

.sfB-pl-card.ytmusic .sfB-pl-btn.play {
  background: rgba(255, 68, 68, 0.12);
  color: rgba(255, 68, 68, 0.9);
}

.sfB-pl-card.ytmusic .sfB-pl-btn.play:hover {
  background: rgba(255, 68, 68, 0.22);
  color: #ff4444;
}

.sfB-pl-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(255, 246, 232, 0.07);
}

.sfB-pl-tag {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 8px;
  font-weight: 500;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  padding: 4px 8px;
  border-radius: 999px;
  background: rgba(255, 246, 232, 0.07);
  color: rgba(255, 246, 232, 0.55);
}

.sfB-pl-card.spotify .sfB-pl-tag {
  background: rgba(29, 185, 84, 0.1);
  color: rgba(29, 185, 84, 0.8);
}

.sfB-pl-card.ytmusic .sfB-pl-tag {
  background: rgba(255, 68, 68, 0.1);
  color: rgba(255, 110, 110, 0.85);
}

.sfB-pl-actions {
  display: flex;
  gap: 7px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 246, 232, 0.07);
}

.sfB-pl-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 7px 10px;
  border-radius: 8px;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  cursor: pointer;
  transition: background .15s, color .15s;
  text-decoration: none;
  border: none;
  line-height: 1;
}

.sfB-pl-btn.play {
  background: rgba(29, 185, 84, 0.12);
  color: rgba(29, 185, 84, 0.9);
}

.sfB-pl-btn.play:hover {
  background: rgba(29, 185, 84, 0.22);
  color: #1db954;
}

.sfB-pl-btn.songs {
  background: rgba(255, 246, 232, 0.06);
  color: rgba(255, 246, 232, 0.5);
}

.sfB-pl-btn.songs:hover {
  background: rgba(255, 246, 232, 0.12);
  color: rgba(255, 246, 232, 0.85);
}

/* Songs modal */
.sfB-modal {
  display: flex;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9000;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease, visibility 0s linear .2s;
}

.sfB-modal.open {
  opacity: 1;
  visibility: visible;
  transition: opacity .2s ease;
}

.sfB-modal-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.72);
  backdrop-filter: blur(4px);
}

.sfB-modal-box {
  position: relative;
  z-index: 1;
  background: #1e1e1e;
  border: 1px solid rgba(255, 246, 232, 0.1);
  border-radius: 20px;
  width: min(540px, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform: scale(.96) translateY(8px);
  transition: transform .2s ease;
}

.sfB-modal.open .sfB-modal-box {
  transform: scale(1) translateY(0);
}

.sfB-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid rgba(255, 246, 232, 0.08);
  gap: 12px;
  flex-shrink: 0;
}

.sfB-modal-title-wrap {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.sfB-modal-logo {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  flex-shrink: 0;
}

.sfB-modal-head h3 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-size: 14px;
  font-weight: 700;
  color: var(--sf-paper);
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sfB-modal-close {
  background: none;
  border: none;
  color: rgba(255, 246, 232, 0.45);
  font-size: 15px;
  cursor: pointer;
  padding: 5px 8px;
  border-radius: 8px;
  transition: background .15s, color .15s;
  flex-shrink: 0;
  line-height: 1;
}

.sfB-modal-close:hover {
  background: rgba(255, 246, 232, 0.08);
  color: var(--sf-paper);
}

.sfB-modal-body {
  overflow-y: auto;
  padding: 6px 0;
  flex: 1;
}

.sfB-welcome-body {
  padding: 20px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255, 246, 232, 0.82);
}

.sfB-welcome-btn {
  align-self: flex-start;
  margin-top: 6px;
  padding: 10px 22px;
  border: none;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--sf-coral), var(--sf-orange));
  color: var(--sf-ink);
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}

.sfB-song-row {
  display: grid;
  grid-template-columns: 30px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 7px 20px;
  transition: background .1s;
}

.sfB-song-row:hover {
  background: rgba(255, 246, 232, 0.04);
}

.sfB-song-num {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 10px;
  color: rgba(255, 246, 232, 0.22);
  text-align: right;
}

.sfB-song-info {
  min-width: 0;
}

.sfB-song-name {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 13px;
  font-weight: 500;
  color: rgba(255, 246, 232, 0.88);
  white-space: normal;
  word-break: break-word;
}

.sfB-song-artist {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 11px;
  color: rgba(255, 246, 232, 0.38);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 1px;
}

.sfB-song-dur {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 10px;
  color: rgba(255, 246, 232, 0.28);
  white-space: nowrap;
}

@media (max-width: 960px) {
  .sfB-pl-grid5 {
    grid-template-columns: repeat(3, 1fr);
  }

  .sfB-pl-title {
    font-size: 36px;
  }
}

@media (max-width: 600px) {
  .sfB-pl-grid5 {
    grid-template-columns: repeat(2, 1fr);
  }

  .sfB-pl-title {
    font-size: 28px;
  }
}
/* ── Plain text pages (Privacy) ── */
.sfB-prose {
  max-width: 720px;
  font-size: 15px;
  line-height: 1.7;
  color: rgba(255, 246, 232, 0.8);
}

.sfB-prose h2 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-weight: 800;
  font-size: 22px;
  color: var(--sf-paper);
  margin: 32px 0 10px;
}

.sfB-prose p + p {
  margin-top: 12px;
}

.sfB-prose a {
  color: var(--sf-gold);
}

/* ── Home FAQ (pages/home, PagesHelper#home_faq) ── */
.sfB-faq-list {
  display: grid;
  gap: 10px;
}

.sfB-faq-item {
  border-radius: 18px;
  background: rgba(255, 246, 232, 0.04);
  border: 1px solid rgba(255, 246, 232, 0.08);
  padding: 0 20px;
}

.sfB-faq-item summary {
  cursor: pointer;
  list-style: none;
  padding: 16px 28px 16px 0;
  position: relative;
  font-weight: 700;
  font-size: 15px;
}

.sfB-faq-item summary::-webkit-details-marker {
  display: none;
}

.sfB-faq-item summary::after {
  content: "+";
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  color: var(--sf-coral);
  font-size: 20px;
  font-weight: 400;
}

.sfB-faq-item[open] summary::after {
  content: "−";
}

.sfB-faq-item p {
  padding-bottom: 16px;
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255, 246, 232, 0.7);
}

.sfB-faq-item a {
  color: var(--sf-gold);
}
