:root{
  --bg0:#06070a;
  --bg1:#0a0d13;
  --text:#f2f4f8;
  --muted:#b2bccb;
  --edge: rgba(255,255,255,.10);
  --shadow: 0 18px 45px rgba(0,0,0,.55);

  --red:#d71920;

  /* FDR legend colours */
  --nr:#6b7280;
  --mod:#22c55e;
  --high:#eab308;
  --ext:#f97316;
  --cat:#ef4444;
}

*{ box-sizing:border-box; }

html,body{
  height:100%;
  margin:0;
  font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
  color: var(--text);
  background:
    radial-gradient(1200px 800px at 50% 20%, rgba(40,55,80,.40), rgba(0,0,0,0) 55%),
    radial-gradient(900px 700px at 20% 80%, rgba(10,120,120,.10), rgba(0,0,0,0) 60%),
    linear-gradient(180deg, var(--bg1), var(--bg0));
}

/* =====================
   Top bar
   ===================== */
.top-bar{
  height: 36px;
  background: var(--red);
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding: 0 18px;
  font-weight: 800;
  letter-spacing: .2px;
}
.top-bar-left, .top-bar-right{
  font-size: 13px;
  opacity: .98;
}

/* =====================
   Hero
   ===================== */
.hero{
  padding: 28px 18px 18px 18px;
  text-align:center;
}

/* Marquee: smooth right -> left, fully off-screen both sides */
.hero-marquee{
  width: 100%;
  overflow: hidden;
  position: relative;
  margin-bottom: 10px;

  /* helps reduce repaints */
  contain: content;
}

.hero-marquee-track{
  display: inline-block;
  white-space: nowrap;

  font-size: clamp(26px, 4vw, 42px);
  font-weight: 900;
  letter-spacing: 1px;
  text-shadow: 0 6px 18px rgba(0,0,0,.45);

  /* start with a full container-width gap on the left */
  padding-left: 100%;

  will-change: transform;
  transform: translate3d(0,0,0);
  animation: hero-marquee-rtl 18s linear infinite;
  backface-visibility: hidden;
}

/* Move left by (text width + that 100% gap) */
@keyframes hero-marquee-rtl{
  0%   { transform: translate3d(0,0,0); }
  100% { transform: translate3d(-100%,0,0); }
}

@media (prefers-reduced-motion: reduce){
  .hero-marquee-track{ animation: none; }
}

/* Date: about half the size of time */
.hero-sub{
  color: var(--muted);
  font-size: clamp(22px, 3vw, 38px);
  margin-top: 6px;
  font-weight: 700;
}
.hero-time{
  margin-top: 6px;
  font-size: clamp(44px, 6vw, 76px);
  font-weight: 900;
  letter-spacing: 1px;
}

/* =====================
   Layout
   ===================== */
.container{
  width: min(1500px, calc(100% - 32px));
  margin: 0 auto 34px auto;
  display:grid;
  gap: 18px;
}
.two-col{
  grid-template-columns: 1fr 1fr;
}
@media (max-width: 1100px){
  .two-col{ grid-template-columns: 1fr; }
}

/* =====================
   Cards
   ===================== */
.card{
  background:
    radial-gradient(900px 500px at 30% 20%, rgba(30,45,70,.35), rgba(0,0,0,0) 60%),
    linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.02));
  border: 1px solid var(--edge);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 16px;
}
.card h2{
  margin: 0 0 12px 0;
  font-size: 20px;
  font-weight: 900;
}
.card-head{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap: 12px;
  margin-bottom: 10px;
}
.smallMuted{
  color: var(--muted);
  font-size: 13px;
}

/* =====================
   Fire Danger Rating
   ===================== */
.fdrGrid{
  display:grid;
  grid-template-columns: 1fr;
  gap: 14px;
}

.fdrMapFrame{
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 12px;
  overflow:hidden;
  min-height: 460px;
  background: rgba(0,0,0,.25);
  position: relative;
}

.fdrSvgHolder{
  width:100%;
  height:100%;
  min-height: 460px;
  display:flex;
  align-items:center;
  justify-content:center;
  padding: 10px;
}

.fdrSvg{
  display:block;
  width:100%;
  height:100%;
  max-width:100%;
  max-height:100%;
}

/* Bottom legend bars */
.fdrLegendBar{
  position:absolute;
  left: 12px;
  right: 12px;
  bottom: 12px;

  display:grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;

  padding: 10px;
  border-radius: 12px;
  background: rgba(0,0,0,.40);
  border: 1px solid rgba(255,255,255,.08);
  z-index: 3;
}

.fdrLegendSeg{
  height: 22px;
  border-radius: 10px;
  border: 1px solid rgba(255,255,255,.10);
  box-shadow: 0 8px 18px rgba(0,0,0,.25);

  display:flex;
  align-items:center;
  justify-content:center;

  font-size: 12px;
  font-weight: 900;
  letter-spacing: .3px;
  white-space: nowrap;

  /* same text colour for all */
  color: #0b1020;
}

.fdrLegendSeg.nr{ background: var(--nr); }
.fdrLegendSeg.mod{ background: var(--mod); }
.fdrLegendSeg.high{ background: var(--high); }
.fdrLegendSeg.ext{ background: var(--ext); }
.fdrLegendSeg.cat{ background: var(--cat); }

/* SVG district styling */
svg [id^="district-"]{
  stroke: rgba(255,255,255,.20);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

/* ✅ district label font */
.saDistrictLabel{
  font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
  font-weight: 900;
  font-size: 11px;
  fill: #ffffff;
  paint-order: stroke;
  stroke: rgba(0,0,0,.70);
  stroke-width: 3px;
  pointer-events: none;
}

.saTfbIcon{
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,.65));
  opacity: 0.95;
}

