{"content_mode":"html","html":"<!doctype html>\n<html lang=\"en\" data-site-base=\"{{FYNESITE_SITE_BASE}}\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n  <meta name=\"theme-color\" content=\"#4b241f\">\n  <meta name=\"description\" content=\"Explore Dreamland Maid Caf\u00e9\u2019s confirmed La Habra roster and DreamLIVE Spotlight.\">\n  <meta name=\"apple-itunes-app\" content=\"app-id=6791316371, app-argument=https://sites.fynesite.com/dreamland-la-habra/\">\n  <link rel=\"icon\" href=\"/api/image/proxy/websites/315d5891-4d1d-46d4-a321-026b53f6f229/assets/image/dreamland/brand/bff4e13a_dreamland-mark-31a924d6192b.png\" type=\"image/png\">\n  <title>Dreamland La Habra \u2014 Roster & DreamLIVE Spotlight</title>\n  <style>\n    :root {\n      color-scheme: light;\n      --espresso: #4b241f;\n      --espresso-2: #6c332c;\n      --cream: #fff8e8;\n      --paper: #fffdf7;\n      --pink: #e9429b;\n      --pink-dark: #b91f70;\n      --pink-soft: #ffd4e9;\n      --sky: #bfe9f4;\n      --sky-dark: #1d5f6c;\n      --gold: #f5b844;\n      --mint: #bce9d1;\n      --lavender: #d8c6f0;\n      --ink: #3d2523;\n      --muted: #755f59;\n      --line: rgba(75, 36, 31, .18);\n      --shadow: 0 18px 50px rgba(75, 36, 31, .13);\n      --radius: 28px;\n      --header: 76px;\n    }\n\n    * { box-sizing: border-box; }\n    html { scroll-behavior: smooth; background: var(--cream); }\n    body {\n      margin: 0;\n      color: var(--ink);\n      background:\n        radial-gradient(circle at 7% 6%, rgba(255, 163, 206, .34), transparent 27rem),\n        radial-gradient(circle at 95% 18%, rgba(155, 221, 238, .38), transparent 29rem),\n        var(--cream);\n      font-family: ui-rounded, \"SF Pro Rounded\", \"Avenir Next\", system-ui, sans-serif;\n      min-width: 300px;\n    }\n    button, a { -webkit-tap-highlight-color: transparent; }\n    button { font: inherit; }\n    img { display: block; max-width: 100%; }\n    a { color: inherit; }\n    [hidden] { display: none !important; }\n    .sr-only {\n      border: 0;\n      clip: rect(0 0 0 0);\n      clip-path: inset(50%);\n      height: 1px;\n      margin: -1px;\n      overflow: hidden;\n      padding: 0;\n      position: absolute;\n      white-space: nowrap;\n      width: 1px;\n    }\n    :focus-visible { outline: 3px solid var(--sky-dark); outline-offset: 4px; }\n    section, footer { scroll-margin-top: calc(var(--header) + 20px); }\n\n    .site-header {\n      align-items: center;\n      backdrop-filter: blur(18px);\n      background: color-mix(in srgb, var(--cream) 88%, transparent);\n      border-bottom: 1px solid rgba(75, 36, 31, .1);\n      display: flex;\n      height: var(--header);\n      justify-content: space-between;\n      left: 0;\n      padding: 10px max(22px, calc((100vw - 1220px) / 2));\n      position: sticky;\n      right: 0;\n      top: 0;\n      z-index: 20;\n    }\n    .brand {\n      align-items: center;\n      display: inline-flex;\n      gap: 12px;\n      text-decoration: none;\n    }\n    .brand-mark {\n      flex: 0 0 48px;\n      height: 48px;\n      object-fit: contain;\n      width: 48px;\n    }\n    .brand-copy { display: block; min-width: 0; }\n    .brand-copy img { height: auto; max-width: 190px; width: 190px; }\n    .brand-copy small { color: var(--muted); display: block; font-size: 10px; letter-spacing: .12em; margin-top: 4px; text-transform: uppercase; }\n    .location-chip {\n      align-items: center;\n      background: white;\n      border: 1px solid var(--line);\n      border-radius: 999px;\n      display: inline-flex;\n      font-size: 12px;\n      font-weight: 800;\n      gap: 8px;\n      padding: 9px 13px;\n    }\n    .location-chip::before { background: var(--pink); border-radius: 50%; box-shadow: 0 0 0 4px rgba(233, 66, 155, .14); content: \"\"; height: 7px; width: 7px; }\n\n    main { overflow: clip; padding-bottom: 24px; }\n    .shell { margin: 0 auto; max-width: 1220px; padding: 0 22px; }\n    .hero {\n      display: grid;\n      gap: 44px;\n      grid-template-columns: minmax(0, 1.05fr) minmax(380px, .95fr);\n      min-height: 610px;\n      padding: 74px 0 48px;\n      position: relative;\n    }\n    .hero > * { min-width: 0; }\n    .hero::before {\n      color: rgba(233, 66, 155, .12);\n      content: \"\u2605\";\n      font-size: 360px;\n      line-height: 1;\n      pointer-events: none;\n      position: absolute;\n      right: -150px;\n      top: -40px;\n      transform: rotate(18deg);\n    }\n    .eyebrow {\n      align-items: center;\n      color: var(--pink-dark);\n      display: inline-flex;\n      font-size: 12px;\n      font-weight: 900;\n      gap: 8px;\n      letter-spacing: .12em;\n      text-transform: uppercase;\n    }\n    .eyebrow::before { background: var(--pink); border-radius: 50%; content: \"\"; height: 8px; width: 8px; }\n    h1, h2, h3, p { margin-top: 0; }\n    h1 {\n      color: var(--espresso);\n      font: 900 clamp(58px, 7.1vw, 102px)/.85 Georgia, serif;\n      letter-spacing: -.075em;\n      margin: 25px 0 28px;\n      max-width: 760px;\n    }\n    h1 em, .section-heading em { color: var(--pink); font-style: italic; position: relative; }\n    h1 em::after {\n      background: var(--sky);\n      border-radius: 50%;\n      bottom: .02em;\n      content: \"\";\n      height: .18em;\n      left: .05em;\n      opacity: .65;\n      position: absolute;\n      right: -.08em;\n      transform: rotate(-2deg);\n      z-index: -1;\n    }\n    .hero-lede { color: var(--muted); font-size: clamp(17px, 2vw, 21px); line-height: 1.6; max-width: 590px; }\n    .hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }\n    .button {\n      align-items: center;\n      border: 2px solid var(--espresso);\n      border-radius: 999px;\n      display: inline-flex;\n      font-size: 14px;\n      font-weight: 900;\n      gap: 9px;\n      justify-content: center;\n      min-height: 48px;\n      padding: 12px 19px;\n      text-decoration: none;\n      transition: transform .18s ease, box-shadow .18s ease;\n    }\n    .button:hover { transform: translateY(-2px); }\n    .button.primary { background: var(--pink-dark); box-shadow: 4px 4px 0 var(--espresso); color: white; }\n    .button.secondary { background: var(--paper); }\n\n    .planner {\n      align-self: center;\n      background: rgba(255, 253, 247, .9);\n      border: 2px solid var(--espresso);\n      border-radius: 36px;\n      box-shadow: 12px 14px 0 rgba(75, 36, 31, .1), var(--shadow);\n      padding: 24px;\n      position: relative;\n      scroll-margin-top: calc(var(--header) + 20px);\n      transform: rotate(1deg);\n      z-index: 1;\n    }\n    .planner::after {\n      background: var(--pink-soft);\n      border: 2px solid var(--espresso);\n      border-radius: 50%;\n      content: \"\u2661\";\n      display: grid;\n      font-size: 22px;\n      height: 50px;\n      place-items: center;\n      position: absolute;\n      right: -18px;\n      top: -22px;\n      transform: rotate(10deg);\n      width: 50px;\n    }\n    .planner-label { color: var(--muted); font-size: 11px; font-weight: 900; letter-spacing: .13em; text-transform: uppercase; }\n    .date-rail {\n      display: flex;\n      gap: 12px;\n      margin: 14px -4px 18px;\n      overflow-x: auto;\n      overscroll-behavior-inline: contain;\n      padding: 4px 4px 10px;\n      scroll-padding-inline: 4px;\n      scroll-snap-type: x proximity;\n      scrollbar-width: none;\n      width: 100%;\n    }\n    .date-rail::-webkit-scrollbar, .roster-grid::-webkit-scrollbar { display: none; }\n    .date-loading { color: var(--muted); font-size: 12px; padding: 22px 8px; text-align: center; }\n    .date-button {\n      align-items: center;\n      background: rgba(255,255,255,.64);\n      border: 1px solid rgba(75,36,31,.1);\n      border-radius: 18px;\n      color: var(--muted);\n      cursor: pointer;\n      display: grid;\n      flex: 0 0 84px;\n      min-height: 76px;\n      padding: 10px 8px;\n      place-content: center;\n      scroll-snap-align: start;\n      transition: background .18s, color .18s, transform .18s;\n    }\n    .date-button .mobile-weekday { display: block; font-size: 9px; font-weight: 900; letter-spacing: .08em; text-transform: uppercase; }\n    .date-button strong { display: block; font: 900 22px/1 Georgia, serif; margin-top: 5px; }\n    .date-button[aria-pressed=\"true\"] { background: var(--espresso); box-shadow: 3px 3px 0 var(--pink); color: white; transform: translateY(-2px) rotate(-2deg); }\n    .day-summary {\n      background: var(--sky);\n      border-radius: 22px;\n      min-height: 116px;\n      padding: 20px;\n      position: relative;\n    }\n    .day-summary span { color: var(--sky-dark); display: block; font-size: 11px; font-weight: 900; letter-spacing: .1em; text-transform: uppercase; }\n    .day-summary strong { color: var(--espresso); display: block; font: 900 28px/1.2 Georgia, serif; letter-spacing: -.025em; margin-top: 8px; white-space: nowrap; }\n    .day-summary p { color: var(--sky-dark); font-size: 13px; font-weight: 700; margin: 8px 0 0; }\n    .loading-line { animation: shimmer 1.2s linear infinite; background: linear-gradient(90deg, rgba(255,255,255,.3), rgba(255,255,255,.85), rgba(255,255,255,.3)); background-size: 220% 100%; border-radius: 8px; height: 18px; width: 70%; }\n\n    .data-alert {\n      align-items: flex-start;\n      background: #fff0f0;\n      border: 1px solid #e38c8c;\n      border-radius: 18px;\n      color: #7d2828;\n      display: flex;\n      gap: 12px;\n      margin: 0 auto 28px;\n      max-width: 1176px;\n      padding: 14px 16px;\n    }\n    .data-alert button { background: white; border: 1px solid currentColor; border-radius: 999px; color: inherit; cursor: pointer; font-weight: 900; margin-left: auto; min-height: 44px; padding: 8px 13px; }\n\n    .roster-section { padding: 44px 0 72px; }\n    .section-heading { align-items: end; display: flex; gap: 24px; justify-content: space-between; margin-bottom: 28px; }\n    .section-heading h2 { color: var(--espresso); font: 900 clamp(38px, 5vw, 66px)/.95 Georgia, serif; letter-spacing: -.055em; margin: 10px 0 0; }\n    .section-heading p { color: var(--muted); line-height: 1.6; margin: 0; max-width: 460px; }\n    .roster-grid { display: grid; gap: 18px; grid-template-columns: repeat(3, minmax(0, 1fr)); }\n    .roster-card {\n      background: var(--paper);\n      border: 1px solid var(--line);\n      border-radius: 26px;\n      box-shadow: 0 10px 28px rgba(75, 36, 31, .08);\n      cursor: pointer;\n      overflow: hidden;\n      padding: 0;\n      text-align: left;\n      transition: transform .2s ease, box-shadow .2s ease;\n    }\n    .roster-card:hover { box-shadow: 0 18px 34px rgba(75, 36, 31, .14); transform: translateY(-5px) rotate(-.4deg); }\n    .portrait {\n      align-items: center;\n      aspect-ratio: 16 / 10;\n      background: linear-gradient(135deg, var(--pink-soft), var(--sky));\n      display: flex;\n      justify-content: center;\n      overflow: hidden;\n      position: relative;\n    }\n    .portrait img { height: 100%; object-fit: cover; width: 100%; }\n    .portrait-fallback { color: rgba(75, 36, 31, .72); font: 900 58px/1 Georgia, serif; }\n    .shift-status { background: rgba(255,255,255,.9); border-radius: 999px; bottom: 12px; font-size: 10px; font-weight: 900; left: 12px; padding: 7px 10px; position: absolute; text-transform: uppercase; }\n    .shift-status[data-status=\"cancelled\"] { background: #fff0f0; color: #9d2c45; }\n    .shift-status[data-status=\"changed\"] { background: #fff7cf; color: #71560b; }\n    .roster-copy { padding: 18px; }\n    .roster-copy small { color: var(--pink-dark); font-size: 10px; font-weight: 900; letter-spacing: .1em; text-transform: uppercase; }\n    .roster-copy h3 { color: var(--espresso); font: 900 29px/1 Georgia, serif; margin: 8px 0 10px; }\n    .roster-copy p { color: var(--muted); font-size: 13px; margin: 0; }\n    .empty-state { background: rgba(255,255,255,.58); border: 2px dashed var(--line); border-radius: 26px; color: var(--muted); grid-column: 1 / -1; padding: 48px 24px; text-align: center; }\n    .empty-state strong { color: var(--espresso); display: block; font: 900 25px/1.2 Georgia, serif; margin-bottom: 8px; }\n\n    .jukebox-section {\n      background:\n        radial-gradient(circle at 10% 18%, rgba(233,66,155,.14) 0 2px, transparent 2.5px) 0 0 / 22px 22px,\n        linear-gradient(135deg, #fff3f7, #fff8e9 54%, #e6f7f8);\n      margin: 0 calc(50% - 50vw);\n      overflow: hidden;\n      padding: 68px max(22px, calc((100vw - 1176px) / 2)) 80px;\n      position: relative;\n    }\n    .jukebox-card {\n      align-items: center;\n      background:\n        linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px) 0 0 / 58px 100%,\n        radial-gradient(circle at 86% 18%, rgba(233,66,155,.38), transparent 34%),\n        linear-gradient(135deg, #6f285e, #451d3a 68%);\n      border: 3px solid var(--espresso);\n      border-radius: 36px;\n      box-shadow: 12px 14px 0 var(--pink), 18px 22px 38px rgba(75,36,31,.18);\n      color: white;\n      display: grid;\n      gap: 38px;\n      grid-template-columns: minmax(0, 1.2fr) minmax(210px, .55fr);\n      margin: 0 auto;\n      max-width: 1080px;\n      overflow: hidden;\n      padding: 48px 54px;\n      position: relative;\n    }\n    .jukebox-card::after { border: 1px solid rgba(255,255,255,.1); border-radius: 50%; content: \"\"; height: 330px; position: absolute; right: -160px; top: -170px; width: 330px; }\n    .jukebox-heading { max-width: 650px; position: relative; text-align: left; z-index: 1; }\n    .jukebox-heading .eyebrow { color: var(--pink-soft); }\n    .jukebox-heading h2 { font: 900 clamp(46px, 5.4vw, 72px)/.92 Georgia, serif; letter-spacing: -.055em; margin: 13px 0 15px; }\n    .jukebox-heading p { color: #f5e4ee; font-size: 16px; line-height: 1.55; margin: 0; max-width: 560px; }\n    .jukebox-heading .button { background: var(--pink); border-color: #fff8ef; box-shadow: 5px 6px 0 #2b1513; color: white; margin-top: 22px; }\n    .jukebox-preview-art { display: grid; min-height: 220px; place-items: center; position: relative; z-index: 1; }\n    .preview-record { align-items: center; animation: spin 12s linear infinite; background: repeating-radial-gradient(circle, #241321 0 7px, #39192f 8px 12px); border: 8px solid #fff7ef; border-radius: 50%; box-shadow: 10px 12px 0 rgba(43,21,19,.72), 0 0 0 3px var(--pink); display: flex; height: 192px; justify-content: center; width: 192px; }\n    .preview-record i { align-items: center; background: var(--pink); border: 5px solid var(--gold); border-radius: 50%; display: flex; font-size: 25px; font-style: normal; height: 67px; justify-content: center; width: 67px; }\n    .preview-spark { color: var(--gold); filter: drop-shadow(3px 4px 0 rgba(43,21,19,.55)); font-size: 44px; position: absolute; right: 4px; top: 12px; transform: rotate(12deg); }\n    .jukebox-stage { align-items: stretch; display: grid; gap: 42px; grid-template-columns: minmax(350px, .9fr) minmax(0, 1.1fr); margin-top: 54px; position: relative; z-index: 1; }\n    .machine {\n      background: linear-gradient(145deg, #ffeff6, #ffd0e5);\n      border: 5px solid #2b1513;\n      border-radius: 190px 190px 42px 42px;\n      box-shadow: inset 0 0 0 10px var(--gold), inset 0 0 0 15px #2b1513, 16px 20px 0 #2b1513;\n      min-height: 510px;\n      padding: 60px 42px 42px;\n      position: relative;\n    }\n    .bulbs { display: flex; justify-content: space-between; left: 45px; position: absolute; right: 45px; top: 29px; }\n    .bulbs i { animation: bulbs 1.6s ease-in-out infinite alternate; background: #fff8c9; border: 2px solid #2b1513; border-radius: 50%; box-shadow: 0 0 14px #fff1a1; height: 12px; width: 12px; }\n    .bulbs i:nth-child(2n) { animation-delay: -.8s; }\n    .record-window {\n      align-items: center;\n      background: #9bddec;\n      border: 5px solid #2b1513;\n      border-radius: 50%;\n      display: flex;\n      height: 285px;\n      justify-content: center;\n      margin: 0 auto;\n      overflow: hidden;\n      position: relative;\n      width: 285px;\n    }\n    .record-window::after { border: 2px dashed rgba(43,21,19,.3); border-radius: 50%; content: \"\"; inset: 20px; position: absolute; }\n    .record {\n      animation: spin 11s linear infinite;\n      background: repeating-radial-gradient(circle, #3c1d1d 0 6px, #562726 7px 9px);\n      border: 3px solid #2b1513;\n      border-radius: 50%;\n      display: grid;\n      height: 210px;\n      place-items: center;\n      position: relative;\n      width: 210px;\n    }\n    .record-label { align-items: center; background: var(--pink); border: 3px solid #2b1513; border-radius: 50%; color: white; display: flex; flex-direction: column; font-size: 10px; font-weight: 900; height: 76px; justify-content: center; letter-spacing: .08em; text-align: center; text-transform: uppercase; width: 76px; }\n    .record-label::after { background: #2b1513; border-radius: 50%; content: \"\"; height: 8px; margin-top: 5px; width: 8px; }\n    .equalizer { align-items: end; display: flex; gap: 7px; height: 38px; justify-content: center; margin: 27px 0 15px; }\n    .equalizer i { animation: bounce .8s ease-in-out infinite alternate; background: var(--pink); border: 2px solid #2b1513; border-radius: 8px 8px 2px 2px; height: 14px; width: 13px; }\n    .equalizer i:nth-child(2) { animation-delay: -.3s; height: 30px; }\n    .equalizer i:nth-child(3) { animation-delay: -.55s; height: 23px; }\n    .equalizer i:nth-child(4) { animation-delay: -.15s; height: 35px; }\n    .equalizer i:nth-child(5) { animation-delay: -.45s; height: 18px; }\n    .machine-caption { color: var(--espresso); font-size: 12px; font-weight: 900; letter-spacing: .11em; text-align: center; text-transform: uppercase; }\n    .setlist { align-self: center; }\n    .now-playing { border-bottom: 1px solid rgba(255,255,255,.16); padding-bottom: 26px; }\n    .set-kicker { color: var(--pink-soft); font-size: 11px; font-weight: 900; letter-spacing: .13em; text-transform: uppercase; }\n    .now-playing h3 { font: 900 clamp(38px, 4.6vw, 62px)/.96 Georgia, serif; letter-spacing: -.045em; margin: 12px 0; }\n    .now-playing p { color: #e9d6ca; font-size: 17px; }\n    .song-meta { align-items: center; display: flex; flex-wrap: wrap; gap: 9px; }\n    .song-meta span { background: rgba(255,255,255,.1); border-radius: 999px; color: white; font-size: 11px; font-weight: 800; padding: 8px 11px; }\n    .song-meta .song-status[data-status=\"cancelled\"] { background: rgba(255, 126, 149, .22); color: #ffd5de; }\n    .song-meta .song-status[data-status=\"changed\"] { background: rgba(255, 224, 123, .2); color: #fff1b5; }\n    .song-meta .song-status[data-status=\"completed\"] { background: rgba(155, 221, 236, .2); color: #c9f5ff; }\n    .track-list { display: grid; gap: 10px; margin-top: 22px; }\n    .track-button {\n      align-items: center;\n      background: transparent;\n      border: 1px solid rgba(255,255,255,.15);\n      border-radius: 18px;\n      color: white;\n      cursor: pointer;\n      display: grid;\n      gap: 13px;\n      grid-template-columns: 42px minmax(0, 1fr) auto;\n      padding: 13px;\n      text-align: left;\n      transition: background .18s, border .18s, transform .18s;\n    }\n    .track-button:hover, .track-button[aria-pressed=\"true\"] { background: rgba(233,66,155,.18); border-color: var(--pink); transform: translateX(4px); }\n    .track-number { align-items: center; background: var(--pink-dark); border-radius: 50%; display: flex; font: 900 16px/1 Georgia, serif; height: 42px; justify-content: center; width: 42px; }\n    .track-copy strong, .track-copy small { display: block; }\n    .track-copy small { color: #d8c1b5; margin-top: 3px; }\n    .track-copy .track-status { color: var(--pink-soft); font-weight: 900; text-transform: uppercase; }\n    .track-button[data-status=\"cancelled\"] { opacity: .72; }\n    .track-time { color: var(--pink-soft); font-size: 12px; font-weight: 900; }\n    .jukebox-empty { border: 2px dashed rgba(255,255,255,.2); border-radius: 24px; color: #e9d6ca; padding: 42px 24px; text-align: center; }\n    .jukebox-empty strong { color: white; display: block; font: 900 26px Georgia, serif; margin-bottom: 8px; }\n\n    .notes-section { padding: 84px 0; }\n    .notes-grid { display: grid; gap: 18px; grid-template-columns: repeat(3, minmax(0, 1fr)); }\n    .note-card { background: var(--paper); border: 1px solid var(--line); border-radius: 26px; min-height: 230px; padding: 25px; position: relative; }\n    .note-card:nth-child(3n+2) { background: #edf9fc; transform: rotate(.6deg); }\n    .note-card:nth-child(3n+3) { background: #fff0f7; transform: rotate(-.5deg); }\n    .note-label { color: var(--pink-dark); font-size: 10px; font-weight: 900; letter-spacing: .12em; text-transform: uppercase; }\n    .note-card h3 { color: var(--espresso); font: 900 24px/1.1 Georgia, serif; margin: 15px 0 12px; }\n    .note-card p { color: var(--muted); line-height: 1.65; }\n    .note-card time { bottom: 21px; color: var(--muted); font-size: 11px; font-weight: 800; position: absolute; }\n\n    .visit-section { padding: 0 0 82px; }\n    .visit-card {\n      background: linear-gradient(135deg, #c6287d, #bd2f8d 62%, #813168);\n      border: 3px solid var(--espresso);\n      border-radius: 34px;\n      box-shadow: 10px 12px 0 var(--espresso);\n      color: white;\n      display: grid;\n      gap: 34px;\n      grid-template-columns: minmax(0, 1fr) auto;\n      overflow: hidden;\n      padding: 48px;\n      position: relative;\n    }\n    .visit-card::after { color: rgba(255,255,255,.12); content: \"\u2661\"; font: 900 240px/1 Georgia, serif; position: absolute; right: -20px; top: -30px; transform: rotate(-12deg); }\n    .visit-card h2 { font: 900 clamp(42px, 5vw, 68px)/.92 Georgia, serif; letter-spacing: -.05em; margin: 12px 0 20px; position: relative; z-index: 1; }\n    .visit-card p { line-height: 1.7; position: relative; z-index: 1; }\n    .visit-actions { align-items: stretch; display: grid; gap: 10px; min-width: 300px; position: relative; z-index: 1; }\n    .visit-actions a { align-items: center; background: white; border: 2px solid var(--espresso); border-radius: 18px; color: var(--espresso); display: flex; font-size: 13px; font-weight: 900; justify-content: space-between; padding: 15px 17px; text-decoration: none; }\n    .visit-actions a:hover { background: var(--sky); }\n    .visit-card :focus-visible { outline-color: white; }\n\n    footer { align-items: center; border-top: 1px solid var(--line); color: var(--muted); display: flex; font-size: 12px; gap: 20px; justify-content: space-between; padding: 26px 0 88px; }\n    .footer-mark { flex: 0 0 42px; height: 42px; object-fit: contain; width: 42px; }\n    .footer-wordmark { height: auto; width: min(220px, 55vw); }\n    .bottom-nav { display: none; }\n\n    dialog {\n      background: var(--paper);\n      border: 2px solid var(--espresso);\n      border-radius: 30px;\n      box-shadow: var(--shadow);\n      color: var(--ink);\n      max-width: 780px;\n      padding: 0;\n      width: calc(100% - 32px);\n    }\n    dialog[data-profile-dialog][open] { display: grid; grid-template-columns: minmax(260px, .9fr) minmax(280px, 1fr); overflow: hidden; }\n    dialog::backdrop { background: rgba(43, 21, 19, .7); backdrop-filter: blur(7px); }\n    .profile-hero { align-items: end; aspect-ratio: 3 / 4; background: linear-gradient(135deg, var(--pink-soft), var(--sky)); border-right: 2px solid var(--espresso); display: grid; min-height: 0; overflow: hidden; padding: 25px; position: relative; }\n    .profile-hero img { height: 100%; inset: 0; object-fit: contain; object-position: center top; position: absolute; width: 100%; }\n    .profile-hero::after { background: linear-gradient(transparent, rgba(43,21,19,.72)); content: \"\"; inset: 0; position: absolute; }\n    .profile-title { color: white; position: relative; text-shadow: 0 2px 10px rgba(0,0,0,.3); z-index: 1; }\n    .profile-title small { font-size: 10px; font-weight: 900; letter-spacing: .12em; text-transform: uppercase; }\n    .profile-title h2 { font: 900 42px/1 Georgia, serif; margin: 7px 0 0; }\n    .profile-body { align-content: center; display: grid; gap: 18px; padding: 30px; }\n    .profile-kicker { color: var(--pink-dark); font-size: 10px; font-weight: 900; letter-spacing: .14em; text-transform: uppercase; }\n    .profile-facts { display: grid; gap: 10px; grid-template-columns: repeat(2, minmax(0, 1fr)); }\n    .profile-fact { background: #fff1f7; border-radius: 16px; min-width: 0; padding: 13px; }\n    .profile-fact small, .profile-fact strong { display: block; }\n    .profile-fact small { color: var(--muted); font-size: 9px; font-weight: 900; letter-spacing: .1em; text-transform: uppercase; }\n    .profile-fact strong { color: var(--espresso); font-size: 15px; margin-top: 5px; overflow-wrap: anywhere; }\n    .profile-body p { color: var(--muted); line-height: 1.65; margin: 0; }\n    .profile-body .button { justify-self: start; }\n    .dialog-close { background: white; border: 2px solid var(--espresso); border-radius: 50%; cursor: pointer; font-size: 18px; height: 44px; position: absolute; right: 14px; top: 14px; width: 44px; z-index: 2; }\n\n    @keyframes spin { to { transform: rotate(360deg); } }\n    @keyframes bounce { to { height: 38px; } }\n    @keyframes bulbs { to { background: var(--pink); box-shadow: 0 0 17px var(--pink); } }\n    @keyframes shimmer { to { background-position: -120% 0; } }\n\n    @media (max-width: 900px) {\n      .hero { gap: 30px; grid-template-columns: 1fr; padding-top: 52px; }\n      .hero-lede { max-width: 650px; }\n      .planner { margin: 0 auto; max-width: 620px; transform: none; width: 100%; }\n      .roster-grid { display: flex; gap: 16px; margin: 0 -22px; overflow-x: auto; padding: 2px 22px 16px; scroll-padding-inline: 22px; scroll-snap-type: x mandatory; }\n      .roster-card { flex: 0 0 min(42vw, 290px); scroll-snap-align: start; }\n      .notes-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n      .jukebox-card { grid-template-columns: minmax(0, 1fr) 190px; padding: 44px 38px; }\n      .preview-record { height: 164px; width: 164px; }\n      .jukebox-stage { grid-template-columns: 1fr; }\n      .machine { justify-self: center; max-width: 470px; width: 100%; }\n      .visit-card { grid-template-columns: 1fr; }\n      .visit-actions { min-width: 0; }\n    }\n\n    @media (max-width: 620px) {\n      :root { --header: 66px; }\n      dialog[data-profile-dialog][open] { display: block; max-height: 90svh; overflow: auto; }\n      .profile-hero { border-right: 0; border-bottom: 2px solid var(--espresso); max-height: 58svh; }\n      .site-header { height: 72px; padding: 10px 15px; }\n      .brand { gap: 8px; min-width: 0; }\n      .brand-mark { flex: 0 0 40px; height: 40px; width: 40px; }\n      .brand-copy img { width: min(176px, 48vw); }\n      .brand-copy small { display: none; }\n      .location-chip { flex: 0 0 auto; font-size: 9px; padding: 7px 9px; white-space: nowrap; }\n      .shell { padding: 0 15px; }\n      .hero { min-height: 0; padding: 31px 0 30px; }\n      .hero::before { display: none; }\n      h1 { font-size: clamp(40px, 11.8vw, 50px); line-height: .88; margin: 17px 0 18px; }\n      h1 em { white-space: nowrap; }\n      .hero-lede { font-size: 17px; line-height: 1.45; margin-bottom: 0; }\n      .hero-actions { display: none; }\n      .planner { border-radius: 28px; max-width: 100%; min-width: 0; padding: 16px; }\n      .date-rail { gap: 10px; margin-right: -18px; padding-right: 18px; }\n      .date-button { flex-basis: 74px; min-height: 74px; }\n      .day-summary { min-height: 104px; padding: 17px; }\n      .day-summary strong { font-size: clamp(20px, 6.2vw, 24px); letter-spacing: -.045em; margin-top: 7px; }\n      .section-heading { align-items: start; flex-direction: column; }\n      .roster-grid { gap: 14px; margin: 0 -15px; padding: 2px 15px 14px; scroll-padding-inline: 15px; }\n      .roster-card { flex-basis: min(78vw, 300px); }\n      .notes-grid { grid-template-columns: 1fr; }\n      .profile-body { gap: 15px; padding: 24px 20px 28px; }\n      .profile-body .button { justify-self: stretch; }\n      .roster-section { padding: 34px 0 55px; }\n      .notes-section { padding: 48px 0 96px; }\n      .jukebox-section { padding: 52px 16px 64px; }\n      .jukebox-card { border-radius: 28px; gap: 24px; grid-template-columns: 1fr; padding: 34px 25px 38px; text-align: center; }\n      .jukebox-heading { text-align: center; }\n      .jukebox-heading p { font-size: 14px; }\n      .jukebox-heading .button { width: 100%; }\n      .jukebox-preview-art { min-height: 132px; order: -1; }\n      .preview-record { border-width: 6px; height: 118px; width: 118px; }\n      .preview-record i { border-width: 3px; font-size: 18px; height: 44px; width: 44px; }\n      .preview-spark { font-size: 30px; right: calc(50% - 85px); top: -3px; }\n      .jukebox-stage { gap: 34px; margin-top: 38px; }\n      .machine { border-radius: 150px 150px 34px 34px; min-height: 440px; padding: 52px 27px 30px; }\n      .record-window { height: 240px; width: 240px; }\n      .record { height: 174px; width: 174px; }\n      .track-button { grid-template-columns: 38px minmax(0, 1fr); }\n      .track-time { grid-column: 2; }\n      .visit-card { padding: 34px 25px; }\n      footer { align-items: flex-start; flex-direction: column; padding-bottom: 112px; }\n      .bottom-nav {\n        background: rgba(255, 253, 247, .96);\n        border: 1px solid rgba(75, 36, 31, .18);\n        border-radius: 24px;\n        bottom: max(8px, env(safe-area-inset-bottom));\n        box-shadow: 0 12px 40px rgba(75, 36, 31, .2);\n        display: grid;\n        grid-template-columns: repeat(3, 1fr);\n        left: 50%;\n        margin: 0;\n        padding: 6px;\n        position: fixed;\n        transform: translateX(-50%);\n        width: min(460px, calc(100% - 22px));\n        z-index: 30;\n      }\n      .bottom-nav a { align-items: center; border-radius: 18px; color: var(--muted); display: grid; font-size: 12px; font-weight: 900; min-height: 50px; padding: 4px; text-align: center; text-decoration: none; text-transform: none; }\n      .bottom-nav a span { display: none; }\n      .bottom-nav a[aria-current=\"page\"] { background: var(--pink-soft); box-shadow: inset 0 0 0 1px #f2a8ce; color: var(--pink-dark); }\n    }\n\n    @media (prefers-reduced-motion: reduce) {\n      html { scroll-behavior: auto; }\n      *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; transition-duration: .001ms !important; }\n      .record { transform: none; }\n      .button:hover,\n      .date-button[aria-pressed=\"true\"],\n      .roster-card:hover,\n      .track-button:hover,\n      .track-button[aria-pressed=\"true\"] { transform: none; }\n    }\n    .jukebox-section :focus-visible { outline-color: var(--gold); }\n  </style>\n</head>\n<body>\n  <header class=\"site-header\">\n    <a class=\"brand\" href=\"#home\" aria-label=\"Dreamland La Habra home\">\n      <span class=\"brand-copy\"><img src=\"/api/image/proxy/websites/315d5891-4d1d-46d4-a321-026b53f6f229/assets/image/dreamland/brand/76171fd8_dreamland-anime-cafe-wordmark-cbc912840df6.png\" alt=\"Dreamland Anime Cafe\" width=\"2827\" height=\"346\"></span>\n    </a>\n    <span class=\"location-chip\">La Habra \u00b7 CA</span>\n  </header>\n\n  <main id=\"home\">\n    <div class=\"shell\">\n      <section class=\"hero\" aria-labelledby=\"hero-title\">\n        <div>\n          <span class=\"eyebrow\">Confirmed mansion guide</span>\n          <h1 id=\"hero-title\">Make it a <em>Dreamland day!</em></h1>\n          <p class=\"hero-lede\">Choose a confirmed date and meet the maids welcoming guests during caf\u00e9 hours.</p>\n          <div class=\"hero-actions\">\n            <a class=\"button primary\" href=\"#roster\">See the roster <span aria-hidden=\"true\">\u2193</span></a>\n            <a class=\"button secondary\" href=\"jukebox\" data-spotlight-link>Open DreamLIVE <span aria-hidden=\"true\">\u266a</span></a>\n          </div>\n        </div>\n\n        <div class=\"planner\" id=\"schedule\" aria-label=\"Choose a visit date\">\n          <span class=\"planner-label\">Confirmed schedule \u00b7 next 30 days</span>\n          <div class=\"date-rail\" data-date-rail role=\"group\" aria-label=\"Choose a confirmed date\">\n            <span class=\"date-loading\">Checking confirmed dates\u2026</span>\n          </div>\n          <div class=\"day-summary\" data-day-summary>\n            <span>Loading the mansion schedule</span>\n            <div class=\"loading-line\" aria-hidden=\"true\"></div>\n            <p>Please wait a little moment.</p>\n          </div>\n        </div>\n      </section>\n    </div>\n\n    <div class=\"data-alert\" data-data-alert role=\"alert\" hidden>\n      <span aria-hidden=\"true\">\u2726</span>\n      <span><strong>We couldn\u2019t reach the mansion schedule.</strong><br>Try again for the latest confirmed roster and setlist.</span>\n      <button type=\"button\" data-retry>Try again</button>\n    </div>\n    <p class=\"sr-only\" data-selection-announcement aria-live=\"polite\" aria-atomic=\"true\"></p>\n\n    <div class=\"shell\">\n      <section class=\"roster-section\" id=\"roster\" aria-labelledby=\"roster-title\">\n        <div class=\"section-heading\">\n          <div><span class=\"eyebrow\">Selected day at Dreamland</span><h2 id=\"roster-title\">Meet your <em>maids.</em></h2></div>\n          <p>The roster follows the confirmed date above. Only confirmed roster assignments appear here.</p>\n        </div>\n        <div class=\"roster-grid\" data-roster-state>\n          <div class=\"empty-state\"><strong>Loading the roster\u2026</strong><span>Polishing the name cards.</span></div>\n        </div>\n      </section>\n    </div>\n\n    <section class=\"jukebox-section\" id=\"jukebox\" aria-labelledby=\"jukebox-title\">\n      <div class=\"jukebox-card\">\n        <div class=\"jukebox-heading\">\n          <span class=\"eyebrow\">DreamLIVE Jukebox</span>\n          <h2 id=\"jukebox-title\">Dance <em>repertoire.</em></h2>\n          <p>See what each maid can dance, then open DreamLIVE to choose your Oshi and send a cheer.</p>\n          <a class=\"button\" href=\"jukebox\" data-spotlight-link>Open DreamLIVE <span aria-hidden=\"true\">\u2192</span></a>\n        </div>\n        <div class=\"jukebox-preview-art\" aria-hidden=\"true\">\n          <div class=\"preview-record\"><i>\u266a</i></div>\n          <span class=\"preview-spark\">\u2726</span>\n        </div>\n      </div>\n    </section>\n\n    <div class=\"shell\">\n      <section class=\"notes-section\" id=\"notes\" aria-labelledby=\"notes-title\">\n        <div class=\"section-heading\">\n          <div><span class=\"eyebrow\">From the mansion</span><h2 id=\"notes-title\">Official <em>messages.</em></h2></div>\n          <p>The Dreamland team shares schedule changes and announcements here.</p>\n        </div>\n        <div class=\"notes-grid\" data-notes-state>\n          <div class=\"empty-state\"><strong>Loading official notes\u2026</strong></div>\n        </div>\n      </section>\n\n      <section class=\"visit-section\" id=\"visit\" aria-labelledby=\"visit-title\">\n        <div class=\"visit-card\">\n          <div>\n            <span class=\"eyebrow\" style=\"color:#fff\">Ready when you are</span>\n            <h2 id=\"visit-title\">Make it a<br>Dreamland day.</h2>\n            <p>1281 E La Habra Blvd, Unit 6<br>La Habra, CA 90631</p>\n          </div>\n          <div class=\"visit-actions\">\n            <a href=\"https://www.dreamlandmaidcafe.com/\" target=\"_blank\" rel=\"noreferrer\">Official website <span aria-hidden=\"true\">\u2197</span></a>\n            <a href=\"https://maps.google.com/?q=1281+E+La+Habra+Blvd+Unit+6+La+Habra+CA+90631\" target=\"_blank\" rel=\"noreferrer\">Open in maps <span aria-hidden=\"true\">\u2197</span></a>\n          </div>\n        </div>\n      </section>\n\n      <footer>\n        <img class=\"footer-mark\" src=\"/api/image/proxy/websites/315d5891-4d1d-46d4-a321-026b53f6f229/assets/image/dreamland/brand/bff4e13a_dreamland-mark-31a924d6192b.png\" alt=\"\" width=\"1080\" height=\"1080\" loading=\"lazy\">\n        <img class=\"footer-wordmark\" src=\"/api/image/proxy/websites/315d5891-4d1d-46d4-a321-026b53f6f229/assets/image/dreamland/brand/76171fd8_dreamland-anime-cafe-wordmark-cbc912840df6.png\" alt=\"Dreamland Anime Cafe\" width=\"2827\" height=\"346\" loading=\"lazy\">\n        <span>Dreamland confirms its schedule, roster, and messages here \u00b7 <a href=\"https://www.dreamlandmaidcafe.com/\" target=\"_blank\" rel=\"noreferrer\">Official website \u2197</a></span>\n      </footer>\n    </div>\n  </main>\n\n  <nav class=\"bottom-nav\" aria-label=\"Dreamland app\">\n    <a href=\"#schedule\" aria-current=\"page\">Schedule</a>\n    <a href=\"jukebox\">DreamLIVE</a>\n    <a href=\"#notes\">Messages</a>\n  </nav>\n\n  <dialog data-profile-dialog aria-labelledby=\"profile-name\">\n    <button class=\"dialog-close\" type=\"button\" data-profile-close aria-label=\"Close maid profile\">\u00d7</button>\n    <div class=\"profile-hero\" data-profile-hero>\n      <div class=\"profile-title\"><small data-profile-role>Maid</small><h2 id=\"profile-name\" data-profile-name>Dreamland maid</h2></div>\n    </div>\n    <div class=\"profile-body\">\n      <span class=\"profile-kicker\">Meet your maid</span>\n      <div class=\"profile-facts\">\n        <div class=\"profile-fact\"><small>Cafe rank</small><strong data-profile-rank>Coming soon</strong></div>\n        <div class=\"profile-fact\"><small>Birthday</small><strong data-profile-birthday>Coming soon</strong></div>\n      </div>\n      <p data-profile-copy>Profile details are coming soon.</p>\n      <button class=\"button secondary\" type=\"button\" data-profile-done>Back to roster</button>\n    </div>\n  </dialog>\n\n  <script>\n    (() => {\n      'use strict';\n\n      const TEMPLATE_KEYS = ['performers', 'events', 'shifts', 'featured-songs', 'repertoire', 'official-notes'];\n      const windowStart = new Date();\n      windowStart.setHours(12, 0, 0, 0);\n      const windowMid = new Date(windowStart);\n      windowMid.setDate(windowMid.getDate() + 30);\n      const windowNext = new Date(windowStart);\n      windowNext.setDate(windowNext.getDate() + 31);\n      const windowEnd = new Date(windowStart);\n      windowEnd.setDate(windowEnd.getDate() + 60);\n      const DATE_START = windowStart.toISOString().slice(0, 10);\n      const DATE_MID = windowMid.toISOString().slice(0, 10);\n      const DATE_NEXT = windowNext.toISOString().slice(0, 10);\n      const DATE_END = windowEnd.toISOString().slice(0, 10);\n      const state = {\n        selectedDate: null,\n        selectedSongId: null,\n        data: Object.fromEntries(TEMPLATE_KEYS.map((key) => [key, []])),\n      };\n\n      const $ = (selector, root = document) => root.querySelector(selector);\n      const $$ = (selector, root = document) => Array.from(root.querySelectorAll(selector));\n      const safeText = (value) => String(value == null ? '' : value);\n      const escapeHtml = (value) => safeText(value).replace(/[&<>\"']/g, (character) => ({\n        '&': '&amp;',\n        '<': '&lt;',\n        '>': '&gt;',\n        '\"': '&quot;',\n        \"'\": '&#39;',\n      })[character]);\n      const itemData = (item) => ({ id: item.id, public_revision: item.public_revision, ...(item.data || {}) });\n\n      function siteBase() {\n        const declared = document.documentElement.dataset.siteBase || '';\n        if (declared && !declared.includes('{{')) return declared.replace(/\\/$/, '');\n        const parts = location.pathname.split('/').filter(Boolean);\n        if (location.hostname.startsWith('sites.') && parts[0]) return `/${parts[0]}`;\n        if (parts[0] === 'sites' && parts[1]) return `/sites/${parts[1]}`;\n        return '';\n      }\n\n      function dataUrls(templateKey) {\n        const base = `${siteBase()}/_apps/jukebox/data/${encodeURIComponent(templateKey)}`;\n        if (!['events', 'shifts', 'featured-songs'].includes(templateKey)) return [base];\n        return [\n          new URLSearchParams({ from: DATE_START, to: DATE_MID }),\n          new URLSearchParams({ from: DATE_NEXT, to: DATE_END }),\n        ].map((params) => `${base}?${params}`);\n      }\n\n      function formatTime(value) {\n        if (!value) return '';\n        const raw = safeText(value);\n        const timePart = raw.includes('T') ? raw.split('T')[1].slice(0, 5) : raw.slice(0, 5);\n        const [rawHour, rawMinute = '00'] = timePart.split(':');\n        const hour = Number(rawHour);\n        if (!Number.isFinite(hour)) return safeText(value);\n        const suffix = hour >= 12 ? 'PM' : 'AM';\n        const display = hour % 12 || 12;\n        return `${display}${rawMinute === '00' ? '' : `:${rawMinute}`} ${suffix}`;\n      }\n\n      function customerHours(event) {\n        if (event?.status === 'closed') return 'Closed';\n        return '11 AM\u20133 PM \u00b7 5\u20139 PM';\n      }\n\n      function shiftMinutes(value) {\n        const match = safeText(value).match(/T(\\d{2}):(\\d{2})/);\n        return match ? (Number(match[1]) * 60) + Number(match[2]) : NaN;\n      }\n\n      function formatMinutes(minutes) {\n        const hour = Math.floor(minutes / 60);\n        const minute = minutes % 60;\n        return formatTime(`T${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`);\n      }\n\n      function guestShiftHours(shift, event) {\n        const start = shiftMinutes(shift?.starts_at);\n        const end = shiftMinutes(shift?.ends_at);\n        if (!Number.isFinite(start) || !Number.isFinite(end) || end <= start) return customerHours(event);\n        return [[11 * 60, 15 * 60], [17 * 60, 21 * 60]]\n          .map(([windowStart, windowEnd]) => [Math.max(start, windowStart), Math.min(end, windowEnd)])\n          .filter(([segmentStart, segmentEnd]) => segmentEnd > segmentStart)\n          .map(([segmentStart, segmentEnd]) => `${formatMinutes(segmentStart)}\u2013${formatMinutes(segmentEnd)}`)\n          .join(' \u00b7 ');\n      }\n\n      function formatDate(value) {\n        if (!value) return 'No confirmed date selected';\n        const parsed = new Date(`${value}T12:00:00`);\n        return new Intl.DateTimeFormat('en-US', { weekday: 'long', month: 'long', day: 'numeric' }).format(parsed);\n      }\n\n      function performerMap() {\n        return new Map(state.data.performers.map((performer) => [performer.id, performer]));\n      }\n\n      function selectedEvents() {\n        if (!state.selectedDate) return [];\n        return state.data.events.filter((event) => event.date === state.selectedDate);\n      }\n\n      function selectedEvent() {\n        const events = selectedEvents();\n        const shiftCounts = new Map(events.map((event) => [event.id, state.data.shifts.filter((shift) => shift.event_id === event.id).length]));\n        return events.sort((left, right) => (\n          Number(['cancelled', 'closed'].includes(left.status)) - Number(['cancelled', 'closed'].includes(right.status))\n          || (shiftCounts.get(right.id) || 0) - (shiftCounts.get(left.id) || 0)\n          || Number(Boolean(right.spotlight_key)) - Number(Boolean(left.spotlight_key))\n        ))[0] || null;\n      }\n\n      function renderDateRail() {\n        const rail = $('[data-date-rail]');\n        const events = state.data.events\n          .filter((event) => /^\\d{4}-\\d{2}-\\d{2}$/.test(event.date || ''))\n          .sort((left, right) => left.date.localeCompare(right.date));\n        const uniqueDates = [...new Set(events.map((event) => event.date))];\n        if (!uniqueDates.includes(state.selectedDate)) {\n          state.selectedDate = uniqueDates[0] || null;\n          state.selectedSongId = null;\n        }\n        rail.replaceChildren();\n        if (!uniqueDates.length) {\n          const empty = document.createElement('span');\n          empty.className = 'date-loading';\n          empty.textContent = 'No confirmed dates yet. Check back when the mansion shares its schedule.';\n          rail.append(empty);\n          return;\n        }\n        uniqueDates.forEach((date) => {\n          const parsed = new Date(`${date}T12:00:00`);\n          const button = document.createElement('button');\n          button.type = 'button';\n          button.className = 'date-button';\n          button.dataset.date = date;\n          button.setAttribute('aria-label', formatDate(date));\n          button.setAttribute('aria-pressed', String(date === state.selectedDate));\n          const weekday = document.createElement('span');\n          weekday.className = 'mobile-weekday';\n          weekday.textContent = new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format(parsed);\n          const day = document.createElement('strong');\n          day.textContent = new Intl.DateTimeFormat('en-US', { day: 'numeric' }).format(parsed);\n          button.append(weekday, day);\n          button.addEventListener('click', () => {\n            state.selectedDate = date;\n            state.selectedSongId = null;\n            renderAll();\n            const selected = [...document.querySelectorAll('[data-date]')].find((candidate) => candidate.dataset.date === date);\n            selected?.focus({ preventScroll: true });\n            if (typeof selected?.scrollIntoView === 'function') selected.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });\n          });\n          rail.append(button);\n        });\n      }\n\n      function renderSpotlightLinks() {\n        const params = new URLSearchParams();\n        const key = selectedEvents().find((event) => /^[a-z0-9-]{1,40}$/i.test(event.spotlight_key || ''))?.spotlight_key;\n        if (/^[a-z0-9-]{1,40}$/i.test(key || '')) params.set('shift', key);\n        const query = params.toString();\n        const href = `${siteBase()}/jukebox${query ? `?${query}` : ''}`;\n        $$('[data-spotlight-link]').forEach((link) => { link.href = href; });\n      }\n\n      function renderSummary() {\n        const container = $('[data-day-summary]');\n        const event = selectedEvent();\n        if (!event) {\n          container.innerHTML = '<span>Confirmed schedule</span><strong>No date announced</strong><p>Check back when Dreamland shares its confirmed mansion schedule.</p>';\n          return;\n        }\n        const announcedHours = customerHours(event);\n        const hours = event.status === 'cancelled'\n          ? 'Schedule cancelled'\n          : event.status === 'closed'\n            ? 'Closed'\n            : event.status === 'changed'\n              ? `Schedule changed \u00b7 ${announcedHours}`\n              : announcedHours;\n        container.innerHTML = `<span>Caf\u00e9 hours</span><strong>${escapeHtml(hours)}</strong>`;\n      }\n\n      function profileButton(performer, shift) {\n        const button = document.createElement('button');\n        button.type = 'button';\n        button.className = 'roster-card';\n        button.dataset.performerId = performer.id;\n        const portrait = document.createElement('div');\n        portrait.className = 'portrait';\n        if (performer.portrait_url) {\n          const img = document.createElement('img');\n          img.src = performer.portrait_url;\n          img.alt = performer.portrait_alt || `${performer.stage_name}, ${performer.role || 'Dreamland maid'}`;\n          img.loading = 'lazy';\n          portrait.append(img);\n        } else {\n          const fallback = document.createElement('span');\n          fallback.className = 'portrait-fallback';\n          fallback.textContent = (performer.stage_name || '?').slice(0, 1).toUpperCase();\n          portrait.append(fallback);\n        }\n        const status = document.createElement('span');\n        status.className = 'shift-status';\n        status.dataset.status = shift.status || 'scheduled';\n        status.textContent = shift.status === 'cancelled'\n          ? 'Cancelled shift'\n          : shift.status === 'changed'\n            ? 'Changed shift'\n            : 'On the roster';\n        portrait.append(status);\n        const copy = document.createElement('div');\n        copy.className = 'roster-copy';\n        const role = document.createElement('small');\n        role.textContent = performer.role || 'Dreamland maid';\n        const name = document.createElement('h3');\n        name.dataset.rosterName = '';\n        name.textContent = performer.stage_name || 'Dreamland maid';\n        const time = document.createElement('p');\n        time.textContent = `${formatDate(selectedEvent()?.date)} \u00b7 ${guestShiftHours(shift, selectedEvent())}`;\n        copy.append(role, name, time);\n        button.append(portrait, copy);\n        button.addEventListener('click', () => openProfile(performer));\n        return button;\n      }\n\n      function renderRoster() {\n        const container = $('[data-roster-state]');\n        const event = selectedEvent();\n        if (event?.status === 'cancelled' || event?.status === 'closed') {\n          const empty = document.createElement('div');\n          empty.className = 'empty-state';\n          empty.innerHTML = event.status === 'cancelled'\n            ? '<strong>This date was cancelled.</strong><span>No roster is active for this date.</span>'\n            : '<strong>This date is closed.</strong><span>The roster is no longer active.</span>';\n          container.replaceChildren(empty);\n          return;\n        }\n        const eventIds = new Set(selectedEvents().filter((item) => !['cancelled', 'closed'].includes(item.status)).map((item) => item.id));\n        const shiftsByPerformer = new Map();\n        state.data.shifts.filter((shift) => eventIds.has(shift.event_id) && shift.status !== 'cancelled').forEach((shift) => {\n          if (!guestShiftHours(shift, event)) return;\n          const current = shiftsByPerformer.get(shift.performer_id);\n          const duration = shiftMinutes(shift.ends_at) - shiftMinutes(shift.starts_at);\n          const currentDuration = current ? shiftMinutes(current.ends_at) - shiftMinutes(current.starts_at) : -1;\n          if (!current || duration > currentDuration) shiftsByPerformer.set(shift.performer_id, shift);\n        });\n        const shifts = [...shiftsByPerformer.values()].sort((left, right) => Number(left.sort_order || 0) - Number(right.sort_order || 0));\n        const people = performerMap();\n        container.replaceChildren();\n        const cards = shifts.map((shift) => {\n          const performer = people.get(shift.performer_id);\n          return performer && performer.active !== false ? profileButton(performer, shift) : null;\n        }).filter(Boolean);\n        if (!cards.length) {\n          const empty = document.createElement('div');\n          empty.className = 'empty-state';\n          empty.innerHTML = '<strong>No maids announced for this day yet.</strong><span>The confirmed roster will appear here.</span>';\n          container.append(empty);\n          return;\n        }\n        container.append(...cards);\n      }\n\n      function renderNotes() {\n        const container = $('[data-notes-state]');\n        const notes = state.data['official-notes'].filter((note) => note.active !== false).slice(0, 50);\n        container.replaceChildren();\n        if (!notes.length) {\n          const empty = document.createElement('div');\n          empty.className = 'empty-state';\n          empty.innerHTML = '<strong>No official notes right now.</strong><span>Schedule updates will appear here.</span>';\n          container.append(empty);\n          return;\n        }\n        notes.forEach((note) => {\n          const article = document.createElement('article');\n          article.className = 'note-card';\n          const label = document.createElement('span');\n          label.className = 'note-label';\n          label.textContent = note.label || 'Official update';\n          const title = document.createElement('h3');\n          title.textContent = note.title || 'Dreamland update';\n          const body = document.createElement('p');\n          body.textContent = note.body || '';\n          const time = document.createElement('time');\n          time.dateTime = note.published_on || '';\n          time.textContent = note.published_on ? formatDate(note.published_on) : '';\n          article.append(label, title, body, time);\n          container.append(article);\n        });\n      }\n\n      function renderSelectionAnnouncement() {\n        const container = $('[data-selection-announcement]');\n        const event = selectedEvent();\n        if (!state.selectedDate) {\n          container.textContent = 'No confirmed mansion dates are available yet.';\n          return;\n        }\n        const dateLabel = formatDate(state.selectedDate);\n        if (!event) {\n          container.textContent = `${dateLabel}. Schedule not announced. 0 maids, 0 performances.`;\n          return;\n        }\n        if (event.status === 'cancelled' || event.status === 'closed') {\n          const status = event.status === 'cancelled' ? 'Schedule cancelled' : 'Closed';\n          container.textContent = `${dateLabel}. ${status}. 0 maids, 0 performances.`;\n          return;\n        }\n        const people = performerMap();\n        const eventIds = new Set(selectedEvents().filter((item) => !['cancelled', 'closed'].includes(item.status)).map((item) => item.id));\n        const performerIds = [...new Set(state.data.shifts.filter((shift) => eventIds.has(shift.event_id) && guestShiftHours(shift, event)).map((shift) => shift.performer_id))];\n        const maidCount = performerIds.filter((id) => people.get(id)?.active !== false).length;\n        const performanceCount = state.data.repertoire.filter((song) => Array.isArray(song.performer_ids) && song.performer_ids.some((id) => performerIds.includes(id))).length;\n        const status = event.status === 'changed' ? 'Schedule changed. ' : '';\n        container.textContent = `${dateLabel}. ${status}${maidCount} ${maidCount === 1 ? 'maid' : 'maids'}, ${performanceCount} available ${performanceCount === 1 ? 'dance' : 'dances'}.`;\n      }\n\n      function renderAll() {\n        renderDateRail();\n        renderSpotlightLinks();\n        renderSummary();\n        renderRoster();\n        renderNotes();\n        renderSelectionAnnouncement();\n      }\n\n      function openProfile(performer) {\n        const dialog = $('[data-profile-dialog]');\n        $('[data-profile-name]').textContent = performer.stage_name || 'Dreamland maid';\n        $('[data-profile-role]').textContent = performer.role || 'Dreamland maid';\n        const rawCopy = String(performer.bio || performer.tagline || '').trim();\n        const numericRank = Number(performer.star_level || performer.cafe_rank || rawCopy.match(/Cafe rank\\s+(\\d+)/i)?.[1]);\n        const existingStars = rawCopy.match(/\u2605/g)?.length || 0;\n        const starCount = Math.min(5, Math.max(0, Math.floor(numericRank || existingStars)));\n        const birthday = performer.birthday || rawCopy.match(/Birthday:\\s*([^.]*)/i)?.[1]?.trim() || 'Coming soon';\n        const profileCopy = rawCopy\n          .replace(/Cafe rank[^.]*\\.?/ig, '')\n          .replace(/Birthday:\\s*[^.]*\\.?/ig, '')\n          .replace(/\\s{2,}/g, ' ')\n          .trim();\n        $('[data-profile-rank]').textContent = starCount ? Array(starCount).fill('\u2605').join(' ') : 'Coming soon';\n        $('[data-profile-birthday]').textContent = birthday;\n        $('[data-profile-copy]').textContent = profileCopy || (performer.tagline && !/^Official Dreamland Maid Cafe cast profile$/i.test(performer.tagline) ? performer.tagline : 'Profile details are coming soon.');\n        const hero = $('[data-profile-hero]');\n        $('img', hero)?.remove();\n        if (performer.portrait_url) {\n          const img = document.createElement('img');\n          img.src = performer.portrait_url;\n          img.alt = performer.portrait_alt || '';\n          hero.prepend(img);\n        }\n        dialog.showModal();\n      }\n\n      async function loadData() {\n        $('[data-data-alert]').hidden = true;\n        try {\n          const requests = TEMPLATE_KEYS.flatMap((key) => dataUrls(key).map((url) => ({ key, url })));\n          const payloads = await Promise.all(requests.map(async ({ key, url }) => {\n            const response = await fetch(url, { headers: { Accept: 'application/json' }, credentials: 'same-origin' });\n            if (!response.ok) throw new Error(`Schedule request failed (${response.status})`);\n            return [key, await response.json()];\n          }));\n          state.data = Object.fromEntries(TEMPLATE_KEYS.map((key) => [key, []]));\n          payloads.forEach(([key, payload]) => {\n            const items = Array.isArray(payload?.items) ? payload.items : [];\n            const byId = new Map(state.data[key].map((item) => [item.id, item]));\n            items.map(itemData).forEach((item) => byId.set(item.id, item));\n            state.data[key] = [...byId.values()];\n          });\n          renderAll();\n        } catch (error) {\n          console.error('[Dreamland] Could not load live site data', error);\n          $('[data-data-alert]').hidden = false;\n          state.data = Object.fromEntries(TEMPLATE_KEYS.map((key) => [key, []]));\n          renderAll();\n        }\n      }\n\n      $('[data-retry]').addEventListener('click', loadData);\n      $('[data-profile-close]').addEventListener('click', () => $('[data-profile-dialog]').close());\n      $('[data-profile-done]').addEventListener('click', () => $('[data-profile-dialog]').close());\n      $('[data-profile-dialog]').addEventListener('click', (event) => {\n        if (event.target === event.currentTarget) event.currentTarget.close();\n      });\n\n      const navLinks = $$('.bottom-nav a');\n      if ('IntersectionObserver' in window) {\n        const observer = new IntersectionObserver((entries) => {\n          const visible = entries.filter((entry) => entry.isIntersecting).sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0];\n          if (!visible) return;\n          navLinks.forEach((link) => link.toggleAttribute('aria-current', link.getAttribute('href') === `#${visible.target.id}`));\n        }, { rootMargin: '-25% 0px -60%', threshold: [0, .2, .6] });\n        ['schedule', 'jukebox', 'notes'].forEach((id) => { const element = document.getElementById(id); if (element) observer.observe(element); });\n      }\n\n      loadData();\n    })();\n  </script>\n</body>\n</html>\n"}
