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

/* Keyboard-accessibility skip link: invisible until focused via Tab. */
.skip-link { position: absolute; left: -9999px; top: 0; z-index: 10001; background: var(--gold); color: #000; font-family: 'Bebas Neue', sans-serif; font-size: 14px; letter-spacing: 1px; padding: 8px 14px; text-decoration: none; }
.skip-link:focus { left: 8px; top: 8px; }

:root {
  --gold:    #FFB800;
  --dark:    #07101c;
  --card:    #0d1929;
  --border:  #1a3050;
  --text:    #dde8f5;
  --muted:   #607898;
  --confirmed-paid:   #7cfc00;
  --confirmed-unpaid: #cc5500;
  --pending:  #2563eb;
  --ooa:      #1a2a3c;
  --avail:    #07101c;
}

body {
  background:
    radial-gradient(ellipse at 90% 0%, rgba(0,56,130,0.30) 0%, transparent 55%),
    linear-gradient(150deg, #00060f 0%, #001530 55%, #07101c 100%);
  background-attachment: fixed;
  color: var(--text);
  font-family: 'Inter', sans-serif;
  /* Flex column + bounded height on ALL sizes, not just mobile -- this is
     what makes #view-aerial/#scroll-aerial's flex:1 1 auto sizing (see
     #scroll-aerial below) actually have something to compute against.
     Previously desktop relied on #scroll-aerial's own hardcoded
     max-height:calc(100vh - 140px) instead, since body here was plain
     display:block outside the mobile media query -- when that hardcoded
     value was replaced with flexbox sizing, desktop lost its bound
     entirely (nothing constrained the flex chain's height any more) and
     the map just grew to content size instead of scrolling. Same
     display:flex column stacks children in DOM order, so this shouldn't
     change desktop's visual layout at all outside of restoring scroll. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  max-height: 100vh;
  max-height: 100dvh;
  overflow-x: hidden;
  overflow-y: auto;
  position: relative;
}

body::before {
  content: '';
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background:
    linear-gradient(rgba(0,170,255,1) 1px, transparent 1px) 0 0 / 48px 48px,
    linear-gradient(90deg, rgba(0,170,255,1) 1px, transparent 1px) 0 0 / 48px 48px;
  opacity: 0.035;
  pointer-events: none;
  z-index: -1;
}


header {
  background: rgba(4,13,24,0.96);
  border-bottom: 3px solid var(--gold);
  padding: 14px 20px 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
}
.header-left { display: flex; align-items: center; gap: 14px; }
.header-logo-img { height: 52px; width: auto; display: block; flex-shrink: 0; }
.header-logo { font-family: 'Bebas Neue', sans-serif; font-size: 32px; letter-spacing: 2px; color: var(--gold); line-height: 1; display: none; }
.header-title { font-family: 'Bebas Neue', sans-serif; font-size: 18px; letter-spacing: 1.5px; color: #ccc; line-height: 1; }
.header-sub { font-size: 11px; color: var(--muted); letter-spacing: 0.5px; margin-top: 2px; }
.header-right { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.event-badge { background: var(--gold); color: #000; font-family: 'Bebas Neue', sans-serif; font-size: 13px; letter-spacing: 1px; padding: 3px 10px; border-radius: 3px; }
.sync-time { font-size: 11px; color: var(--muted); }

.controls {
  background: #060e1a;
  border-bottom: 1px solid var(--border);
  padding: 10px 20px;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.search-wrap { position: relative; flex: 0 0 240px; }
.search-wrap input {
  width: 100%;
  background: #0d1e35;
  border: 1.5px solid #3a6090;
  border-radius: 6px;
  color: var(--text);
  font-size: 13px;
  padding: 8px 12px 8px 34px;
  outline: none;
  transition: border-color .2s, box-shadow .2s;
  box-shadow: 0 0 0 1px rgba(100,160,220,0.08) inset;
}
.search-wrap input:focus {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(255,184,0,0.18);
}
.search-wrap::before {
  content: '⌕';
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: #6aa8d0;
  font-size: 16px;
  pointer-events: none;
  transition: color .2s;
}
.search-wrap:focus-within::before { color: var(--gold); }
.search-wrap input::placeholder { color: #4a6888; font-style: italic; }

.view-toggle {
  display: flex;
  background: #0a1828;
  border: 1px solid #E85D04;
  border-radius: 6px;
  overflow: hidden;
}
.view-btn {
  font-family: 'Bebas Neue', sans-serif;
  font-size: 13px;
  letter-spacing: 1px;
  padding: 6px 16px;
  cursor: pointer;
  color: #E85D04;
  background: none;
  border: none;
  border-right: 1px solid #E85D04;
  transition: background .15s, color .15s;
}
.view-btn:last-child { border-right: none; }
.view-btn.active { background: #E85D04; color: #000; font-weight: 700; }
.view-btn:not(.active):hover { background: rgba(232,93,4,0.12); color: #ff7a2a; }
.view-btn:focus {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.zoom-controls { display: flex; align-items: center; gap: 6px; background: #0a1828; border: 1px solid var(--border); border-radius: 6px; padding: 4px 8px; margin-left: 8px; }
.zoom-controls button { font-family: 'Inter', sans-serif; font-size: 14px; font-weight: 600; padding: 4px 8px; cursor: pointer; color: var(--text); background: #152336; border: 1px solid var(--border); border-radius: 3px; transition: background .15s, color .15s; }
.zoom-controls button:hover { background: #1a3050; color: var(--gold); }
.zoom-controls button:focus {
  outline: 2px solid var(--gold);
  outline-offset: -2px;
}
#zoom-level { font-size: 12px; min-width: 45px; text-align: center; color: var(--muted); }

.legend { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-left: auto; }
.leg { display: flex; align-items: center; gap: 5px; font-size: 11px; color: #aaa; }
.leg-dot { width: 12px; height: 12px; border-radius: 2px; flex-shrink: 0; }
.leg-gold   { background: var(--confirmed-paid); }
.leg-blue   { background: var(--confirmed-unpaid); }
.leg-orange { background: var(--pending); }
.leg-dark   { background: #1a2a3c; border: 1px solid #2a4060; }
.leg-gray   { background: var(--ooa); border: 1px solid #555; }
.leg-ems { background: repeating-linear-gradient(45deg,rgba(255,255,255,0.5) 0,rgba(255,255,255,0.5) 2px,rgba(0,0,0,0.5) 2px,rgba(0,0,0,0.5) 4px); border: 1px solid rgba(255,200,0,0.6); }

.scroll-shell { position: relative; overflow-x: auto; overflow-y: auto; -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: var(--gold) #1e1e1e; }
.scroll-shell::-webkit-scrollbar { height: 8px; }
.scroll-shell::-webkit-scrollbar-track { background: #060e1a; }
.scroll-shell::-webkit-scrollbar-thumb { background: var(--gold); border-radius: 4px; }
.scroll-shell::-webkit-scrollbar-thumb:hover { background: #ffd040; }

.scroll-arrow-bar { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 6px 16px; background: rgba(0,0,0,0.3); border-bottom: 1px solid #2a2a2a; }
.scroll-arrow { background: #0a1828; border: 1px solid var(--border); color: var(--gold); font-size: 22px; line-height: 1; width: 38px; height: 30px; cursor: pointer; border-radius: 4px; display: inline-flex; align-items: center; justify-content: center; transition: background .15s; flex-shrink: 0; }
.scroll-arrow:hover { background: #1a3050; color: #ffd040; }
.scroll-arrow:focus { outline: 2px solid var(--gold); outline-offset: 2px; }
.scroll-hint { font-size: 11px; color: #555; margin-left: 4px; font-style: italic; }


#view-aerial { display: none; flex-direction: column; background: #040d18; padding: 0; flex: 1 1 auto; overflow: hidden; min-height: 0; }
/* #scroll-aerial fills whatever space .rules-notice + .scroll-arrow-bar don't take,
   via flexbox -- NOT a hardcoded max-height calc. That used to subtract a fixed
   140px guess for the notice/toolbar above it, which silently went stale (and
   clipped/locked the map) the day the safety notice was enlarged. flex:1 1 auto
   plus min-height:0 (overriding the flex default that blocks shrinking) makes this
   self-adjusting no matter how tall those siblings are now or become later. */
#scroll-aerial { flex: 1 1 auto; min-height: 0; }
#aerial-scaler { display: inline-block; line-height: 0; vertical-align: top; overflow: hidden; }
.aerial-wrap { position: relative; display: inline-block; background: #0a1828; line-height: 0; transform-origin: top left; transition: transform 0.1s ease-out; }
.aerial-wrap img#aerial-bg { display: block; width: 100%; min-width: 900px; max-width: 1552px; height: auto; }
.aerial-placeholder { display: none; width: 100%; min-width: 900px; max-width: 1552px; height: 400px; background: #07101c; border: 2px dashed #1a3050; align-items: center; justify-content: center; flex-direction: column; gap: 12px; color: var(--muted); font-size: 13px; text-align: center; padding: 20px; }
.aerial-placeholder strong { font-family: 'Bebas Neue', sans-serif; font-size: 22px; color: var(--gold); letter-spacing: 1px; }
.aerial-section { position: absolute; display: flex; flex-direction: row; overflow: hidden; cursor: default; }
.aerial-section.acol { flex-direction: column; }
.acol .a-stall { border-right: none; border-bottom: 1px solid rgba(0,0,0,.25); }
.acol .a-stall:last-child { border-bottom: none; }
.acol .a-stall .a-name { writing-mode: horizontal-tb; text-orientation: initial; }

.a-stall { flex: 1; height: 100%; cursor: pointer; border-right: 1px solid rgba(0,0,0,.25); display: block; font-size: 7px; font-weight: 600; line-height: 1; color: rgba(0,0,0,0.7); overflow: visible; transition: filter .1s, z-index .1s; position: relative; }
.a-stall:last-child { border-right: none; }
.a-stall:hover { filter: brightness(1.35); z-index: 30; }
.a-stall:focus { outline: 2px solid var(--gold); outline-offset: -2px; z-index: 30; }
.a-stall.s-ooa      { background: rgba(26,42,60,0.85); color: #607898; }
.a-stall.s-avail    { background: rgba(7,16,28,0.75);  color: #607898; border-right-color: rgba(26,48,80,.35); }
.a-stall.s-confirmed-paid   { background: rgba(124,252,0,0.88);  color: #000; }
.a-stall.s-confirmed-unpaid { background: rgba(204,85,0,0.88);  color: #fff; }
.a-stall.s-pending  { background: rgba(37,99,235,0.88); color: #fff; }
.a-stall.is-dim   { opacity: 0.08; }
.a-stall.is-match { filter: brightness(1.5); outline: 2px solid #fff; z-index: 35; }

.a-stall .a-num { position: absolute; top: 2px; left: 2px; font-size: 8px; font-weight: 700; line-height: 1; background: rgba(0,0,0,0.25); padding: 1px 3px; border-radius: 2px; z-index: 2; color: var(--gold); }
.a-stall.s-avail .a-num, .a-stall.s-ooa .a-num { background: rgba(255,255,255,0.07); }
.a-stall .a-name-hover { position: absolute; left: 50%; bottom: calc(100% + 4px); transform: translateX(-50%); display: none; min-width: max-content; max-width: 140px; padding: 4px 6px; border-radius: 4px; background: rgba(6,14,26,0.96); color: #fff; border: 1px solid rgba(255,184,0,0.55); box-shadow: 0 4px 14px rgba(0,0,0,0.45); font-family: 'Bebas Neue', sans-serif; font-size: 12px; letter-spacing: 0.8px; line-height: 1; white-space: nowrap; text-align: center; pointer-events: none; z-index: 50; }
.a-stall:hover .a-name-hover,
.a-stall:focus .a-name-hover,
.a-stall:focus-visible .a-name-hover { display: block; }
/* Restored elegant overhead: always-on vertical name labels */
.a-stall .a-name { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 13px 1px 1px; font-family: 'Bebas Neue', sans-serif; font-size: 8px; font-weight: 400; letter-spacing: 0.3px; line-height: 1.05; text-align: center; overflow: hidden; word-break: break-word; color: inherit; opacity: 0.9; writing-mode: vertical-rl; text-orientation: mixed; }
.a-stall.s-ooa .a-name { color: #aaa; opacity: 1; }


#popup-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.6); z-index: 9000; align-items: center; justify-content: center; }
#popup-overlay.open { display: flex; }
#popup-card { background: var(--card); border: 1px solid #333; border-radius: 10px; padding: 24px 28px; width: 320px; max-width: 90vw; position: relative; box-shadow: 0 8px 40px rgba(0,0,0,.8); }
.popup-close { position: absolute; top: 12px; right: 14px; background: none; border: none; color: var(--muted); cursor: pointer; font-size: 20px; line-height: 1; transition: color .15s; }
.popup-close:hover { color: var(--text); }
.popup-close:focus { outline: 2px solid var(--gold); outline-offset: 2px; }
.popup-stall-id { font-family: 'Bebas Neue', sans-serif; font-size: 42px; color: var(--gold); letter-spacing: 2px; line-height: 1; }
.popup-grade  { font-size: 11px; color: var(--muted); letter-spacing: 1px; text-transform: uppercase; margin-bottom: 12px; }
.popup-name   { font-size: 20px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.popup-status-badge { display: inline-block; font-size: 11px; font-weight: 600; padding: 3px 10px; border-radius: 20px; letter-spacing: 0.5px; text-transform: uppercase; }
.badge-confirmed-paid   { background: var(--confirmed-paid); color: #000; }
.badge-confirmed-unpaid { background: var(--confirmed-unpaid); color: #fff; }
.badge-pending  { background: var(--pending); color: #000; }
.badge-ooa      { background: var(--ooa); color: #888; }
.badge-avail    { background: #0d1929; color: #607898; border: 1px solid #1a3050; }
.btn-buy-stall { display: block; margin-top: 18px; width: 100%; background: var(--gold); color: #000; font-family: 'Bebas Neue', sans-serif; font-size: 17px; letter-spacing: 1.5px; border: none; border-radius: 6px; padding: 10px 0; text-align: center; text-decoration: none; }
.btn-buy-stall:hover { filter: brightness(1.1); }
.btn-buy-stall:focus { outline: 2px solid #000; outline-offset: 2px; }

.rules-notice { background: rgba(200,20,0,0.32); border-top: 3px solid #ff3300; border-bottom: 3px solid #ff3300; padding: 16px 20px; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px; color: #ffe4d8; font-family: 'Bebas Neue', sans-serif; font-size: 24px; font-weight: 700; letter-spacing: 1.4px; text-align: center; text-shadow: 0 1px 4px rgba(0,0,0,0.6); box-shadow: 0 0 0 1px rgba(255,51,0,0.25) inset, 0 4px 16px rgba(200,20,0,0.35); }
.rules-notice .rn-icon { font-size: 30px; flex-shrink: 0; }
.rules-notice .rn-divider { color: rgba(255,150,110,0.55); margin: 0 6px; }
@media (max-width: 640px) { .rules-notice { font-size: 18px; letter-spacing: 1px; padding: 14px 14px; gap: 6px; } .rules-notice .rn-icon { font-size: 22px; } .rules-notice .rn-divider { display: none; } }

.sponsor-badge { position: absolute; bottom: 2px; right: 2px; font-size: 9px; line-height: 1; z-index: 3; pointer-events: none; filter: drop-shadow(0 0 3px rgba(255,184,0,0.7)); }
.a-stall.is-sponsor { border-bottom: 2px solid #FFB800 !important; }

.sponsor-ticker { background: #040d18; border-top: 1px solid var(--border); padding: 10px 0; min-height: 64px; overflow: hidden; position: relative; display: flex; align-items: center; }
.sponsor-ticker::before, .sponsor-ticker::after { content: ''; position: absolute; top: 0; bottom: 0; width: 80px; z-index: 2; pointer-events: none; }
.sponsor-ticker::before { left: 0;  background: linear-gradient(90deg,  #040d18, transparent); }
.sponsor-ticker::after  { right: 0; background: linear-gradient(270deg, #040d18, transparent); }
.ticker-label { position: absolute; left: 0; top: 0; bottom: 0; width: 90px; display: flex; align-items: center; justify-content: center; font-family: 'Bebas Neue', sans-serif; font-size: 9px; letter-spacing: 2px; color: var(--gold); text-align: center; line-height: 1.2; }
.ticker-track { overflow: hidden; margin-left: 90px; }
.ticker-inner { display: flex; align-items: center; gap: 56px; width: max-content; padding: 0 28px; }
@keyframes ticker-scroll { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } }
.ticker-logo { height: 44px; width: auto; max-width: 140px; object-fit: contain; opacity: 0.88; filter: brightness(1.05); flex-shrink: 0; transition: opacity .2s, filter .2s; }
.ticker-logo:hover { opacity: 1; filter: brightness(1.2); }
.ticker-logo:focus { outline: 2px solid var(--gold); outline-offset: 4px; }

button, .a-stall, .view-btn { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }

@media (max-width: 640px) {
  header { padding: 10px 12px 8px; gap: 6px; }
  .header-logo-img { height: 40px; }
  .header-logo  { font-size: 24px; }
  .header-title { font-size: 14px; letter-spacing: 1px; }
  .header-sub   { font-size: 10px; }
  .event-badge  { font-size: 11px; padding: 3px 8px; }
  .sync-time    { font-size: 10px; }
  .controls { padding: 8px 12px; gap: 8px; }
  .search-wrap { flex: 1 1 100%; order: -1; }
  .view-toggle { flex-shrink: 0; }
  .zoom-controls { margin-left: 0; flex-shrink: 0; }
  .legend { gap: 7px; margin-left: 0; width: 100%; }
  .leg    { font-size: 10px; }
  .leg-dot { width: 10px; height: 10px; }
  .scroll-arrow-bar { padding: 5px 12px; gap: 8px; }
  .scroll-arrow { width: 48px; height: 40px; font-size: 22px; }
  .scroll-hint { display: none; }
  #popup-card { width: 92vw; padding: 20px 16px; }
  .popup-stall-id { font-size: 36px; }
  .popup-name     { font-size: 18px; }
  .popup-close    { font-size: 22px; top: 10px; right: 12px; }
  /* 100vh on Android Chrome is sized for the collapsed address bar, so with it
     visible the flex content can exceed the real visible height. That used to be
     clipped outright (overflow:hidden) with no way to reach it -- 100dvh tracks the
     actual visible viewport, and overflow-y:auto is a safety valve for any device
     where content still doesn't fit, so the page can scroll instead of clipping. */
  header          { order: 1; }
  .controls       { order: 2; }
  /* John's requested mobile stack: warning label, then the sponsor bar
     directly under it, then the map. */
  body > .rules-notice { order: 3; }  /* body-level only: admin's notice still lives inside its map view */
  .sponsor-ticker { order: 4; height: 56px; min-height: 56px; padding: 6px 0; border-top: none; border-bottom: 1px solid var(--border); }
  /* Map height = viewport minus the sponsor bar's fixed 56px: page content
     always exceeds the viewport so the chrome above scrolls away naturally,
     and the scroll's natural END lands with the sponsor bar pinned at the
     very top and the map filling everything below it. (Also prevents the
     old "header locks and blocks the map" crush, where the chrome consumed
     the whole 100dvh-bounded viewport and left the flex map a sliver.) */
  #view-aerial    { order: 5; min-height: calc(100vh - 56px); min-height: calc(100dvh - 56px); }
  #view-trackmap  { order: 5; }
  #popup-overlay  { order: 6; }
  .ticker-label { display: none; }
  .ticker-track { margin-left: 0; }
  .a-stall .a-name { font-size: 6px; word-break: normal; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; writing-mode: horizontal-tb; padding: 10px 1px 1px; }
  .a-stall .a-name-hover { display: none !important; }
}

@media (max-width: 400px) {
  .header-logo  { font-size: 20px; }
  .header-title { font-size: 12px; }
  .zoom-controls button { padding: 3px 6px; font-size: 13px; }
  #zoom-level { min-width: 36px; font-size: 11px; }
}

.track-map-section {
  width: 100%;
  max-width: 1400px;
  margin: 0 auto 0 auto;
  padding: 16px 20px 16px;
  box-sizing: border-box;
}
.track-map-header {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  margin-bottom: 10px;
}
.track-map-title {
  font-family: 'Bebas Neue', sans-serif;
  font-size: 16px;
  letter-spacing: 1.5px;
  color: var(--gold);
  margin: 0;
}
.track-map-sub {
  font-size: 11px;
  color: var(--muted);
  flex: 1 1 auto;
  letter-spacing: 0.3px;
}
.track-map-download {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  background: #c0392b;
  color: #fff;
  font-family: 'Bebas Neue', sans-serif;
  font-size: 12px;
  letter-spacing: 1.2px;
  padding: 4px 12px;
  border-radius: 3px;
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s ease;
  flex-shrink: 0;
  border: none;
}
.track-map-download:hover { background: #a93226; }
.track-map-download:focus { outline: 2px solid var(--gold); outline-offset: 2px; }
.track-map-wrap {
  width: 100%;
  border-radius: 5px;
  overflow: hidden;
  box-shadow: 0 2px 16px rgba(0,0,0,0.5);
  line-height: 0;
  background: #2a4a1a;
  border: 1px solid var(--border);
}
.track-map-img {
  width: 100%;
  height: auto;
  display: block;
}
.track-map-caption {
  margin: 6px 0 0 0;
  font-size: 10px;
  color: var(--muted);
  text-align: center;
  letter-spacing: 0.5px;
  font-family: 'Bebas Neue', sans-serif;
}
@media (max-width: 640px) {
  .track-map-section { padding: 10px 0 10px; }
  .track-map-header  { padding: 0 12px; }
  .track-map-caption { padding: 0 12px; }
  .track-map-wrap    { border-radius: 0; border-left: none; border-right: none; }
}

#view-trackmap {
  flex-direction: column;
  background: var(--dark);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--gold) #1e1e1e;
}
#view-trackmap::-webkit-scrollbar { width: 6px; }
#view-trackmap::-webkit-scrollbar-track { background: #060e1a; }
#view-trackmap::-webkit-scrollbar-thumb { background: var(--gold); border-radius: 3px; }

@media (max-width: 640px) {
  #view-trackmap { order: 4; }
}