/* =====================
   CFA News – 3 items fill evenly
   ===================== */

/* Make the CFA News card a vertical layout so the list can fill height */
.card.cfa-news-card{
  display:flex;
  flex-direction: column;
}

/* Replace default list styling + make it a 3-row grid that fills the card */
#cfa-news{
  list-style: none;
  padding: 0;
  margin: 0;

  display: grid;
  grid-template-rows: repeat(3, minmax(0, 1fr));
  gap: 14px;

  flex: 1;
  min-height: 0;
}

/* Each article fills its grid row */
.newsFeatured{
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 12px;
  align-items: stretch;

  height: 100%;
  margin: 0;

  padding: 14px; /* ✅ more padding inside the card */
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 12px;
  background: rgba(0,0,0,.20);
}

/* Thumb stays constant size */
.newsThumb{
  width: 140px;
  height: 90px;
  flex-shrink: 0;
  border-radius: 8px;
  overflow: hidden;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.10);
  box-shadow: 0 10px 22px rgba(0,0,0,.35);
}
.newsThumb img{
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Content becomes a vertical stack and can grow */
.newsContent{
  display: flex;
  flex-direction: column;
  min-height: 0;

  /* ✅ optional spacing */
  padding-top: 2px;
}

/* Title + meta */
.newsFeaturedTitle{
  font-weight: 900;
  font-size: 15px;
  line-height: 1.2;
  margin: 0 0 4px 0;
}
.newsFeaturedTitle a{
  color: #fff;
  text-decoration: none;
}
.newsFeaturedTitle a:hover{
  text-decoration: underline;
}

.newsMeta{
  color: var(--muted);
  font-size: 12px;
  margin: 0 0 8px 0;
}

/* Excerpt expands to fill available row height */
.newsExcerpt{
  color: var(--text);

  /* ✅ bigger excerpt text */
  font-size: 14.5px;
  line-height: 1.45;

  flex: 1;
  min-height: 0;

  display: -webkit-box;
  -webkit-line-clamp: 12;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Fallback links/list styling (kept for safety if any plain list items appear) */
.newsList{
  margin: 0;
  padding-left: 18px;
}
.newsList li{
  margin: 8px 0;
  color: var(--text);
}
.newsList a{
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid rgba(255,255,255,.15);
}
.newsList a:hover{
  border-bottom-color: rgba(255,255,255,.55);
}

/* =====================
   API bubble
   ===================== */
#apiBubble{
  position:fixed;
  right: 18px;
  bottom: 18px;
  width: 46px;
  height: 46px;
  border-radius: 999px;
  display:flex;
  align-items:center;
  justify-content:center;
  font-weight: 900;
  letter-spacing: .4px;
  user-select:none;
  z-index: 50;
  box-shadow: 0 18px 35px rgba(0,0,0,.55);
  border: 1px solid rgba(255,255,255,.10);
}
#apiBubble.ok{
  background: #22c55e;
  color:#08340f;
}
#apiBubble.bad{
  background: #ef4444;
  color:#3b0a0a;
}


/* =====================
   Page rotation (Option A)
   ===================== */
#panelWrap{
  position: relative;
  width: 100%;
}

/* Each page crossfades */
.panelPage{
  opacity: 0;
  pointer-events: none;
  transition: opacity .6s ease;

  position: absolute;
  inset: 0;
}

.panelPage.isActive{
  opacity: 1;
  pointer-events: auto;
  position: relative; /* active page participates in layout */
}

/* =====================
   Weather card
   ===================== */
.wxNow{
  display:flex;
  align-items:center;
  gap: 18px;
  margin-top: 6px;
}

.wxTemp{
  font-size: clamp(44px, 6vw, 70px);
  font-weight: 900;
  letter-spacing: 1px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.wxSummary{
  font-size: 14px;
  font-weight: 900;
  margin-bottom: 6px;
}

.wxDaily{
  margin-top: 16px;
  display:grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}

.wxDay{
  border: 1px solid rgba(255,255,255,.10);
  border-radius: 12px;
  background: rgba(0,0,0,.20);
  padding: 12px;
}

.wxDayTop{
  display:flex;
  align-items:center;
  justify-content:space-between;
  font-weight: 900;
  margin-bottom: 8px;
}

.wxRange{
  display:flex;
  align-items:center;
  justify-content:space-between;
  font-size: 14px;
  font-weight: 800;
}

.wxLo{
  opacity: .8;
  font-weight: 800;
}

/* =====================
   Availability placeholder
   ===================== */
.availPlaceholder{
  border: 1px dashed rgba(255,255,255,.18);
  border-radius: 12px;
  padding: 14px;
  background: rgba(0,0,0,.18);
}


/* =====================
   Weather: 6-hour forecast bar
   ===================== */
.weatherCard{
  /* slightly larger text inside weather card */
  font-size: 16px;
}

.wxMeta .smallMuted{
  font-size: 15px;
}

.wxBar{
  margin-top: 14px;
  border: 1px solid rgba(255,255,255,.10);
  border-radius: 12px;
  background: rgba(0,0,0,.18);
  overflow: hidden;
}

.wxBarRow{
  display: grid;
  grid-template-columns: 110px repeat(6, minmax(0, 1fr));
}

.wxBarLabel{
  padding: 10px 12px;
  font-weight: 900;
  letter-spacing: .2px;
  background: rgba(255,255,255,.04);
  border-right: 1px solid rgba(255,255,255,.08);
  display:flex;
  align-items:center;
  justify-content:flex-start;
}

.wxCell{
  padding: 10px 8px;
  border-right: 1px solid rgba(255,255,255,.08);
  display:flex;
  flex-direction:column;
  gap: 6px;
  align-items:center;
  justify-content:center;
  min-height: 86px;
}
.wxBarRow .wxCell:last-child{ border-right: none; }

.wxHour{
  font-size: 13px;
  color: var(--muted);
  font-weight: 800;
}

.wxTempSmall{
  font-size: 18px;
  font-weight: 900;
}

.wxIcon{
  font-size: 18px;
  line-height: 1;
}

.wxWindLine{
  display:flex;
  align-items:center;
  gap: 8px;
  font-weight: 900;
  font-size: 14px;
}

.wxArrow{
  width: 22px;
  height: 22px;
  border-radius: 999px;
  border: 2px solid rgba(120,170,255,.95);
  display:flex;
  align-items:center;
  justify-content:center;
  box-shadow: 0 10px 20px rgba(0,0,0,.35);
}

.wxArrow svg{
  width: 14px;
  height: 14px;
  display:block;
  transform-origin: 50% 50%;
}

.wxRainLine{
  font-weight: 900;
  font-size: 14px;
}

.wxRainSub{
  font-size: 13px;
  color: var(--muted);
  font-weight: 800;
}


/* =========================================================
   CFA News: compact items (no stretching) + safe scroll
   ========================================================= */
.panelPage[data-page="0"] .card.cfa-news-card{
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}

/* Let the list take remaining height, but DON'T stretch items */
.panelPage[data-page="0"] .card.cfa-news-card #cfa-news{
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow: auto;              /* if content is too tall, scroll inside card */
  padding-bottom: 4px;         /* avoids last item kissing the border */
}

/* Fixed-ish tile height so 3 items look consistent */
.panelPage[data-page="0"] .card.cfa-news-card #cfa-news > li{
  flex: 0 0 auto;              /* IMPORTANT: no flex:1 stretching */
  min-height: 110px;           /* tune: 96–130 depending on your card height */
  overflow: hidden;
}

/* Clamp excerpts so they don't blow out tile height */
.panelPage[data-page="0"] .card.cfa-news-card .newsExcerpt{
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}



/* =========================================================
   LAYOUT FIX: restore original two-column cards
   (Prevents FDR card becoming full-screen)
   ========================================================= */
.two-col{
  display: grid !important;
  grid-template-columns: 1fr 1fr !important;
  gap: 18px !important;
  align-items: stretch !important;
}

@media (max-width: 1100px){
  .two-col{ grid-template-columns: 1fr !important; }
}



/* =========================================================
   FINAL: Align CFA News tiles to FDR card top/bottom with even spacing
   - Screen 1 only (data-page="0")
   - Keeps cards same size; does not affect weather screen
   ========================================================= */

/* Ensure both cards behave the same vertically */
.panelPage[data-page="0"] .two-col{
  align-items: stretch !important;
}

.panelPage[data-page="0"] .card{
  height: 100% !important;
  display: flex !important;
  flex-direction: column !important;
  overflow: hidden !important;
}

/* Make header spacing consistent between FDR + News so content starts aligned */
.panelPage[data-page="0"] .card .card-head{
  margin-bottom: 14px !important;
}

/* News list fills remaining height and uses a 3-row grid so:
   - first tile touches top of content area
   - last tile touches bottom of content area
   - gaps are even
*/
.panelPage[data-page="0"] .newsCard #cfa-news{
  flex: 1 !important;
  min-height: 0 !important;
  display: grid !important;
  grid-template-rows: repeat(3, minmax(0, 1fr)) !important;
  gap: 14px !important;                 /* even spaces between tiles */
  overflow: hidden !important;          /* no scrolling; stays inside card */
  padding: 0 !important;
  margin: 0 !important;
  list-style: none !important;
}

/* Tiles stretch evenly but don't overflow */
.panelPage[data-page="0"] .newsCard #cfa-news > li{
  min-height: 0 !important;
  overflow: hidden !important;
  margin: 0 !important;
}

/* Clamp excerpt so a long story can't blow up a tile */
.panelPage[data-page="0"] .newsCard .newsExcerpt{
  display: -webkit-box !important;
  -webkit-line-clamp: 3 !important;
  -webkit-box-orient: vertical !important;
  overflow: hidden !important;
}

/* Undo earlier compact-news scroll behaviour if present */
.panelPage[data-page="0"] .card.cfa-news-card #cfa-news{
  overflow: hidden !important;
}


/* =====================
   Weather: top row layout (summary + wind) and hi/lo in header
   ===================== */
.wxMeta{ flex: 1; min-width: 0; }

.wxTopRow{
  display:flex;
  align-items:center;
  justify-content: space-between;
  gap: 12px;
}

.wxWindNow{
  display:flex;
  align-items:center;
  gap: 8px;
  font-weight: 900;
  font-size: 16px;
  white-space: nowrap;
}

.wxHiLo{
  margin-left: auto;
  font-weight: 900;
  font-size: 16px;
  text-align: right;
  white-space: nowrap;
}

/* Make weather header support right-side content cleanly */
.card-head{
  display:flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}


/* Weather header: Hi/Lo top-right above Updated */
.wxHeadRight{
  margin-left: auto;
  display:flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}

.wxHiLo{
  font-weight: 900;
  font-size: 16px;
  text-align: right;
  white-space: nowrap;
}

/* Summary row: Summary left, Wind right */
.wxTopRow{
  display:flex;
  align-items:center;
  justify-content: space-between;
  gap: 12px;
}

.wxWindNow{
  display:flex;
  align-items:center;
  gap: 8px;
  font-weight: 900;
  font-size: 16px;
  white-space: nowrap;
}


/* =========================================================
   CFA NEWS: increase space below header ONLY (align with FDR map)
   Applies to screen 1 only.
   ========================================================= */
.panelPage[data-page="0"] .newsCard > #cfa-news{
  margin-top: 15px !important; /* pushes first news tile down */
}

/* =====================
   Weather: gust display
   (adds current gust under wind + hourly gust line)
   ===================== */
.wxWindNowStack{
  display:flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}
.wxWindNowMain{
  display:flex;
  align-items:center;
  gap: 8px;
  white-space: nowrap;
}
.wxWindNowSpeed{
  font-weight: 900;
  opacity: .9;
}
.wxGustNow{
  font-size: 12px;
  color: var(--muted);
  font-weight: 800;
  margin-left: 32px; /* aligns under text after arrow */
  white-space: nowrap;
}
.wxGust{
  font-size: 12px;
  color: var(--muted);
  font-weight: 800;
  margin-top: 2px;
  white-space: nowrap;
}


/* =====================
   CFA News alignment (restore prior spacing under header)
   ===================== */
.panelPage[data-page="0"] .newsCard > #cfa-news{
  margin-top: 12px !important;
}

/* =====================
   Weather header boxes (W/T)
   ===================== */
.weatherCard .wxHeadRight{
  margin-left: auto;
  display:flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}

.weatherCard .wxBoxes{
  display:flex;
  align-items: stretch;
  gap: 12px;
}

.weatherCard .wxBox{
  display:flex;
  align-items:center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 14px;
  border: 1px solid rgba(255,255,255,.10);
  background: rgba(0,0,0,.18);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.04);
  min-width: 132px;
}

.weatherCard .wxWindTxt{
  display:flex;
  flex-direction: column;
  line-height: 1.1;
}
.weatherCard .wxWindDir{ font-weight: 950; font-size: 14px; letter-spacing: .2px; }
.weatherCard .wxWindSpd{ font-weight: 900; font-size: 14px; }
.weatherCard .wxWindGust{ font-weight: 800; font-size: 12px; color: var(--muted); }

.weatherCard .wxTempBox{
  flex-direction: column;
  align-items: flex-end;
  text-align:right;
  line-height: 1.05;
}
.weatherCard .wxTempTop{ font-weight: 950; font-size: 16px; }
.weatherCard .wxTempBot{ font-weight: 900; font-size: 12px; color: var(--muted); }

/* Hide old placements so the header boxes are the only source of wind/temps */
.weatherCard #wxWindNow,
.weatherCard #wxHiLo{
  display:none !important;
}

/* =====================
   PAGE ROTATION HARDEN
   Ensures inactive pages never push layout (fixes weather showing under page 1)
   ===================== */
#panelWrap{ position: relative; }

.panelPage{
  position: absolute !important;
  inset: 0 !important;
  width: 100% !important;
}

.panelPage.isActive{
  position: relative !important;
}



/* Thermometer icon matches wind arrow size/position */
.weatherCard .wxTempBox{
  flex-direction: row !important;
  align-items: center !important;
  justify-content: flex-start !important;
  text-align: left !important;
}

.weatherCard .wxTempIcon{
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.weatherCard .wxTempIcon svg{
  width: 22px;
  height: 22px;
  display:block;
}

.weatherCard .wxTempText{
  display:flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.05;
  margin-left: auto; /* keeps numbers right-aligned inside the box */
}


/* =====================
   Thermometer: match wind arrow size + position exactly
   ===================== */
.weatherCard .wxTempBox{
  display:flex !important;
  align-items:center !important;
  justify-content:flex-start !important;
  gap: 10px !important;
}

.weatherCard .wxTempIcon{
  width: 22px !important;
  height: 22px !important;
  flex: 0 0 22px !important;
  display:inline-flex !important;
  align-items:center !important;
  justify-content:center !important;
}

.weatherCard .wxTempIcon svg{
  width: 22px !important;
  height: 22px !important;
}



/* Weather header temp icon: use same .wxArrow circle as wind, slightly larger glyph */
.weatherCard .wxTempBox .wxArrow svg{
  width: 16px;
  height: 16px;
}

/* =========================
   Fullscreen / Large Display Expansion
   ========================= */
@media (min-width: 1600px) {

  /* Main page wrapper */
  .panelPage{
    padding-left: 24px;
    padding-right: 24px;
  }

  /* Two-column layout (FDR + News, Weather + Availability) */
  .panelGrid{
    max-width: none;              /* remove artificial ceiling */
    gap: 32px;                    /* slightly wider spacing */
  }

  /* Individual cards expand naturally */
  .card{
    width: 100%;
  }

  /* Fire Danger + News row */
  .panelGrid.twoCol{
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 1600px) {
  body{
    padding-left: 0;
    padding-right: 0;
  }
}

@media (min-width: 1600px){

  /* Page 1: FDR wider than CFA News */
  .panelPage.isActive .panelGrid.twoCol{
grid-template-columns: 1.4fr 0.6fr;
  }

}



/* =========================
       Pairing overlay + kiosk blur
       ========================= */
    .hidden{ display:none !important; }

    body.pairing .container,
    body.pairing .hero,
    body.pairing .top-bar{
      filter: blur(6px);
      opacity: .35;
      pointer-events: none;
      user-select: none;
    }

    .pairOverlay{
      position: fixed;
      inset: 0;
      z-index: 9999;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 24px;
      background: rgba(0,0,0,.55);
      backdrop-filter: blur(10px);
    }

    .pairCard{
      width: min(760px, 92vw);
      border-radius: 18px;
      padding: 22px 22px 18px;
      background: rgba(18,26,40,.92);
      border: 1px solid rgba(255,255,255,.08);
      box-shadow: 0 18px 60px rgba(0,0,0,.55);
      color: #e8eefc;
    }

    .pairTitle{ font-size: 28px; font-weight: 800; margin: 0 0 6px; }
    .pairSub{ opacity: .9; margin-bottom: 14px; }

    .pairGrid{
      display: grid;
      grid-template-columns: 260px 1fr;
      gap: 16px;
      align-items: center;
    }
    @media (max-width: 720px){
      .pairGrid{ grid-template-columns: 1fr; }
    }

    .pairQr{
      background: #fff;
      border-radius: 10px;
      padding: 10px;
      width: 260px;
      height: 260px;
      justify-self: center;
    }

    .pairCode{
      font-size: 46px;
      font-weight: 900;
      letter-spacing: .22em;
      margin: 6px 0 6px;
    }
    .pairMeta{ opacity: .85; font-size: 14px; }
    .pairHint{ opacity: .75; font-size: 13px; }

    /* =========================
       Marquee fallback
       ========================= */
    .hero-marquee{ overflow: hidden; }
    .hero-marquee-track{
      display: inline-block;
      white-space: nowrap;
      animation: sa-marquee 18s linear infinite;
      will-change: transform;
    }
    @keyframes sa-marquee{
      0%{ transform: translateX(0); }
      100%{ transform: translateX(-40%); }
    }

/* =========================
   ALERT OVERLAY
   ========================= */

.hidden{ display:none !important; }

.alert-overlay{
  position:fixed;
  inset:0;
  z-index:9999;
  background: rgba(0,0,0,0.85);
  display:flex;
  align-items:center;
  justify-content:center;
  padding: 24px;
}

.alert-card{
  width:min(1100px, 96vw);
  max-height: 92vh;
  overflow:auto;
  background: #0b1220;
  border: 3px solid rgba(255,255,255,0.18);
  border-radius: 18px;
  box-shadow: 0 24px 80px rgba(0,0,0,0.55);
  padding: 22px 22px 18px;
}

.alert-top{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap: 18px;
  margin-bottom: 10px;
}

.alert-title{
  font-weight: 800;
  letter-spacing: 0.08em;
  color: #ffdf7a;
  font-size: 18px;
}

.alert-time{
  font-variant-numeric: tabular-nums;
  opacity: 0.9;
  font-size: 14px;
}

.alert-incident{
  font-size: 44px;
  font-weight: 900;
  line-height: 1.05;
  margin: 8px 0 10px;
}

.alert-address{
  font-size: 34px;
  font-weight: 800;
  line-height: 1.15;
  margin: 10px 0 10px;
  opacity: 0.98;
}

.alert-responding{
  font-size: 18px;
  opacity: 0.95;
  margin: 8px 0;
  white-space: pre-wrap;
}

.alert-notes{
  font-size: 16px;
  opacity: 0.9;
  margin: 10px 0 14px;
  white-space: pre-wrap;
}

.alert-actions{
  display:flex;
  justify-content:flex-end;
  gap: 12px;
  margin-top: 10px;
}

.alert-ack{
  cursor:pointer;
  font-size: 18px;
  font-weight: 800;
  padding: 12px 16px;
  border-radius: 12px;
  border: 2px solid rgba(255,255,255,0.22);
  background: rgba(255,255,255,0.10);
  color: #e8eefc;
}

.alert-ack:active{
  transform: translateY(1px);
}

@media (max-width: 680px){
  .alert-incident{ font-size: 32px; }
  .alert-address{ font-size: 26px; }
}


/* =========================
   Alert overlay: Ops vs Debug
   Toggle with 'D' key (handled in app.js)
   ========================= */
.alert-debug{ display:none; }
html.sa-debug .alert-debug{ display:block; }
html.sa-debug .alert-ops{ display:none; }

/* Ops (big red takeover) */
.alert-overlay{
  background: radial-gradient(1200px 600px at 20% 0%, rgba(255,255,255,0.10), transparent 55%),
              linear-gradient(180deg, rgba(180,0,0,0.94), rgba(120,0,0,0.94));
}

.alert-ops{
  position: absolute;
  inset: 0;
  padding: 26px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  color: #0b0b0b;
}

.ops-banner{
  background: rgba(255,255,255,0.96);
  border: 6px solid rgba(0,0,0,0.88);
  border-radius: 16px;
  padding: 18px 20px;
  display:flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  box-shadow: 0 18px 50px rgba(0,0,0,0.35);
}

.ops-headline{
  font-size: clamp(34px, 4.2vw, 64px);
  font-weight: 1000;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  line-height: 1.05;
}

.ops-updated{
  font-weight: 800;
  font-size: 18px;
  opacity: 0.85;
  white-space: nowrap;
}

.ops-body{
  flex: 1;
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 18px;
  min-height: 0;
}

/* Left column is a locked stack: MAP then AGENCIES (between map + raw pager) */
.ops-left{
  display:flex;
  flex-direction: column;
  gap: 18px;
  min-height: 0;
}

:root{
  /* Brigade-tunable later; hard-coded sensible defaults for 1080p */
  --ops-addr-h: clamp(150px, 18vh, 230px);
  --ops-inc-h:  clamp(170px, 23vh, 290px);
  --ops-resp-h: clamp(70px,  10vh, 120px); /* match agencies height */
  --ops-ag-h:   clamp(70px,  10vh, 120px);
  --ops-footer-h: clamp(72px, 8.5vh, 105px);
}
/* Use dynamic viewport units where supported to avoid initial fullscreen/kiosk clipping
   (some Chromium builds update vh only after a user interaction). */
@supports (height: 1dvh) {
  :root{
    --ops-addr-h: clamp(150px, 18dvh, 230px);
    --ops-inc-h:  clamp(170px, 23dvh, 290px);
    --ops-resp-h: clamp(70px,  10dvh, 120px);
    --ops-ag-h:   clamp(70px,  10dvh, 120px);
    --ops-footer-h: clamp(72px, 8.5dvh, 105px);
  }
  .alert-card{ max-height: 92dvh; }
  .ops-raw{ min-height: clamp(60px, 7.5dvh, 92px); }
}



.ops-map{
  flex: 1;
  min-height: 0;
  background: rgba(255,255,255,0.94);
  border: 6px solid rgba(0,0,0,0.88);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 18px 50px rgba(0,0,0,0.35);
  display:flex;
}

.ops-map-inner{
  flex:1;
  display:flex;
  align-items:center;
  justify-content:center;
  background: repeating-linear-gradient(
    45deg,
    rgba(0,0,0,0.06),
    rgba(0,0,0,0.06) 12px,
    rgba(0,0,0,0.02) 12px,
    rgba(0,0,0,0.02) 24px
  );
}

.ops-map-placeholder{
  font-size: 72px;
  font-weight: 1000;
  opacity: 0.18;
  letter-spacing: 10px;
}

.ops-right{
  display:flex;
  flex-direction: column;
  gap: 18px;
  min-height: 0;
}

.ops-address,
.ops-incident,
.ops-responding,
.ops-agencies{
  background: rgba(255,255,255,0.96);
  border: 6px solid rgba(0,0,0,0.88);
  border-radius: 16px;
  padding: 18px 20px;
  box-shadow: 0 18px 50px rgba(0,0,0,0.35);
}

/* Lock right-hand boxes so the grid doesn't reflow when text is long */
.ops-address{ flex: 0 0 var(--ops-addr-h); overflow:hidden; }
.ops-incident{ flex: 0 0 var(--ops-inc-h); overflow:hidden; }
.ops-responding{ flex: 0 0 var(--ops-resp-h); overflow:hidden; }

/* Agencies now lives in the left stack under the map */
.ops-left .ops-agencies{ flex: 0 0 var(--ops-ag-h); overflow:hidden; }

.ops-address-main{
  display:block;
  padding-bottom: 8px;
  font-size: clamp(34px, 4.0vw, 62px);
  font-weight: 1000;
  text-transform: uppercase;
  line-height: 1.05;
}

.ops-address-sub{
  display:block;
  padding-bottom: 8px;
  margin-top: 10px;
  font-size: clamp(22px, 2.2vw, 36px);
  font-weight: 950;
  text-transform: uppercase;
  opacity: 0.95;
}

.ops-incident-text{
  display:block;
  padding-bottom: 8px;
  font-size: clamp(48px, 5.0vw, 86px);
  font-weight: 1000;
  text-transform: uppercase;
  line-height: 1.02;
}

.ops-agencies-text{
  display:block;
  padding-bottom: 8px;
  font-size: clamp(20px, 2.6vw, 40px);
  font-weight: 950;
  text-transform: uppercase;
  line-height: 1.1;
}


.ops-responding-text{
  display:block;
  padding-bottom: 8px;
  font-size: clamp(30px, 3.1vw, 52px);
  font-weight: 1000;
  text-transform: uppercase;
  line-height: 1.05;
  letter-spacing: 0.5px;
}

.ops-footer{
  display:grid;
  grid-template-columns: 2fr 1fr 0.7fr;
  gap: 18px;
}

.ops-raw,
.ops-ref,
.ops-timer{
  background: rgba(255,255,255,0.96);
  border: 6px solid rgba(0,0,0,0.88);
  border-radius: 16px;
  padding: 12px 16px;
  box-shadow: 0 18px 50px rgba(0,0,0,0.35);
  min-height: var(--ops-footer-h);
}


/* Reduce RAW pager box height (per kiosk request) */
.ops-raw{ min-height: clamp(60px, 7.5vh, 92px); }
.ops-raw-text{ max-height: 2.6em; }

.ops-footer-title{
  font-weight: 1000;
  font-size: 14px;
  letter-spacing: 1px;
  opacity: 0.7;
  text-transform: uppercase;
}

.ops-raw-text{
  display:block;
  padding-bottom: 8px;
  margin-top: 6px;
  font-weight: 900;
  font-size: 16px;
  line-height: 1.15;
  max-height: 999px;
  overflow: hidden;
}

.ops-ref-text{
  display:block;
  padding-bottom: 8px;
  margin-top: 8px;
  font-weight: 1000;
  font-size: clamp(24px, 2.6vw, 44px);
  text-transform: uppercase;
}

.ops-timer-text{
  display:block;
  padding-bottom: 8px;
  margin-top: 4px;
  font-weight: 1000;
  font-size: clamp(44px, 5vw, 86px);
  text-align: center;
  letter-spacing: 2px;
}

@media (max-width: 980px){
  .ops-body{ grid-template-columns: 1fr; }
  .ops-footer{ grid-template-columns: 1fr; }
}


/* =========================
   DEBUG INSPECTOR (toggle D)
   - Does NOT change the Ops UI layout
   ========================= */

.alert-debug{
  display:none;
  position:absolute;
  inset:18px;
  z-index: 9999;
  border-radius:18px;
  /* Charcoal backdrop for readability over the red Ops takeover */
  background: rgba(15,17,20,.96);
  border: 1px solid rgba(255,255,255,.12);
  color: #eaf0ff;
  padding:16px;
  overflow:auto;
  box-shadow: 0 18px 60px rgba(0,0,0,.55);
  pointer-events: none;
}

/* Support both the html.sa-debug toggle and the .hidden toggle used by app.js */
html.sa-debug .alert-debug{ display:block; }
.alert-debug.hidden{ display:none !important; }
.alert-debug *{ pointer-events: auto; }

.dbg-head{
  display:flex;
  justify-content:space-between;
  align-items:baseline;
  gap:12px;
  margin-bottom:12px;
}

.dbg-title{
  font-weight:900;
  letter-spacing:.08em;
}

.dbg-hint{
  opacity:.85;
  font-size:14px;
}

.dbg-grid{
  display:grid;
  grid-template-columns: 1fr 1fr;
  gap:12px;
}

.dbg-card{
  border:1px solid rgba(255,255,255,.12);
  border-radius:14px;
  padding:12px;
  background: rgba(255,255,255,.04);
  min-height:180px;
}

.dbg-card-title{
  font-weight:900;
  letter-spacing:.06em;
  text-transform:uppercase;
  font-size:12px;
  opacity:.9;
  margin-bottom:8px;
}

.dbg-kv{
  display:grid;
  gap:6px;
  font-size:13px;
}

.dbg-row{
  display:grid;
  grid-template-columns: 180px 1fr;
  gap:10px;
  border-bottom:1px dashed rgba(255,255,255,.08);
  padding-bottom:6px;
}

.dbg-k{ opacity:.9; font-weight:800; }
.dbg-v{ opacity:.95; word-break:break-word; }

.dbg-pre{
  margin:0;
  white-space:pre-wrap;
  word-break:break-word;
  font-size:12px;
  line-height:1.25;
  max-height:420px;
  overflow:auto;
}

.dbg-ack-btn{
  background: #ef4444;
  color: #111;
  border: none;
  border-radius: 10px;
  padding: 6px 14px;
  font-weight: 900;
  font-size: 12px;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0,0,0,.45);
}

.dbg-ack-btn:hover{
  filter: brightness(1.1);
}

@media (max-width: 1200px){
  .dbg-grid{ grid-template-columns: 1fr; }
  .dbg-row{ grid-template-columns: 140px 1fr; }
}


/* Ensure ops content never clips glyphs at the bottom edge */
.ops-address-main,
.ops-address-sub,
.ops-incident-text,
.ops-responding-text,
.ops-agencies-text,
.ops-ref-text,
.ops-timer-text,
.ops-raw-text{
  box-sizing: border-box;
}



/* =====================
   Auto-fit overflow fallback: marquee (only applied when JS marks data-marquee="1")
   ===================== */
.sa-marquee{
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: clip !important;
  position: relative;
  will-change: transform;
  padding-right: 28px; /* protect last glyphs */
}

.sa-marquee[data-marquee="1"]{
  animation: saMarquee var(--marqueeDur, 12s) linear infinite;
}

/* Gentle fade at right edge for readability on the white cards */
.sa-marquee::after{
  content: "";
  position: absolute;
  right: 0;
  top: 0;
  width: 44px;
  height: 100%;
  pointer-events: none;
  background: linear-gradient(to right, rgba(255,255,255,0), rgba(255,255,255,1));
}

@keyframes saMarquee{
  0%   { transform: translateX(0); }
  100% { transform: translateX(-45%); }
}


/* =====================
   ALERT OVERLAY: locked box layout (address/incident/units on right)
   agencies between map and raw; footer holds raw+mapref+timer
   ===================== */

/* Left column becomes a 2-row grid: MAP (big) + AGENCIES (short) */
.alert-ops .ops-left{
  display: grid;
  grid-template-rows: 1fr 0.22fr;
  gap: 18px;
  min-height: 0;
}

/* Agencies panel on left matches card styling */
.alert-ops .ops-agencies-left{
  background: rgba(255,255,255,.96);
  border: 4px solid #111;
  border-radius: 16px;
  box-shadow: 0 12px 26px rgba(0,0,0,.35);
  padding: 12px 14px;
  min-height: 0;
  overflow: hidden;
}

/* Right column: lock sizes (Address + Incident larger than Units) */
.alert-ops .ops-right{
  display: grid;
  grid-template-rows: 0.92fr 1.18fr 0.62fr; /* address, incident, units */
  gap: 18px;
  min-height: 0;
}

/* Ensure the three right cards behave as locked containers */
.alert-ops .ops-address,
.alert-ops .ops-incident,
.alert-ops .ops-responding{
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Footer: keep everything inside the viewport */
.alert-ops .ops-footer{
  display: grid;
  grid-template-columns: 1.75fr 0.65fr 0.65fr;
  gap: 18px;
  min-height: 0;
}

/* Text containers should not clip glyph descenders */
.alert-ops .ops-address-main,
.alert-ops .ops-address-sub,
.alert-ops .ops-incident-text,
.alert-ops .ops-responding-text,
.alert-ops .ops-agencies-text,
.alert-ops .ops-raw-text,
.alert-ops .ops-ref-text{
  padding-bottom: 6px;
  min-height: 0;
}

/* Marquee helper (only when we explicitly enable it per-box) */
.sa-marquee{
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: clip !important;
  will-change: transform;
}

.sa-marquee[data-marquee="1"]{
  animation: saMarquee var(--marqueeDur, 10s) linear infinite;
}

@keyframes saMarquee{
  0%   { transform: translateX(0); }
  100% { transform: translateX(calc(-1 * var(--marqueeShift, 35%))); }
}



/* ============================================================
   OPS ALERT LAYOUT: Agencies + Units locked as 2nd row (same height)
   - Row 1: MAP (left) + Address/Incident stack (right)
   - Row 2: Agencies (left) + Units (right) at identical height
   ============================================================ */

.ops-body{
  grid-template-rows: 1fr var(--ops-ag-h);
  align-items: stretch;
}

/* New wrapper for Address + Incident (row 1, right column) */
.ops-topright{
  grid-column: 2;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-height: 0;
}

.ops-map{
  grid-column: 1;
  grid-row: 1;
}

/* Address + Incident share the available height equally */
.ops-topright .ops-address,
.ops-topright .ops-incident{
  flex: 1 1 0 !important;
  min-height: 0;
  overflow: hidden;
}

/* Agencies + Units are the entire 2nd row, locked to same height */
.ops-agencies{
  grid-column: 1;
  grid-row: 2;
  height: var(--ops-ag-h);
  overflow: hidden;
}

.ops-responding{
  grid-column: 2;
  grid-row: 2;
  height: var(--ops-ag-h);
  overflow: hidden;
  flex: 0 0 var(--ops-ag-h) !important;
}

/* ================================
   Text fit tweaks – prevent clipping
   ================================ */

/* ADDRESS */
#opsAddress .ops-value{
  font-size: clamp(26px, 3.2vw, 38px);
  line-height: 1.08;
}

/* INCIDENT DETAILS */
#opsIncident .ops-value{
  font-size: clamp(28px, 3.4vw, 40px);
  line-height: 1.08;
}

/* AGENCIES NOTIFIED */
#opsAgencies .ops-value{
  font-size: clamp(24px, 3vw, 34px);
  line-height: 1.1;
}


/* =====================================================
   Units notified: match agencies sizing + prevent clipping
   ===================================================== */
#opsResponding .ops-responding-text{
  line-height: 1.12 !important;
  padding-bottom: 14px !important; /* protect descenders inside locked card */
  display: flex;
  align-items: center;
  height: 100%;
  white-space: nowrap;
}

/* =========================================================
   LOCKED UX: Marquees are forbidden (alert overlay + dashboard).
   Safety net: if any element accidentally gets .sa-marquee, disable
   animation and allow wrapping so it won't scroll or clip unexpectedly.
   ========================================================= */
.sa-marquee,
.sa-marquee[data-marquee="1"]{
  animation: none !important;
  transform: none !important;
  white-space: normal !important;
}
.sa-marquee::after{ display:none !important; }



/* Safety note card (only shown when present) */
#alertTurnoutNotesCard{
  border-color: #ff0000; /* bright red */
}
#alertTurnoutNotesCard .ops-footer-title{
  color: #ff0000;
}
#alertTurnoutNotes{
  font-weight: 900;
  line-height: 1.05;
  white-space: normal;       /* allow 2 lines */
  word-break: break-word;
  overflow: hidden;
}


/* ===== SAFETY NOTE (only shown when present) ===== */
#alertTurnoutNotesCard{
  border-color: #ff0000 !important;
  border-width: 6px !important;
}
#alertTurnoutNotes{
  font-weight: 900;
  white-space: normal;
  line-height: 1.05;
}


/* --- Safety note layout + styling tweaks (locked below pager message) --- */
.ops-footer-left{
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 18px;
  min-height: 0;
}

/* Safety note card: match other box thickness, but bright red border + white background */
#alertTurnoutNotesCard{
  border-color: #ff0000 !important;
  background: rgba(255,255,255,0.96) !important;
}

/* Safety note text: bold, wrap, and let JS autofit handle size */
#alertTurnoutNotes{
  font-weight: 900;
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.05;
}


/* SAFETY NOTE */

#alertTurnoutNotesCard.ops-card.ops-safety{
  /* keep same border thickness as other cards; only change colour */
  border-color: #ff0000;
  background: #ffffff;
}
#alertTurnoutNotes{
  font-weight: 800;
  line-height: 1.12;
  /* allow wrapping to 2 lines */
  white-space: normal;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}


/* =========================
   Turnout Map (Leaflet)
   ========================= */
.ops-map-inner{
  position: relative;
}

.turnout-map{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  display:none; /* shown when map is active */
}

.ops-map-overlay{
  position:absolute;
  left:10px;
  top:10px;
  z-index: 500; /* above tiles */
  pointer-events:none;
  background: rgba(0,0,0,0.62);
  color:#fff;
  padding: 8px 10px;
  border-radius: 10px;
  font-weight: 800;
  font-size: 16px;
  line-height: 1.15;
  box-shadow: 0 10px 20px rgba(0,0,0,0.35);
}

.ops-map-status{
  white-space: pre-line;
}

#turnoutMapPlaceholder{
  position: relative;
  z-index: 1;
}

/* Leaflet defaults need explicit height via container; we provide it above. */
.leaflet-container{
  font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
}

/* Keep controls readable on large displays */
.leaflet-control{
  box-shadow: 0 10px 22px rgba(0,0,0,0.25);
}


/* =========================
   AUX overlay (Hb/QD)
   ========================= */
.auxOverlay{
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
}
.auxOverlayBox{
  pointer-events: auto;
  max-width: 72vw;
  margin: 18px auto 0 auto;
  background: rgba(0,0,0,0.55);
  color: #fff;
  border: 2px solid rgba(255,255,255,0.25);
  border-radius: 14px;
  padding: 14px 16px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.auxOverlayTitle{
  font-weight: 700;
  letter-spacing: 0.06em;
  margin-bottom: 8px;
}
.auxOverlayBody{
  font-size: 18px;
  line-height: 1.25;
  white-space: pre-wrap;
  word-break: break-word;
}
.auxOverlayHint{
  margin-top: 10px;
  opacity: 0.85;
  font-size: 13px;
}


/* =========================
   Early support-call overlay
   ========================= */
.supportEarlyOverlay{
  position: fixed;
  inset: 0;
  z-index: 10020;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  padding: 24px;
}
.supportEarlyOverlay.hidden{
  display: none !important;
}
.supportEarlyOverlayBox{
  pointer-events: none;
  width: min(1100px, 82vw);
  background: rgba(0,0,0,0.68);
  color: #fff;
  border: 2px solid rgba(255,255,255,0.24);
  border-radius: 18px;
  padding: 22px 28px;
  box-shadow: 0 18px 45px rgba(0,0,0,.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  text-align: center;
}
.supportEarlyOverlayTitle{
  font-size: clamp(28px, 3.6vw, 54px);
  font-weight: 900;
  letter-spacing: 0.06em;
  margin-bottom: 10px;
}
.supportEarlyOverlayBody{
  font-size: clamp(24px, 3vw, 42px);
  line-height: 1.18;
  font-weight: 700;
  white-space: pre-wrap;
  word-break: break-word;
}
