  :root{
    --bg:#050a16; --bg2:#0a1426; --card:#0e1a30; --card2:#16243f; --line:#223450;
    --txt:#eef3fb; --mut:#8ea3c6; --accent:#3d8bff; --accent2:#7ad1ff;
    --hi:#ffffff; --lo:#5fb4ff; --good:#39d98a; --warn:#ffcc55; --bad:#ff5a6e;
    --shadow:0 14px 50px rgba(0,0,0,.4); --maxw:1240px; --mainw:var(--maxw);
  }
  *{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
  /* --bg lives on html, not body, so it can act as the permanent ultimate fallback underneath
     #siteBackdrop (the optional CMS-driven image, see site-chrome.js's renderBackdrop()) --
     body's own two gradients paint on top of that, and the backdrop image (when active) paints
     on top of THOSE, below real content. Nothing here changes what today's plain background
     looks like when no backdrop is active. */
  html{background:var(--bg)}
  body{margin:0;background:
        radial-gradient(1100px 500px at 80% -8%, #16335e 0, transparent 60%),
        radial-gradient(900px 500px at 0% 0%, #0d2348 0, transparent 55%);
       color:var(--txt);font:1rem/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;min-height:100vh}
  #siteBackdrop{display:none;position:fixed;inset:0;z-index:-1;background-size:cover;
    background-position:center;background-repeat:no-repeat;pointer-events:none}
  #siteBackdrop.on{display:block}
  .wrap{max-width:var(--maxw);margin:0 auto;padding:0 1.4rem}
  a{color:inherit;text-decoration:none}
  svg.ic{display:block}
  /* real weather glyphs (same set as the admin dashboard), tinted via CSS mask */
  .wxi{display:inline-block;background-color:currentColor;-webkit-mask:var(--wxu) center/contain no-repeat;mask:var(--wxu) center/contain no-repeat}
  .wglyph{display:inline-block;vertical-align:middle} /* shared layout for both masked + two-tone icons */

  /* ---- brand bar ---- */
  /* Lowered from f2/cc (~95%/80%) so an active #siteBackdrop shows through -- header stays
     position:sticky and #siteBackdrop stays position:fixed, so both track the viewport the
     same way and won't drift apart on scroll. backdrop-filter:blur(12px) already does the real
     work of keeping nav text readable regardless of what's behind it, so this can go fairly
     transparent without a legibility cost. */
  header{position:sticky;top:0;z-index:20;background:linear-gradient(#050a1699,#050a1680);backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
  .bar{max-width:var(--mainw);display:flex;align-items:center;gap:1.1rem;padding:.85rem 1.4rem}
  /* Horizontal wordmark PNG (BubbleWeb-Text.png, transparent bg) replacing the plain-text logo
     -- same single-row header, just swapping what sits in .logo (Kyle, 2026-09-04). */
  .logo{display:flex;align-items:center}
  .logo img{display:block;height:80px;width:auto}
  nav{display:flex;gap:.15rem;margin-left:.6rem;align-items:center}
  nav .nav-item{position:relative}
  nav a{color:var(--mut);padding:.4rem .75rem;border-radius:5px;font-size:.86rem;font-weight:700;letter-spacing:.3px}
  nav a.active,nav a:hover{color:var(--txt);background:var(--card2)}
  /* The submenu grows directly out of the parent link's own highlight (same background, flush
     corners, no border) instead of floating as a separate card -- reads as the nav item's
     background extending downward, not a popup sitting on top of the text. */
  nav .nav-item:hover>a,nav .nav-item:focus-within>a{color:var(--txt);background:var(--card2);border-radius:5px 5px 0 0}
  nav .nav-children{display:none;position:absolute;top:100%;left:0;min-width:100%;background:var(--card2);
    border-radius:0 5px 5px 5px;padding:.2rem;box-shadow:0 10px 22px rgba(0,0,0,.3);z-index:50}
  nav .nav-item:hover .nav-children,nav .nav-item:focus-within .nav-children{display:block}
  nav .nav-children a{display:block;white-space:nowrap;border-radius:4px}
  .mobile-nav-toggle{display:none;width:42px;height:42px;padding:9px;border:1px solid var(--line);border-radius:8px;background:var(--card2);color:var(--txt);cursor:pointer}
  .mobile-nav-toggle span:not(.sr-only){display:block;width:100%;height:2px;margin:4px 0;border-radius:2px;background:currentColor;transition:transform .18s ease,opacity .18s ease}
  .mobile-nav-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(6px) rotate(45deg)}
  .mobile-nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
  .mobile-nav-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}
  .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
  .right{margin-left:auto;display:flex;align-items:center;gap:.7rem;color:var(--mut)}
  /* Not scoped to .right -- site-chrome.js relocates .soc into #siteNav on mobile (see the
     single-hamburger merge below), and a .right-only selector silently stopped matching
     there, leaving the Discord <img> with no width/height constraint at all (it rendered at
     nearly full-screen size instead of a small icon). */
  .soc{display:flex;gap:.5rem}
  .soc a{width:30px;height:30px;display:grid;place-items:center;border-radius:8px;background:var(--card2);font-size:.8rem;font-weight:800;cursor:pointer;color:var(--mut);border:1px solid transparent}
  .soc a:hover{color:var(--txt);border-color:var(--line);background:#1b2b4a}
  .social-icon-image{display:block;width:62%;height:62%;object-fit:contain}
  /* Percentage sizing only resolves reliably against a parent with a definite, stable width --
     fine for the footer's own single fixed context, fragile here since .soc a now renders
     inside two different DOM parents (its own dropdown on desktop, #siteNav once merged on
     mobile) with different flex/grid contexts. Fixed pixels sidestep that entirely. */
  .soc a .social-icon-image{width:18px;height:18px}
  /* Same sizing as .social-icon-image at each of its call sites, for the masked (recolored)
     icon variant -- background-color:currentColor lets it inherit whatever color the
     surrounding link is already rendered in (including :hover), instead of hardcoding one. */
  .social-icon-mask{display:block;width:62%;height:62%;background-color:currentColor;
    -webkit-mask-size:contain;-webkit-mask-position:center;-webkit-mask-repeat:no-repeat;
    mask-size:contain;mask-position:center;mask-repeat:no-repeat}
  .soc a .social-icon-mask{width:18px;height:18px}
  .textsize{display:flex;align-items:center;gap:.1rem;border:1px solid var(--line);border-radius:6px;padding:.15rem .25rem;background:var(--card2)}
  .textsize .ts-lbl{font-size:.62rem;color:var(--mut);font-weight:800;text-transform:uppercase;letter-spacing:.4px;margin:0 .3rem 0 .15rem}
  .textsize button{background:none;border:none;color:var(--mut);cursor:pointer;font-weight:900;line-height:1;padding:.2rem .4rem;border-radius:4px}
  .textsize button:hover{color:var(--txt)}
  .textsize button.on{background:var(--accent);color:#03101f}
  .textsize button.s1{font-size:.72rem} .textsize button.s2{font-size:.9rem} .textsize button.s3{font-size:1.1rem}
  /* Utility menu: social icons, text size, Account, About -- pulled off the main bar (which
     was getting crunched on desktop too, not just mobile) into one always-available dropdown
     at the far right. Built by site-chrome.js's initUtilityMenu(), which relocates the
     existing .textsize/.soc elements in place rather than duplicating their markup. */
  .util-menu{position:relative}
  .util-toggle{width:42px;height:42px;padding:9px;border:1px solid var(--line);border-radius:8px;
    background:var(--card2);color:var(--txt);cursor:pointer}
  .util-toggle span:not(.sr-only){display:block;width:100%;height:2px;margin:4px 0;border-radius:2px;background:currentColor}
  .util-toggle:hover{border-color:var(--accent2);color:var(--txt)}
  .util-toggle[aria-expanded="true"]{border-color:var(--accent2);background:#1b2b4a}
  .util-panel{display:none;position:absolute;top:calc(100% + 10px);right:0;min-width:210px;
    background:var(--card2);border:1px solid var(--line);border-radius:10px;padding:.9rem;
    box-shadow:0 14px 34px rgba(0,0,0,.4);z-index:60}
  .util-panel.open{display:block}
  .util-section{padding-bottom:.8rem;margin-bottom:.8rem;border-bottom:1px solid var(--line)}
  .util-section:last-child{padding-bottom:0;margin-bottom:0;border-bottom:0}
  .util-label{font-size:.62rem;color:var(--mut);font-weight:800;text-transform:uppercase;
    letter-spacing:.4px;margin-bottom:.5rem}
  .util-links{display:flex;flex-direction:column;gap:.15rem}
  .util-links a{font-size:.82rem;font-weight:700;color:var(--txt);padding:.4rem .3rem;border-radius:6px}
  .util-links a:hover{background:#1b2b4a}
  .util-panel .textsize{width:100%;justify-content:space-between}
  .util-panel .soc{flex-wrap:wrap}
  /* nav-l/nav-r (leftover from splitting nav around a centered header logo, before Kyle asked
     to move the menu into the status bar instead) stay permanently inert -- display:contents
     dissolves them into flat nav children everywhere, at every width. .nav-logo-space (a spacer
     element from that same earlier attempt) is likewise always hidden. Neither is removed from
     the markup since nothing downstream depends on that; both are just dead weight now. */
  .nav-l,.nav-r{display:contents}
  .nav-logo-space{display:none}
  @media(min-width:1024px){
    /* Kyle: bigger centered logo alone in the top bar; the actual nav (#siteNav, the same
       element used for mobile's hamburger drawer, physically relocated by initStatusbarNav() in
       site-chrome.js, not cloned) moves down into the status bar in its place, replacing each
       page's tagline (hidden below, not deleted -- it's different text per page, e.g. "Every
       active NWS alert." on alerts.html, not just the homepage's "Not your granny's forecast").
       .citysearch already self-pushes right via margin-left:auto, so nav just needs to sit
       plainly at the row's start. */
    header .bar{position:relative;min-height:151px}
    header .logo{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:2}
    header .logo img{height:125px}
    .statusbar .tag{display:none}
    .statusbar .wrap nav{display:flex;align-items:center;gap:1rem;margin-left:0}
  }
  @media(max-width:820px){
    header .bar{position:relative}
    header nav{display:none}
    .mobile-nav-toggle{display:block;margin-left:auto;flex:0 0 auto}
    header .right{margin-left:0}
    /* Logo was the first in-flow child, so it sat flush left with the hamburger pushed to the
       far right -- centering it the same absolute+translate way as the desktop logo, which
       also means .bar needs an explicit floor tall enough for it now that it's not in flow. */
    header .bar{min-height:98px}
    header .logo{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}
    /* One hamburger on mobile, not two -- the utility panel's own trigger hides here since
       site-chrome.js relocates the panel itself into #siteNav at this breakpoint, so the
       existing nav hamburger opens both nav links and utility content together. */
    .util-menu{display:none}
    header nav .util-panel{
      display:block;position:static;min-width:0;margin:.5rem 0 0;padding:.7rem 0 0;
      background:transparent;border:0;border-top:1px solid var(--line);border-radius:0;
      box-shadow:none
    }
    header nav.mobile-nav-open{
      display:flex;position:absolute;top:calc(100% + 1px);left:1.4rem;right:1.4rem;
      margin:0;padding:.5rem;flex-direction:column;align-items:stretch;gap:.15rem;
      max-height:calc(100vh - 76px);overflow-y:auto;background:#0a1426;
      border:1px solid var(--line);border-top:2px solid var(--accent2);border-radius:0 0 9px 9px;
      box-shadow:0 18px 38px rgba(0,0,0,.55);z-index:60
    }
    header nav.mobile-nav-open a{display:block;width:100%;padding:.72rem .8rem;font-size:.88rem}
    header nav.mobile-nav-open .nav-item{width:100%}
    header nav.mobile-nav-open .nav-children{display:block;position:static;min-width:0;margin:.1rem 0 .25rem .65rem;padding:0 0 0 .45rem;background:transparent;border:0;border-left:1px solid var(--line);border-radius:0;box-shadow:none}
    header nav.mobile-nav-open .nav-children a{font-size:.78rem;padding:.5rem .7rem}
  }

  /* ---- status strip ---- */
  .statusbar{border-bottom:1px solid var(--line);background:linear-gradient(90deg,#0b1830,#0a1426)}
  .statusbar .wrap{max-width:var(--mainw);display:flex;align-items:center;gap:.8rem;padding:.6rem 1.4rem;flex-wrap:wrap}
  .statusbar .lab{color:var(--accent2);font-weight:900;font-size:.72rem;letter-spacing:1px}
  .statusbar .msg{font-weight:700;font-size:.86rem}
  .statusbar .emoji{font-size:1rem}
  .bubblecon{display:inline-flex;align-items:center;gap:.4rem;border:1px solid var(--line);border-radius:5px;padding:.22rem .5rem;background:var(--card2);white-space:nowrap}
  .bubblecon .bc-dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto;box-shadow:0 0 6px currentColor}
  .bubblecon b{font-size:.68rem;font-weight:900;letter-spacing:.5px}
  .bubblecon #bcDesc{font-size:.6rem;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--mut)}
  @media(max-width:720px){.bubblecon #bcDesc{display:none}}
  .statusbar .tag{font-size:.86rem;font-weight:900;letter-spacing:.6px;color:var(--mut)}
  .statusbar .tag b{color:var(--accent2)}
  @media(max-width:620px){.statusbar .tag{display:none}}
  .citysearch{position:relative;margin-left:auto;display:flex;align-items:center;gap:.4rem;background:var(--card2);border:1px solid var(--line);border-radius:6px;padding:.3rem .6rem;min-width:210px;transition:border-color .15s}
  .cs-results{position:absolute;top:calc(100% + 6px);right:0;left:auto;z-index:40;min-width:min(280px,88vw);background:var(--card);border:1px solid var(--line);border-radius:8px;box-shadow:var(--shadow);overflow:hidden;max-height:min(60vh,360px);overflow-y:auto}
  .cs-results[hidden]{display:none}
  .cs-item{display:flex;align-items:baseline;justify-content:space-between;gap:.7rem;padding:.5rem .7rem;cursor:pointer;border-bottom:1px solid var(--line)}
  .cs-item:last-child{border-bottom:0}
  .cs-item:hover,.cs-item.on{background:var(--card2)}
  .cs-item .nm{font-weight:700;font-size:.84rem;color:var(--txt)}
  .cs-item .st{color:var(--mut);font-size:.72rem;font-weight:800;letter-spacing:.5px}
  .cs-hint{padding:.6rem .7rem;font-size:.76rem;color:var(--mut)}
  .citysearch:focus-within{border-color:var(--accent2)}
  .citysearch .cs-ic{font-size:.78rem;opacity:.65;line-height:1}
  .citysearch input{flex:1;min-width:0;background:none;border:0;outline:none;color:var(--txt);font:inherit;font-size:.8rem;font-weight:600}
  .citysearch input::placeholder{color:var(--mut);font-weight:600}
  .citysearch input::-webkit-search-cancel-button{filter:invert(.5)}
  @media(max-width:620px){.citysearch{margin-left:0;flex:1 1 100%;min-width:0}}

  /* ---- layout ---- */
  main.wrap{max-width:var(--mainw);padding-top:1.1rem;padding-bottom:2.5rem}
  .cols{display:grid;gap:1.1rem;grid-template-columns:1fr}
  @media(min-width:1000px){.cols{grid-template-columns:1fr 360px;align-items:start}}
  .colmain,.colside{display:grid;grid-template-columns:minmax(0,1fr);gap:1.1rem;min-width:0}
  .colmain>*,.colside>*{min-width:0}
  .sidebar-shell{display:grid;grid-template-columns:minmax(0,1fr);gap:1.1rem;min-width:0}

  .card{background:var(--card);border:1px solid var(--line);border-radius:6px;box-shadow:var(--shadow)}
  .pad{padding:1.1rem 1.25rem}
  .ctitle{display:flex;align-items:center;justify-content:space-between;margin:0 0 .8rem}
  .ctitle h2{position:relative;margin:0;font-size:.95rem;font-weight:900;letter-spacing:1px;text-transform:uppercase}
  .ctitle a{color:var(--accent2);font-size:.7rem;font-weight:800;letter-spacing:.6px}
  .info-btn{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;margin-left:.45rem;
    border-radius:50%;border:1px solid var(--mut);color:var(--mut);background:transparent;
    font-size:.6rem;font-weight:800;font-style:italic;font-family:Georgia,serif;line-height:1;
    cursor:pointer;vertical-align:middle;padding:0;text-transform:none;letter-spacing:0}
  .info-btn:hover,.info-btn[aria-expanded="true"]{color:var(--txt);border-color:var(--txt)}
  .info-pop{position:absolute;top:100%;left:0;margin-top:.5rem;z-index:20;width:240px;max-width:calc(100vw - 3rem);
    background:var(--card2);border:1px solid var(--line);border-radius:10px;padding:.65rem .8rem;
    font-size:.72rem;font-weight:400;line-height:1.45;letter-spacing:normal;text-transform:none;color:var(--txt);
    box-shadow:0 8px 24px rgba(0,0,0,.3)}

  /* ---- current hero ---- */
  .hero{position:relative;overflow:hidden;padding:1.3rem 1.4rem;
    /* Left-fade over the background photo. Each line is one stop: rgba(14,26,48, OPACITY) POSITION%
       OPACITY: 1.00 = fully dark (hides image) ... 0.00 = clear (shows image).  POSITION: 0%=left, 100%=right.
       (14,26,48 is the card color — change it to tint the fade.) Add/remove stops freely. */
    background:linear-gradient(90deg,
      rgba(14,26,48,1)   0%,     /* far left  */
      rgba(14,26,48,0.85)  25%,     /* quarter in */
      rgba(14,26,48,0.6)  50%,     /* halfway   */
      rgba(14,26,48,0.25) 100%      /* right edge */
    ), url('./assets/images/northdakota/littlemissouri.webp') right center/cover no-repeat}
  .hero-title{margin:0 0 .7rem;font-size:.85rem;font-weight:900;letter-spacing:1.2px;text-transform:uppercase;color:var(--txt)}
  .hero-loading,.hero-error{display:none}
  .hero.is-loading .hero-loading{display:block}
  .hero.is-loading .hero-content,.hero.has-error .hero-content{display:none}
  .hero.has-error .hero-error{display:flex}
  .hero-loading{min-height:181px}
  .hero-sk{display:block;border-radius:999px;background:linear-gradient(100deg,rgba(116,137,170,.16) 25%,rgba(175,197,230,.3) 42%,rgba(116,137,170,.16) 59%);background-size:300% 100%;animation:hero-shimmer 1.35s ease-in-out infinite}
  .sk-loc{width:138px;height:12px}
  .sk-main{display:flex;align-items:center;gap:1rem;margin:.65rem 0 .35rem}
  .sk-temp{width:126px;height:70px;border-radius:8px}
  .sk-icon{width:66px;height:66px;border-radius:50%}
  .sk-cond{width:168px;height:17px;margin-bottom:.45rem}
  .sk-feels{width:112px;height:11px}
  .sk-details{display:flex;flex-wrap:wrap;gap:.9rem 1.7rem;margin-top:1.05rem}
  .sk-details .hero-sk{width:72px;height:27px;border-radius:5px}
  .hero-error{min-height:181px;flex-direction:column;justify-content:center;gap:.35rem;color:var(--txt)}
  .hero-error b{font-size:1rem}
  .hero-error span{color:var(--mut);font-size:.88rem}
  .weather-panel{position:relative;overflow:hidden}
  .weather-panel-loading,.weather-panel-error{display:none}
  .weather-panel.is-loading>:not(.weather-panel-loading),
  .weather-panel.has-error>:not(.weather-panel-error){display:none}
  .weather-panel.is-loading>.weather-panel-loading{display:grid}
  .weather-panel.has-error>.weather-panel-error{display:flex}
  .weather-panel-loading{grid-template-columns:repeat(6,minmax(36px,1fr));align-items:end;gap:.8rem;min-height:112px}
  .weather-panel-loading span{display:block;height:72px;border-radius:7px;background:linear-gradient(100deg,rgba(116,137,170,.16) 25%,rgba(175,197,230,.3) 42%,rgba(116,137,170,.16) 59%);background-size:300% 100%;animation:hero-shimmer 1.35s ease-in-out infinite}
  .weather-panel-loading span:nth-child(2n){height:94px}
  .weather-panel-loading span:nth-child(3n){height:58px}
  .weather-panel-error{min-height:112px;align-items:center;color:var(--mut);font-weight:800;font-size:.9rem}
  #todayCard .weather-panel-loading{min-height:238px}
  #todayCard .weather-panel-loading span{height:150px}
  #todayCard .weather-panel-loading span:nth-child(2n){height:198px}
  #weekCard .weather-panel-loading{min-height:104px}
  #indexesCard .weather-panel-loading{grid-template-columns:1fr 1fr;min-height:245px}
  #indexesCard .weather-panel-loading span{height:105px}
  @keyframes hero-shimmer{0%{background-position:100% 0}100%{background-position:0 0}}
  @media(max-width:620px){.weather-panel-loading{grid-template-columns:repeat(3,1fr)}}
  @media(prefers-reduced-motion:reduce){.hero-sk,.weather-panel-loading span{animation:none}}
  .hero .loc{display:flex;align-items:center;justify-content:space-between;color:var(--mut);font-size:.82rem;font-weight:800;letter-spacing:.5px}
  .hero .loc-pin{color:var(--bad);display:inline-flex;align-items:center;margin-right:.4rem}
  .hero .loc-pin svg{width:13px;height:13px;display:block}
  .heromid{display:flex;align-items:center;gap:1rem;margin:.6rem 0 .2rem}
  .heromid .t{font-family:"Roboto",system-ui,sans-serif;font-size:min(4.8rem,20vw);font-weight:500;letter-spacing:-2px;line-height:1}
  /* Roboto across all temperature readings + forecast highs/lows */
  .hour .d,.wday .hi,.wday .lo,.ndmap .c .tp{font-family:"Roboto",system-ui,sans-serif}
  .hero .cond{color:var(--accent2);font-weight:800;font-size:1.15rem;margin-top:.1rem}
  .hero .feels{color:var(--mut);font-size:.9rem;margin-top:.15rem}
  .hero .det{display:flex;flex-wrap:wrap;gap:.9rem 1.7rem;margin-top:1rem}
  .hero .met{display:flex;flex-direction:column;gap:.12rem}
  .hero .met span{font-size:.64rem;text-transform:uppercase;letter-spacing:.6px;color:var(--mut);font-weight:800}
  .hero .met b{font-size:.95rem;color:var(--txt);font-weight:800}
  .sitrep{margin-top:1rem;display:inline-flex;align-items:center;gap:.45rem;max-width:100%;
    background:linear-gradient(90deg,#12233f,#16243f);border:1px solid var(--line);border-radius:6px;
    padding:.4rem .7rem;font-weight:900;font-size:.82rem;letter-spacing:.4px}
  .sitrep[hidden]{display:none}   /* .sitrep's display would otherwise override the hidden attribute */
  .sitrep .sr-lbl{color:var(--accent2);letter-spacing:1px}
  .sitrep .sr-text{color:var(--txt)}
  .quip{margin-top:.7rem;border-left:3px solid var(--accent);padding:.4rem 0 .4rem .8rem;color:var(--txt);font-style:italic;font-size:.9rem}
  .quip .qm{color:var(--accent);font-weight:900;font-style:normal;margin-right:.2rem}

  /* ---- alert banner ---- */
  .alert{display:flex;align-items:center;gap:.9rem;padding:.85rem 1.1rem;border-radius:6px;border:1px solid #5a2230;
    background:linear-gradient(90deg,#3a121c,#2a0e16);width:100%;margin-bottom:1.1rem;text-align:left}
  .alert.hide{display:none}
  .alert .ab{width:34px;height:34px;border-radius:5px;background:var(--bad);color:#fff;display:grid;place-items:center;font-size:1.15rem;font-weight:1000;flex:0 0 auto;text-shadow:0 1px 2px rgba(0,0,0,.35)}
  .alert .ab .wxi{display:block;text-shadow:none}
  .alert .alabel{font-weight:900;letter-spacing:1px;text-transform:uppercase;font-size:1rem;color:#fff;white-space:nowrap;flex:0 1 auto}
  .alert .adiv{align-self:stretch;width:1px;background:rgba(255,255,255,.28);flex:0 0 auto}
  .alert .adesc{flex:1 1 auto;min-width:0;font-size:.9rem;color:#eef3fb}
  .alert .av{margin-left:auto;flex:0 0 auto;background:rgba(0,0,0,.28);border:1px solid rgba(255,255,255,.28);color:#fff;border-radius:5px;padding:.45rem .7rem;font-size:.72rem;font-weight:800;cursor:pointer}
  .alert .until{opacity:.85;font-weight:700}
  @media(max-width:620px){
    .alert{display:grid;grid-template-columns:44px minmax(0,1fr);align-items:center;gap:.65rem .85rem;padding:1rem;border-radius:8px}
    .alert .ab{grid-column:1;grid-row:1 / span 2;width:44px;height:44px;font-size:1.3rem}
    .alert .alabel{grid-column:2;font-size:1.02rem;line-height:1.18;white-space:normal;overflow-wrap:normal}
    .alert .adiv{display:none}
    .alert .adesc{grid-column:2;font-size:.86rem;line-height:1.35;overflow-wrap:normal;word-break:normal}
    .alert .av{grid-column:1 / -1;margin-left:0;width:100%;text-align:center;padding:.7rem .8rem;font-size:.78rem;letter-spacing:.4px}
  }

  /* ---- closures/cancellations bar -- breaking-news red (Kyle's call, 2026-08-31), with a
     scrolling ticker once there's more than one closure for the county ---- */
  .closures-bar{display:flex;align-items:center;gap:.9rem;padding:.85rem 1.1rem;border-radius:6px;border:1px solid #5c1620;
    background:linear-gradient(90deg,#3d0e14,#220810);width:100%;margin-bottom:1.1rem;text-align:left;text-decoration:none}
  .closures-bar.hide{display:none}
  .closures-bar .cb{width:34px;height:34px;border-radius:5px;background:#c81e34;color:#fff;display:grid;place-items:center;font-size:1.15rem;font-weight:1000;flex:0 0 auto;
    animation:cbPulse 2s ease-in-out infinite}
  /* school.svg is a hardcoded-black shape (like alerts.html's icon set) -- treated as a mask
     and filled white, same trick used there, rather than a plain <img> that can't recolor. */
  .closures-bar .cb-icon{width:19px;height:19px;background-color:#fff;
    -webkit-mask:url('./assets/icons/school.svg') center/contain no-repeat;
    mask:url('./assets/icons/school.svg') center/contain no-repeat}
  @keyframes cbPulse{0%,100%{box-shadow:0 0 0 0 rgba(200,30,52,.55)}50%{box-shadow:0 0 0 7px rgba(200,30,52,0)}}
  .closures-bar .cblabel{font-weight:900;letter-spacing:1px;text-transform:uppercase;font-size:1rem;color:#fff;white-space:nowrap;flex:0 1 auto}
  .closures-bar .cbdiv{align-self:stretch;width:1px;background:rgba(255,255,255,.28);flex:0 0 auto}
  .closures-bar .cbdesc{flex:1 1 auto;min-width:0;font-size:.9rem;color:#fdeaec;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
  .closures-bar.ticker .cbdesc{text-overflow:clip;-webkit-mask-image:linear-gradient(90deg,transparent,#000 20px,#000 calc(100% - 20px),transparent);mask-image:linear-gradient(90deg,transparent,#000 20px,#000 calc(100% - 20px),transparent)}
  .closures-bar .cbdesc-track{display:inline-flex;white-space:nowrap}
  .closures-bar .cbdesc-track span{padding-right:2.5rem}
  .closures-bar.ticker .cbdesc-track{animation:cbTicker 22s linear infinite}
  @keyframes cbTicker{from{transform:translateX(0)}to{transform:translateX(-50%)}}
  .closures-bar .cbv{margin-left:auto;flex:0 0 auto;background:rgba(0,0,0,.28);border:1px solid rgba(255,255,255,.28);color:#fff;border-radius:5px;padding:.45rem .7rem;font-size:.72rem;font-weight:800}
  @media (prefers-reduced-motion: reduce){
    .closures-bar .cb{animation:none}
    .closures-bar.ticker .cbdesc-track{animation:none}
    .closures-bar.ticker .cbdesc{text-overflow:ellipsis;mask-image:none;-webkit-mask-image:none}
  }
  @media(max-width:620px){
    .closures-bar{display:grid;grid-template-columns:44px minmax(0,1fr);align-items:center;gap:.65rem .85rem;padding:1rem;border-radius:8px}
    .closures-bar .cb{grid-column:1;grid-row:1 / span 2;width:44px;height:44px;font-size:1.3rem}
    .closures-bar .cb-icon{width:24px;height:24px}
    .closures-bar .cblabel{grid-column:2;font-size:1.02rem;line-height:1.18;white-space:normal;overflow-wrap:normal}
    .closures-bar .cbdiv{display:none}
    .closures-bar .cbdesc{grid-column:2;font-size:.86rem;line-height:1.35}
    .closures-bar .cbv{grid-column:1 / -1;margin-left:0;width:100%;text-align:center;padding:.7rem .8rem;font-size:.78rem;letter-spacing:.4px}
  }

  /* ---- full alert detail page ---- */
  .alert-page{position:fixed;inset:0;z-index:60;background:rgba(3,7,15,.9);backdrop-filter:blur(6px);overflow-y:auto;padding:2rem 1rem}
  .alert-page.hidden{display:none}
  .alert-doc{max-width:760px;margin:0 auto;background:var(--card);border:1px solid var(--line);border-radius:6px;overflow:hidden;box-shadow:var(--shadow)}
  .alert-count{text-align:center;color:var(--mut);font-size:.72rem;font-weight:800;letter-spacing:.6px;text-transform:uppercase;padding-top:.8rem;border-top:1px solid var(--line);margin-top:.4rem}
  .alert-pager{display:flex;align-items:center;justify-content:center;gap:.4rem;padding:.6rem 1.4rem 1.3rem}
  .alert-pager button{min-width:34px;height:34px;border:1px solid var(--line);background:var(--card2);color:var(--txt);border-radius:5px;font-weight:800;font-size:.85rem;cursor:pointer;display:grid;place-items:center;padding:0 .5rem;transition:.12s}
  .alert-pager button:hover:not(:disabled):not(.on){background:var(--line)}
  .alert-pager button.on{background:var(--accent);border-color:var(--accent);color:#03101f}
  .alert-pager .pg-arrow{font-size:1.2rem}
  .alert-pager button:disabled{opacity:.3;cursor:default}
  .alert-doc .ah{position:relative;padding:1.3rem 1.4rem;color:#fff}
  .alert-doc .ah .ev{font-size:1.5rem;font-weight:900;letter-spacing:.3px;padding-right:2.2rem}
  .alert-doc .ah .hd{opacity:.92;font-size:.9rem;margin-top:.35rem;line-height:1.35}
  .alert-close-x{position:absolute;top:.9rem;right:.9rem;width:32px;height:32px;display:flex;align-items:center;justify-content:center;
    border-radius:8px;border:1px solid rgba(255,255,255,.35);background:rgba(0,0,0,.28);color:#fff;
    font-size:1.05rem;font-weight:900;line-height:1;cursor:pointer;transition:background .12s}
  .alert-close-x:hover{background:rgba(0,0,0,.45)}
  .alert-chips{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.8rem}
  .alert-chips span{background:rgba(0,0,0,.28);border:1px solid rgba(255,255,255,.3);border-radius:999px;padding:.22rem .65rem;font-size:.68rem;font-weight:800;letter-spacing:.4px;text-transform:uppercase}
  .alert-body{padding:1.2rem 1.4rem}
  .alert-meta{display:grid;grid-template-columns:1fr 1fr;gap:.7rem 1rem;margin-bottom:.4rem}
  .alert-meta span{font-size:.66rem;text-transform:uppercase;letter-spacing:.6px;color:var(--mut);font-weight:800}
  .alert-meta b{color:var(--txt);display:block;font-weight:800;font-size:.9rem;margin-top:.15rem}
  .alert-sec{margin-top:1.2rem}
  .alert-sec h4{margin:0 0 .4rem;font-size:.7rem;text-transform:uppercase;letter-spacing:1px;color:var(--accent2)}
  .alert-sec p{margin:0;white-space:pre-wrap;font-size:.92rem;line-height:1.55;color:#dce6f5}
  .alert-actions{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:1.5rem}
  .alert-actions a,.alert-actions button{border:1px solid var(--line);background:var(--card2);color:var(--txt);border-radius:6px;padding:.6rem .95rem;font-weight:800;font-size:.82rem;cursor:pointer;text-decoration:none}
  .alert-actions .primary{background:var(--accent);border-color:var(--accent);color:#03101f}

  /* ---- radar ---- */
  .radarwrap{position:relative;min-height:340px;border-radius:6px;overflow:hidden;border:1px solid var(--line);background:#091324}
  .radarwrap iframe{position:absolute;inset:0;width:100%;height:100%;border:0;z-index:1;background:#091324}
  .radarwait{position:absolute;inset:0;z-index:2;display:grid;place-items:center;background:#091324;color:var(--accent2);
    font-size:.72rem;font-weight:900;letter-spacing:.8px;pointer-events:none}
  .radarwrap.is-ready .radarwait{display:none}
  .radarplace{position:absolute;left:.65rem;bottom:.65rem;z-index:3;padding:.35rem .55rem;border:1px solid #ffffff24;
    border-radius:6px;background:#06101dcc;color:#a8bdd8;font-size:.62rem;font-weight:900;letter-spacing:.55px;
    pointer-events:none;backdrop-filter:blur(5px)}
  .radarplace span{color:#eaf3ff}

  /* ---- today's forecast ---- */
  .today-card{padding-top:1.5rem;padding-bottom:1.6rem;min-width:0}
  .today-card.almanac-mode{box-shadow:inset 0 3px 0 var(--accent2),var(--shadow)}
  .today-head{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;margin-bottom:1.2rem}
  .today-head>div{min-width:0}
  .today-head h2{margin:0;font-size:.95rem;font-weight:900;letter-spacing:1px;text-transform:uppercase}
  .today-sub{color:var(--mut);font-size:.8rem;font-style:italic;margin-top:.2rem}
  .today-view-toggle{flex:0 0 auto;border:1px solid var(--line);background:var(--card2);color:var(--accent2);border-radius:5px;padding:.45rem .7rem;font:800 .67rem/1 inherit;letter-spacing:.55px;cursor:pointer}
  .today-view-toggle:hover,.today-view-toggle:focus-visible{border-color:var(--accent2);color:var(--txt);outline:none}
  .today-forecast-view[hidden],.today-almanac-view[hidden]{display:none}
  .today-forecast-panel,.today-almanac-panel{border:1px solid rgba(122,209,255,.17);border-radius:9px;
    background:linear-gradient(115deg,rgba(24,65,119,.34),rgba(8,20,38,.18));overflow:hidden}
  .today-hero-lockup{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:stretch;gap:0;
    margin:0;padding:1rem 1.1rem;overflow:hidden;container-type:inline-size}
  .today-phrase-block{position:relative;min-width:0;display:flex;align-items:center;justify-content:center;text-align:center;
    padding:.25rem clamp(.55rem,1vw,.9rem);border-left:1px solid rgba(122,209,255,.16)}
  .today-headline{margin:0;color:#f4f8ff;font-family:"Roboto",system-ui,sans-serif;
    font-size:clamp(2.15rem,4.7vw,3.4rem);font-weight:900;line-height:1;letter-spacing:-.06em}
  .today-headline-line{display:inline-block;white-space:nowrap}
  .today-headline-word{display:inline-block}
  .today-headline-line.first .today-headline-word{color:#f4f8ff}
  /* Fallback only -- the real per-word color comes from daily-forecast-headline.js's
     colorForWord(), applied as an inline style on each word by what it actually says (cloudy=
     grey, rainy=blue, hot=orange, ...). This still catches the rare unmapped word (an idiomatic
     phrase's non-classified second word, e.g. "spicy"/"hazardous"/"manageable"). */
  .today-headline-line.second .today-headline-word:not(.connector){color:#ff704d}
  .today-headline-word.connector{color:#9eb3cf;font-size:.6em;letter-spacing:.01em;text-transform:uppercase;transform:translateY(-.08em)}
  .today-full{color:var(--accent2);font-size:.72rem;font-weight:800;letter-spacing:.5px;white-space:nowrap}
  .today-narr{color:var(--txt);font-size:.92rem;line-height:1.45;margin:.7rem 0 1rem}
  .today2{display:grid;grid-template-columns:1fr;gap:1.4rem}
  @media(min-width:660px){.today2{grid-template-columns:1fr 262px}}
  .today-right{border-top:1px solid var(--line);padding-top:1rem}
  @media(min-width:660px){.today-right{border-top:0;border-left:1px solid var(--line);padding:.1rem 0 0 1.2rem}}
  .today-main{display:flex;align-items:center;justify-content:center;gap:1.15rem;min-width:0;
    padding:.25rem clamp(1.5rem,2vw,2rem) .25rem clamp(.5rem,1vw,.8rem)}
  .today-hilo2{display:flex;align-items:flex-end;gap:.6rem;font-family:"Roboto",system-ui,sans-serif}
  .today-hilo2 .hl{display:flex;flex-direction:column;line-height:1}
  .today-hilo2 .lbl{font-size:.62rem;letter-spacing:1px;color:var(--mut);font-weight:800;margin-bottom:.3rem}
  .today-hilo2 b{font-size:min(4.05rem,15vw);font-weight:700;letter-spacing:0}
  .today-hilo2 .hi{color:#ff9f45} .today-hilo2 .lo{color:var(--lo)}
  .today-hilo2 .slash{color:var(--line);font-size:min(2.9rem,12vw);font-weight:300;align-self:center;margin-bottom:.2rem}
  @container (max-width:850px){
    .today-main{gap:.65rem;padding:.25rem 1.15rem .25rem .35rem}
    .today-main #todayIc .wxi,.today-main #todayIc .wglyph{width:82px!important;height:82px!important;flex:0 0 82px}
    .today-hilo2{gap:.3rem}
    .today-hilo2 b{font-size:clamp(2.5rem,7.8cqw,2.9rem)}
    .today-hilo2 .slash{font-size:clamp(1.7rem,5.2cqw,2.2rem);margin-bottom:.1rem}
    .today-headline{font-size:clamp(2.35rem,7.8cqw,2.95rem)}
  }
  .today-almanac-main{display:flex;flex-direction:column;align-items:center;justify-content:center;min-width:0;padding:.5rem 0 1.35rem;text-align:center}
  .today-almanac-kicker{color:var(--accent2);font-size:.64rem;font-weight:900;letter-spacing:.9px;text-transform:uppercase;margin-bottom:.55rem}
  .today-normal-hilo{justify-content:center}
  .today-almanac-basis{color:var(--mut);font-size:.62rem;line-height:1.3;margin-top:.55rem}
  @media(max-width:720px){
    .today-head{margin-bottom:1rem}
    .today-hero-lockup{grid-template-columns:minmax(0,1fr);gap:.75rem;padding:.85rem .8rem 1rem;margin-bottom:0}
    .today-main{gap:.45rem;justify-content:center;padding:.1rem .35rem}
    .today-main #todayIc{display:inline-flex}
    .today-main #todayIc .wxi,.today-main #todayIc .wglyph{width:56px!important;height:56px!important;flex:0 0 56px}
    .today-phrase-block{justify-content:center;text-align:center;border-left:0;border-top:1px solid rgba(122,209,255,.16);padding:.8rem .35rem 0}
    .today-headline{font-size:clamp(2rem,11vw,2.7rem);line-height:1;letter-spacing:-.045em}
    .today-headline-line.is-long{font-size:.7em;letter-spacing:-.025em}
    .today-headline-line.is-xlong{font-size:.58em;letter-spacing:-.01em}
    .today-hilo2{gap:.25rem}
    .today-hilo2 b{font-size:clamp(2rem,10.5vw,2.65rem)}
    .today-hilo2 .slash{font-size:1.65rem;margin-bottom:.1rem}
    .today-hilo2 .lbl{font-size:.52rem;letter-spacing:.5px}
    .today-view-toggle{font-size:.61rem;padding:.4rem .55rem}
  }
  @media(max-width:350px){
    .today-hero-lockup{padding:.75rem .55rem .9rem}
    .today-main #todayIc .wxi,.today-main #todayIc .wglyph{width:50px!important;height:50px!important;flex-basis:50px}
    .today-headline{font-size:2rem}
    .today-hilo2 b{font-size:2rem}
    .today-hilo2 .slash{font-size:1.45rem}
  }
  .today-pill{display:inline-flex;align-items:center;gap:.55rem;flex-wrap:wrap;background:var(--card2);border:1px solid var(--line);border-radius:6px;padding:.5rem .8rem;margin:.9rem 0;font-size:.8rem;color:var(--mut)}
  .today-pill b{color:var(--txt);font-weight:800} .today-pill .pdot{color:var(--line)}
  .today-metrics{display:grid;grid-template-columns:repeat(6,1fr);gap:0;border-top:1px solid rgba(122,209,255,.14);padding:.55rem 0}
  .today-metrics .tm{padding:.7rem .2rem;display:flex;flex-direction:column;align-items:center;gap:.2rem;text-align:center;border-left:1px solid transparent}
  .today-metrics .tm+.tm{border-left-color:rgba(122,209,255,.16)}
  .today-metrics .tm-ic{font-size:1.05rem;line-height:1;height:24px;display:flex;align-items:center;justify-content:center}
  .today-metrics .tm-ic svg{width:22px;height:22px;display:block}
  .today-metrics #sunriseIc svg,.today-metrics #sunsetIc svg{width:29px;height:29px}
  .today-metrics .tm span{font-size:.54rem;text-transform:uppercase;letter-spacing:.3px;color:var(--mut);font-weight:800}
  .today-metrics .tm b{font-size:.9rem;font-weight:900;white-space:nowrap}
  @media(max-width:660px){.today-metrics{grid-template-columns:repeat(3,1fr)}}
  .today-metrics .tm small{font-size:.58rem;color:var(--mut);line-height:1.1}
  .today-almanac-metrics{grid-template-columns:repeat(6,1fr)}
  .today-almanac-metrics .tm-ic{font-size:1.35rem;font-weight:900}
  .today-almanac-metrics .record-high-icon,.today-almanac-metrics .record-high{color:#ff9f45}
  .today-almanac-metrics .record-low-icon,.today-almanac-metrics .record-low{color:var(--lo)}
  .today-almanac-metrics .record-precip-icon,.today-almanac-metrics .record-precip{color:var(--lo)}
  .today-almanac-metrics .yesterday-high-icon,.today-almanac-metrics .yesterday-high{color:#ffb15e}
  .today-almanac-metrics .yesterday-low-icon,.today-almanac-metrics .yesterday-low{color:#78c1ff}
  .today-almanac-metrics .yesterday-precip-icon,.today-almanac-metrics .yesterday-precip{color:var(--lo)}
  @media(max-width:660px){.today-almanac-metrics{grid-template-columns:repeat(3,1fr)}}
  .today-arc{display:flex;align-items:center;gap:.5rem;margin-top:.7rem;background:var(--card2);border-radius:6px;padding:.5rem .8rem}
  .today-arc .se{text-align:center;flex:0 0 auto}
  .today-arc .se span{display:block;font-size:.56rem;text-transform:uppercase;letter-spacing:.5px;color:var(--mut);font-weight:800}
  .today-arc .se b{font-size:.92rem}
  .today-arc .arc{flex:1;height:26px;min-width:40px}
  .timeline{display:flex;flex-direction:column;gap:1.35rem;justify-content:center;height:100%}
  .tp-row{display:flex;gap:.6rem;align-items:flex-start}
  .tp-head{font-weight:900;font-size:.8rem;text-transform:uppercase;letter-spacing:.5px;display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
  .tp-temp{background:var(--card2);border:1px solid var(--line);border-radius:999px;padding:.1rem .55rem;font-size:.64rem;color:var(--accent2);font-weight:800;letter-spacing:0}
  .tp-desc{color:var(--mut);font-size:.82rem;line-height:1.35;margin-top:.15rem}
  .today-summary{margin-top:1.3rem;background:linear-gradient(135deg,#12294c,#0d1a30);border:1px solid var(--line);border-radius:6px;padding:1.1rem 1.15rem;font-size:.95rem;line-height:1.55;color:#e9eef7}
  .today-forecast-panel>.today-summary,.today-almanac-panel>.today-summary{margin-top:0;background:rgba(8,20,38,.22);border:0;border-top:1px solid rgba(122,209,255,.14);
    border-radius:0;padding:1rem 1.15rem}

  /* ---- public weather leaderboard ---- */
  .leaders-status{color:var(--mut);font-size:.7rem;font-weight:800;letter-spacing:.35px}
  .leaders-head-right{display:flex;flex-direction:column;align-items:flex-end;gap:.45rem}
  .leaders-card{min-width:0}
  .leaders-head{display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;margin-bottom:1.25rem}
  .leaders-head h1{margin:.18rem 0 .3rem;font-size:clamp(1.75rem,4vw,2.65rem);line-height:1;font-weight:900;letter-spacing:-.035em}
  .leaders-head p{margin:0;color:var(--mut);font-size:.88rem}
  .leaders-kicker{color:var(--accent2);font-size:.64rem;font-weight:900;letter-spacing:1px;text-transform:uppercase}
  .leaders-scope,.leaders-mode,.leaders-metrics{display:flex;gap:.32rem;flex-wrap:wrap}
  .leaders-scope{padding:.2rem;background:#081528;border:1px solid var(--line);border-radius:5px}
  .leaders-scope button,.leaders-mode button,.leaders-metrics button{border:1px solid #2a3e5e;background:#0b192d;color:#a8b8d1;border-radius:4px;
    padding:.5rem .78rem;font:800 .64rem/1 "Roboto",system-ui,sans-serif;letter-spacing:.45px;text-transform:uppercase;cursor:pointer;transition:background .15s,border-color .15s,color .15s}
  .leaders-scope button{border-color:transparent;background:transparent}
  .leaders-scope button:hover,.leaders-mode button:hover,.leaders-metrics button:hover{color:var(--txt);border-color:#5bb4ff88;background:#10233e}
  .leaders-scope button.active,.leaders-mode button.active,.leaders-metrics button.active{background:#1d63a8;border-color:#5bb4ff;color:#fff;box-shadow:inset 0 -2px 0 rgba(255,255,255,.12)}
  .leaders-controls{display:flex;flex-direction:column;gap:.55rem;border:1px solid rgba(122,209,255,.13);border-radius:6px;padding:.7rem;background:#081528}
  .leaders-control-row{display:flex;align-items:center;gap:.75rem;min-width:0}
  .leaders-control-label{flex:0 0 60px;color:#6f85a7;font-size:.55rem;font-weight:900;letter-spacing:.9px;text-transform:uppercase}
  .leaders-mode,.leaders-metrics{min-width:0}
  .leaders-meta{display:flex;flex-wrap:wrap;gap:.35rem .8rem;color:var(--mut);font-size:.66rem;font-weight:700;margin:.85rem 0}
  .leaders-meta span+span:before{content:"•";margin-right:.8rem;color:#486381}
  .leaders-podium{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.7rem;margin:1rem 0}
  .podium-rank{--medal:#ffca3a;position:relative;min-width:0;text-align:left;background:linear-gradient(145deg,#10243f,#09172a);border:1px solid #2b3e5b;
    border-top:3px solid var(--medal);border-radius:5px;padding:.85rem .9rem .9rem;overflow:hidden;box-shadow:0 12px 28px rgba(0,0,0,.2)}
  .podium-rank:after{content:"";position:absolute;width:150px;height:150px;right:-65px;top:-70px;border-radius:50%;background:var(--medal);opacity:.055;pointer-events:none}
  .podium-rank.rank-1{--medal:#ffca3a;border-color:#94782d;box-shadow:0 14px 32px rgba(130,95,0,.18)}
  .podium-rank.rank-2{--medal:#c7d3df;border-color:#68798b}
  .podium-rank.rank-3{--medal:#c47a43;border-color:#765036}
  .podium-award{position:relative;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.4rem}
  .podium-award>span{display:flex;flex-direction:column;color:var(--medal);font-size:.55rem;font-weight:900;letter-spacing:.8px;text-transform:uppercase}
  .podium-award b{font-size:.72rem;line-height:1.1;letter-spacing:.55px}
  .podium-trophy{display:block;width:38px;height:38px;flex:0 0 38px;background:var(--medal);
    -webkit-mask:url("./assets/icons/trophy.svg") center/contain no-repeat;mask:url("./assets/icons/trophy.svg") center/contain no-repeat;filter:drop-shadow(0 3px 6px rgba(0,0,0,.35))}
  .rank-1 .podium-trophy{width:44px;height:44px;flex-basis:44px}
  .podium-category{display:block;color:#758aa9;font-size:.53rem;font-weight:900;letter-spacing:.65px;text-transform:uppercase}
  .podium-rank strong{position:relative;z-index:1;display:block;font:900 clamp(1.65rem,4vw,2.45rem)/1 "Roboto",system-ui,sans-serif;margin:.3rem 0 .4rem;color:#fff}
  .podium-rank h3{position:relative;z-index:1;margin:0;font-size:.82rem;line-height:1.2}
  .leader-station-link{color:inherit;text-decoration:none}
  .leader-station-link span{color:var(--accent2);font-size:.78em}
  .leader-station-link:hover,.leader-station-link:focus-visible{color:var(--accent2);text-decoration:underline;text-underline-offset:3px}
  .podium-rank small{display:block;color:var(--mut);font-size:.58rem;line-height:1.3;margin-top:.35rem}
  .leaders-table-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:8px}
  .leaders-table{width:100%;border-collapse:collapse;min-width:460px;font-size:.74rem}
  .leaders-table th{padding:.62rem .7rem;background:#09172b;color:var(--mut);font-size:.59rem;text-transform:uppercase;letter-spacing:.45px;text-align:right}
  .leaders-table th:nth-child(2){text-align:left}
  .leaders-table td{padding:.68rem .7rem;border-top:1px solid rgba(122,209,255,.1);text-align:right;white-space:nowrap}
  .leaders-table td:nth-child(2){text-align:left;white-space:normal}
  .leaders-table td small{display:block;color:var(--mut);font-size:.58rem;margin-top:.12rem}
  .leaders-table .rank-cell{width:30px;color:var(--mut);font-weight:900}
  .leaders-table .national-rank{display:inline-grid;margin:auto}
  .leaders-table .value-cell{color:var(--accent2);font-size:.88rem;font-weight:900}
  .leaders-empty{grid-column:1/-1;text-align:center;color:var(--mut);padding:2rem 1rem;border:1px dashed var(--line);border-radius:8px}
  .leaders-showmore{display:block;width:100%;padding:.8rem;border:1px solid rgba(91,180,255,.5);border-radius:9px;
    background:#173a6b;color:#eaf4ff;font:900 .78rem/1 inherit;letter-spacing:.35px;
    text-transform:uppercase;cursor:pointer;text-align:center;transition:background .15s,border-color .15s}
  .leaders-showmore:hover,.leaders-showmore:focus-visible{background:#1f4d8c;border-color:#5bb4ff}
  .leaders-showmore-wrap:has(.leaders-showmore){margin-top:1.3rem}
  .national-intro{display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;padding-top:.25rem;margin-bottom:1rem}
  .national-intro h2{margin:.22rem 0 0;font-size:1.35rem}
  .national-intro a{color:var(--accent2);font-size:.66rem;font-weight:900;letter-spacing:.5px}
  .national-extremes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.8rem}
  .national-extreme{position:relative;min-width:0;border:1px solid var(--line);border-radius:9px;padding:1.15rem;background:#0c1d35;overflow:hidden}
  .national-extreme:after{content:"";position:absolute;inset:0;pointer-events:none;opacity:.26}
  .national-extreme.is-hot:after{background:radial-gradient(circle at 100% 0,#ff6f3c,transparent 55%)}
  .national-extreme.is-cold:after{background:radial-gradient(circle at 100% 0,#4aaeff,transparent 55%)}
  .national-label{position:relative;z-index:1;color:var(--mut);font-size:.66rem;font-weight:900;letter-spacing:.7px;text-transform:uppercase}
  .national-extreme strong{position:relative;z-index:1;display:block;font:900 clamp(3rem,8vw,5.1rem)/.95 "Roboto",system-ui,sans-serif;margin:.65rem 0}
  .national-extreme.is-hot strong{color:#ff8d54}.national-extreme.is-cold strong{color:#5bb4ff}
  .national-extreme ul{position:relative;z-index:1;list-style:none;padding:0;margin:.45rem 0 .7rem}
  .national-extreme li{font-size:.86rem;font-weight:800;line-height:1.35;margin:.15rem 0}
  .national-extreme small{position:relative;z-index:1;color:var(--mut);font-size:.6rem}
  .national-standings{margin-top:1.35rem;padding-top:1.2rem;border-top:1px solid var(--line)}
  .national-standings-head{display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;margin-bottom:.8rem}
  .national-standings-head h3{margin:.18rem 0 0;font-size:1.25rem}
  .national-standings-head .leaders-meta{justify-content:flex-end;margin:0}
  .national-topten{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.8rem}
  .national-ranking{border:1px solid var(--line);border-radius:8px;background:#09172b;overflow:hidden}
  .national-ranking h4{margin:0;padding:.7rem .85rem;border-bottom:1px solid var(--line);font-size:.78rem;letter-spacing:.6px;text-transform:uppercase}
  .national-ranking.is-hot h4{color:#ff8d54}.national-ranking.is-cold h4{color:#5bb4ff}
  .national-ranking ol{list-style:none;padding:0;margin:0}
  .national-ranking li{display:grid;grid-template-columns:2rem minmax(0,1fr) auto;align-items:center;gap:.6rem;padding:.58rem .75rem;border-top:1px solid rgba(122,209,255,.09)}
  .national-ranking li:first-child{border-top:0}
  .national-rank{display:grid;place-items:center;width:1.55rem;height:1.55rem;border:1px solid #2b4363;border-radius:50%;color:var(--mut);font-size:.62rem;font-weight:900}
  .national-rank.rank-1{border-color:#e9bc42;color:#ffd55c}.national-rank.rank-2{border-color:#a9bdd5;color:#dbe8f7}.national-rank.rank-3{border-color:#b8733f;color:#e5a16e}
  .national-station{min-width:0;font-size:.72rem;font-weight:800}
  .national-station small{display:block;color:var(--mut);font-size:.55rem;font-weight:600;margin-top:.08rem}
  .national-ranking li>strong{font-size:1rem}
  .national-ranking.is-hot li>strong{color:#ff8d54}.national-ranking.is-cold li>strong{color:#5bb4ff}
  .national-standings.is-unavailable .national-topten{display:none}
  .leaders-note{color:var(--mut);font-size:.7rem;line-height:1.5;margin:1rem 0 0;padding-top:.85rem;border-top:1px solid var(--line)}
  .leaders-error{border:1px solid #ff5a6e55;background:#3b1420;color:#ffd9df;border-radius:8px;padding:1rem;font-weight:700}
  @media(max-width:720px){
    .leaders-head,.national-intro{align-items:flex-start;flex-direction:column}
    .leaders-scope{width:100%}.leaders-scope button{flex:1}
    .leaders-podium{grid-template-columns:1fr}
    .podium-rank{padding:.8rem .9rem}
    .podium-rank strong{font-size:1.85rem}
    .leaders-control-row{align-items:flex-start;flex-direction:column;gap:.35rem}
    .leaders-control-label{flex-basis:auto}
    .national-extremes,.national-topten{grid-template-columns:1fr}
    .national-standings-head{align-items:flex-start;flex-direction:column}
    .national-standings-head .leaders-meta{justify-content:flex-start}
    .leaders-status{display:none}
  }
  @media(max-width:620px){
    header .bar{height:auto;min-height:98px;flex-wrap:wrap;padding-top:.5rem;padding-bottom:.5rem}
    header .right{width:100%;justify-content:flex-end}
  }
  /* Hourly detail charts (Details toggle) */
  .hourly-charts{display:flex;flex-direction:column;gap:.6rem;margin-top:.5rem}
  .hchart-tabs{display:flex;gap:.4rem;flex-wrap:wrap}
  .hchart-tab{background:var(--card2);border:1px solid var(--line);color:var(--mut);border-radius:999px;padding:.35rem .85rem;font-size:.74rem;font-weight:800;letter-spacing:.2px;cursor:pointer}
  .hchart-tab:hover{color:var(--txt);border-color:var(--mut)}
  .hchart-tab.active{background:var(--accent);border-color:var(--accent);color:#fff}
  .hchart-head{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;margin-bottom:.2rem}
  .hchart-t{font-size:.8rem;font-weight:800;letter-spacing:.3px;color:var(--txt)}
  .hchart-leg{display:flex;gap:.75rem;font-size:.68rem;color:var(--mut)}
  .hchart-leg span{display:inline-flex;align-items:center;gap:.3rem}
  .hchart-leg i{width:11px;height:11px;border-radius:2px;display:inline-block;flex:0 0 auto}
  .hchart-svg{width:100%;height:auto;display:block;overflow:visible}
  .hchart-plot{position:relative;touch-action:pan-y}
  .hchart-cross{position:absolute;top:0;bottom:0;width:1px;background:var(--accent2);opacity:.6;pointer-events:none}
  .hchart-tip{position:absolute;top:0;background:var(--card2);border:1px solid var(--line);border-radius:7px;padding:.35rem .55rem;font-size:.72rem;line-height:1.35;color:var(--txt);pointer-events:none;white-space:nowrap;z-index:3;box-shadow:0 6px 18px rgba(0,0,0,.4)}
  .hchart-tip b{color:var(--accent2)}
  /* Banner ad slots (CMS: ad_banners) -- same bordered-card treatment as the Discord/donate
     boxes beside it (background/border/radius/shadow on the slot itself, not just the image),
     so a live ad reads as one more clean card in the sidebar instead of a label-plus-image
     floating loose above everything else. */
  .ad-slot{background:var(--card);border:1px solid var(--line);border-radius:6px;box-shadow:var(--shadow);
    padding:.85rem .85rem 1rem;overflow:hidden}
  .ad-label{font-size:.56rem;text-transform:uppercase;letter-spacing:.6px;color:var(--mut);opacity:.7;margin-top:.55rem;text-align:center}
  .ad-slot a{display:block}
  .ad-slot img{display:block;width:100%;height:auto;border-radius:8px}
  .ad-fallback{display:block;padding:2rem 1rem;text-align:center;color:var(--mut);font-size:.85rem}

  /* ---- hourly ---- */
  .hourwrap{position:relative}
  .hours{display:flex;gap:.5rem;overflow-x:auto;padding:.2rem 0 .4rem;scroll-behavior:smooth;scrollbar-width:none;-ms-overflow-style:none}
  .hours::-webkit-scrollbar{display:none}
  /* arrows overlay the strip edges and fade in on hover — cards stay full-width */
  .harrow{position:absolute;top:50%;transform:translateY(-50%);z-index:3;width:36px;height:36px;border-radius:50%;
    border:1px solid var(--line);background:#0e1a30e6;backdrop-filter:blur(4px);color:var(--accent2);
    font-size:1.35rem;font-weight:900;line-height:1;cursor:pointer;display:grid;place-items:center;
    box-shadow:0 6px 18px rgba(0,0,0,.5);opacity:0;transition:opacity .16s ease,background .12s,color .12s,border-color .12s}
  #hPrev{left:.15rem} #hNext{right:.15rem}
  .hourwrap:hover .harrow:not(:disabled),
  .hourwrap:focus-within .harrow:not(:disabled){opacity:1}
  .harrow:hover:not(:disabled){background:var(--accent);color:#03101f;border-color:var(--accent)}
  .harrow:disabled{opacity:0;pointer-events:none}
  @media(hover:none){.harrow:not(:disabled){opacity:1}} /* touch: no hover, so always show */
  .hour{flex:0 0 auto;width:84px;text-align:center;background:var(--card2);border-radius:5px;padding:.8rem .3rem}
  .hour .t{color:var(--mut);font-size:.78rem;font-weight:700}
  .hour .ic{margin:.35rem auto}
  .hour .d{font-size:1.25rem;font-weight:900}
  .hour .p{color:var(--accent2);font-size:.72rem;margin-top:.2rem}

  /* ---- 7 day ---- */
  .week{display:grid;grid-template-columns:repeat(7,1fr);gap:.4rem}
  .wday{text-align:center;border-radius:5px;padding:.7rem .2rem;border:1px solid transparent;
    display:block;text-decoration:none;color:inherit;cursor:pointer;transition:background .12s}
  .wday:hover{background:rgba(122,209,255,.1)}
  .wday+.wday{border-left-color:rgba(122,209,255,.16)} /* subtle blue divider between days */
  .wday .nm{font-weight:800;font-size:.8rem;letter-spacing:.5px}
  /* center both icon types as blocks so every day lines up vertically */
  .wday .wglyph,.hour .wglyph{display:block;margin:.35rem auto}
  .wday .hi{font-size:1.2rem;font-weight:900}
  .wday .lo{font-size:.95rem;font-weight:800;color:var(--lo)}
  .wday .pp{color:var(--accent2);font-size:.7rem;margin-top:.15rem}
  @media(max-width:620px){
    .week{
      display:flex;
      gap:.4rem;
      overflow-x:auto;
      overscroll-behavior-x:contain;
      scroll-snap-type:x proximity;
      -webkit-overflow-scrolling:touch;
      padding-bottom:.15rem;
      scrollbar-width:none;
    }
    .week::-webkit-scrollbar{display:none}
    .wday{
      flex:0 0 29%;
      min-width:96px;
      scroll-snap-align:start;
    }
  }

  /* ---- ND map ---- */
  .ndmap{position:relative;min-height:230px;border-radius:5px;overflow:hidden;border:1px solid var(--line);
    background:radial-gradient(600px 300px at 50% 40%,#12325a,transparent 70%),#0a1a30}
  .ndmap .c{position:absolute;text-align:center;transform:translate(-50%,-50%);cursor:pointer}
  .ndmap .c .nm{font-size:.66rem;color:#bcd0f0;font-weight:700}
  .ndmap .c .tp{font-size:1rem;font-weight:900}
  .ndmap .c.on .tp{color:var(--accent2)}

  /* ---- indexes ---- */
  .idx{display:flex;align-items:center;gap:.8rem;padding:.6rem 0;border-bottom:1px solid var(--line)}
  .idx:last-child{border-bottom:0}
  .idx .ii{width:34px;height:34px;border-radius:5px;background:var(--card2);display:grid;place-items:center;font-size:1.05rem;flex:0 0 auto}
  .idx .il{flex:1;min-width:0}
  .idx .il .n{font-size:.7rem;color:var(--mut);text-transform:uppercase;letter-spacing:.6px;font-weight:800}
  .idx .il .s{font-size:.66rem;color:var(--mut)}
  .idx .iv{text-align:right;font-weight:900;font-size:.9rem}
  .idx .iv small{display:block;font-size:.62rem;font-weight:700;letter-spacing:.3px}

  /* ---- news placeholder ---- */
  .story{overflow:hidden}
  .story .ph{position:relative;height:150px;background:repeating-linear-gradient(45deg,#12233f 0 12px,#0e1c34 12px 24px);display:grid;place-items:center}
  .story .ph .tag{position:absolute;top:.7rem;left:.7rem;background:#4a1320;color:#ffb3bd;font-size:.62rem;font-weight:900;letter-spacing:.6px;padding:.25rem .5rem;border-radius:6px}
  .story .ph .cms{color:var(--mut);font-size:.78rem;font-weight:700;text-align:center;padding:0 1rem}
  .story .body{padding:1rem 1.1rem}
  .story .body h3{margin:.1rem 0 .3rem;font-size:1.05rem;font-weight:900;line-height:1.2;color:var(--mut)}
  .story .body .meta{color:var(--mut);font-size:.72rem;margin-bottom:.6rem}
  .skel{height:.7rem;border-radius:5px;background:var(--card2);margin:.4rem 0}
  /* One consistent "latest posts" sidebar treatment everywhere it appears: thumbnail (or the
     repeating-diagonal placeholder when a post has none) + headline + date on its own line
     underneath. display:block on .rt/.rd is what makes them stack -- without it they'd sit as
     flex-row siblings of .th instead (the earlier per-page drift this replaces). */
  .related a{display:flex;gap:.7rem;align-items:center;padding:.6rem 0;border-bottom:1px solid var(--line);text-decoration:none}
  .related a:last-child{border-bottom:0}
  .related a:hover .rt{color:var(--accent2)}
  .related .th{width:52px;height:40px;border-radius:8px;background:repeating-linear-gradient(45deg,#12233f 0 8px,#0e1c34 8px 16px);flex:0 0 auto}
  .related .rt{display:block;font-size:.84rem;font-weight:700;line-height:1.25;color:var(--txt);transition:color .12s}
  .related .rd{display:block;font-size:.68rem;color:var(--mut);margin-top:.2rem}

  /* ---- cta / hotline ---- */
  .cta{text-align:center;padding:1.2rem 1.1rem;background:linear-gradient(160deg,#12294c,#0d1a30)}
  .cta .big{font-weight:900;font-size:1.15rem;letter-spacing:.3px}
  .cta .big b{color:var(--accent2)}
  .cta .sub{color:var(--mut);font-size:.8rem;margin:.35rem 0 .8rem}
  .cta .stores{display:flex;gap:.5rem;justify-content:center}
  .cta .stores span{background:#000;border:1px solid var(--line);border-radius:5px;padding:.5rem .7rem;font-size:.72rem;font-weight:800;cursor:pointer}
  .sidebar-promo{padding:0;overflow:hidden;border-color:#263b66;background:
    radial-gradient(circle at 12% 5%,rgba(88,101,242,.18),transparent 35%),
    linear-gradient(155deg,#101c35 0%,#111b31 100%);box-shadow:0 12px 28px rgba(0,0,0,.2)}
  .sidebar-promo-link{display:flex;flex-direction:column;padding:1.15rem;color:var(--txt);text-align:left;text-decoration:none}
  .sidebar-promo-link:hover{background:rgba(88,101,242,.045)}
  .sidebar-promo-link:focus-visible{outline:3px solid var(--accent2);outline-offset:-4px}
  .sidebar-promo .promo-top{display:flex;align-items:center;gap:.65rem;width:100%}
  .sidebar-promo .promo-discord-logo{display:block;width:38px;height:38px;padding:7px;box-sizing:border-box;object-fit:contain;flex:0 0 38px;border:1px solid rgba(126,139,255,.3);border-radius:10px;background:rgba(88,101,242,.13)}
  .sidebar-promo .promo-kicker{display:block;min-width:0;flex:1;color:#c5d1e7;font-size:.63rem;font-weight:900;letter-spacing:.75px}
  .sidebar-promo .promo-live{display:inline-flex;align-items:center;gap:.3rem;border:1px solid rgba(78,210,139,.25);border-radius:999px;background:rgba(28,133,77,.12);color:#81e8ae;padding:.25rem .4rem;font-size:.55rem;font-weight:900;letter-spacing:.5px}
  .sidebar-promo .promo-live i{width:6px;height:6px;border-radius:50%;background:#4ed28b;box-shadow:0 0 0 3px rgba(78,210,139,.12)}
  .sidebar-promo .promo-copy{display:block;margin-top:.9rem}
  .sidebar-promo .big{display:block;color:#f3f6ff;font-size:1.22rem;line-height:1.06;letter-spacing:-.2px}
  .sidebar-promo .big b{color:#aeb8ff}
  .sidebar-promo .sub{display:block;color:#aebdd5;font-size:.78rem;line-height:1.48;margin:.62rem 0 0}
  .sidebar-promo .promo-button{display:flex;align-items:center;justify-content:space-between;width:100%;box-sizing:border-box;margin-top:1rem;background:#5865f2;border:1px solid rgba(255,255,255,.2);border-radius:7px;color:#fff;padding:.62rem .7rem;font-size:.68rem;font-weight:900;letter-spacing:.3px;box-shadow:0 5px 16px rgba(4,10,30,.22)}
  .sidebar-promo .promo-button>span:last-child{font-size:.88rem;line-height:1;transition:transform .15s ease}
  .sidebar-promo-link:hover .promo-button{background:#6672f4}
  .sidebar-promo-link:hover .promo-button>span:last-child{transform:translate(2px,-2px)}
  @media(max-width:360px){
    .sidebar-promo-link{padding:1rem}
    .sidebar-promo .big{font-size:1.1rem}
  }
  .donate-promo{text-align:left;padding:1.15rem;border-color:#1e4a30;
    background:radial-gradient(120% 100% at 15% 0%,rgba(46,160,94,.16),transparent 60%),linear-gradient(160deg,#0c1912,#080f0c)}
  .donate-top{display:flex;align-items:center;gap:.6rem;width:100%}
  .donate-icon{display:flex;align-items:center;justify-content:center;flex:0 0 34px;width:34px;height:34px;
    border-radius:50%;border:1px solid rgba(78,210,139,.5);color:#4ed28b;font-size:1rem;background:rgba(78,210,139,.08)}
  .donate-kicker{flex:1;min-width:0;color:#7ee2a8;font-size:.63rem;font-weight:900;letter-spacing:.75px}
  .donate-badge{display:inline-flex;align-items:center;gap:.3rem;flex:0 0 auto;border:1px solid rgba(78,210,139,.45);
    border-radius:999px;color:#7ee2a8;padding:.28rem .6rem;font-size:.58rem;font-weight:900;letter-spacing:.4px}
  .donate-badge i{font-style:normal}
  .donate-copy{display:block;margin-top:.9rem}
  .donate-promo-heading{display:block;color:#f3f6ff;font-size:1.15rem;font-weight:900;line-height:1.2;letter-spacing:-.2px}
  .donate-accent{color:#4ed28b}
  .donate-promo-text{display:block;color:#aebdd5;font-size:.78rem;line-height:1.55;margin-top:.62rem}
  .donate-promo-btn{display:flex;align-items:center;justify-content:space-between;width:100%;box-sizing:border-box;
    margin-top:1rem;background:linear-gradient(135deg,#3fbf6f,#1c854d);border:1px solid rgba(255,255,255,.2);
    border-radius:7px;color:#fff;padding:.68rem .8rem;font-size:.78rem;font-weight:900;letter-spacing:.3px;
    text-decoration:none;box-shadow:0 5px 16px rgba(4,10,30,.22);transition:filter .15s}
  .donate-promo-btn i{font-style:normal}
  .donate-promo-btn:hover{filter:brightness(1.08)}
  /* Same card material as .sidebar-promo, applied by position so it holds whether the markup
     is the static fallback (.t/.sub/.btn) or raw CMS paragraphs from renderPlaceholders():
     kicker -> muted sub -> the phone number itself as a button (forest green, distinct from
     Discord's purple, same hue family as the sidebar promo's LIVE dot). */
  .hotline{text-align:center;padding:0;overflow:hidden;border-color:#263b66;background:
    radial-gradient(circle at 12% 5%,rgba(88,101,242,.18),transparent 35%),
    linear-gradient(155deg,#101c35 0%,#111b31 100%);box-shadow:0 12px 28px rgba(0,0,0,.2)}
  .hotline-media{display:block;aspect-ratio:4/3;background:linear-gradient(135deg,#12233f,#0d1a30)}
  .hotline-media img{width:100%;height:100%;object-fit:cover;display:block}
  .hotline-media:hover img{filter:brightness(1.08)}
  .hotline-content{padding:1.15rem}
  .hotline .t,.hotline-content>*:first-child{display:block;margin:0;color:#c5d1e7;font-weight:900;font-size:.63rem;letter-spacing:.75px;text-transform:uppercase}
  .hotline .sub,.hotline-content>*:nth-child(2),.hotline-content>*:nth-child(n+4){display:block;margin:.62rem 0 0;color:#aebdd5;font-size:.78rem;line-height:1.48}
  .hotline .btn,.hotline-content>*:nth-child(3){display:block;width:100%;box-sizing:border-box;margin:.9rem 0 0;background:#1c8a5b;border:1px solid rgba(255,255,255,.2);border-radius:7px;color:#eafff4;padding:.75rem .8rem;font-size:1.05rem;font-weight:900;letter-spacing:.3px;font-variant-numeric:tabular-nums;box-shadow:0 5px 16px rgba(28,138,91,.3)}
  .hotline-content h1,.hotline-content h2,.hotline-content h3{font-size:1.22rem;line-height:1.06;color:#f3f6ff;font-weight:900;letter-spacing:-.2px;margin:.9rem 0 0}

  footer{border-top:1px solid var(--line);color:var(--mut);font-size:.8rem;text-align:center;padding:1.6rem 0}
  footer b{color:var(--accent2)}
  /* Alpha added to each stop (previously fully opaque) so an active #siteBackdrop shows through
     here too, matching the header. */
  .site-footer{border-top:1px solid var(--line);text-align:left;padding:2.1rem 1.4rem 1.35rem;background:linear-gradient(145deg,#07172dd9,#0b1e39d9 58%,#071326d9);box-shadow:0 -14px 42px rgba(0,0,0,.24)}
  .site-footer-panel{max-width:var(--maxw);margin:0 auto;padding:0 1.4rem;display:grid;grid-template-rows:auto auto}
  .footer-main{display:grid;grid-template-columns:minmax(230px,1.35fr) repeat(4,minmax(0,1fr)) minmax(230px,1.35fr);gap:1.3rem;align-items:start}
  /* When the "Get the Bubble App" promo is off (appVisible=false -- no app to promote yet),
     that column still reserved its full minmax(230px,1.35fr) for a handful of small social
     icons, leaving the whole row visibly left-heavy. Narrows that one track and gives the
     space back to brand/nav instead (Kyle, 2026-09-04: "heavily weighted to the left"). */
  .footer-main:has(.footer-app.compact){grid-template-columns:minmax(230px,1.5fr) repeat(4,minmax(0,1fr)) minmax(140px,.55fr)}
  .footer-brand,.footer-col,.footer-app{border-left:1px solid rgba(122,209,255,.12);padding-left:1.25rem}
  .footer-brand{border-left:0;padding-left:0}
  /* auto-fit instead of a hardcoded repeat(4,...) -- the real count is 3 nav groups today
     (Explore/Weather Tools/BubbleHQ, since Resources was retired), and a fixed 4-track grid
     left a phantom empty column contributing to the same left-heavy imbalance. Stays correct
     if the count changes again later instead of silently reserving dead space. */
  .footer-nav-groups{grid-column:2 / 6;display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:1.3rem}
  .footer-wordmark{display:flex;align-items:center;justify-content:center;gap:.8rem;color:var(--txt)}
  .footer-bubble{display:block;height:175px;width:auto}
  .footer-wordmark b{display:block;color:#fff;font-size:.9rem;letter-spacing:.8px;line-height:1}
  .footer-wordmark strong{display:block;color:#fff;font-size:1.45rem;line-height:.88;font-weight:1000;letter-spacing:.2px}
  .footer-wordmark small{display:block;color:#dce8ff;font-size:.68rem;font-weight:900;letter-spacing:5px;margin-top:.35rem}
  .footer-tagline{margin-top:1rem;font-weight:900;letter-spacing:1.8px;color:#fff;font-style:italic}
  .footer-tagline b{color:#18a7ff}
  .footer-col h3,.footer-app h3{margin:.1rem 0 .65rem;color:#edf4ff;font-size:.77rem;font-weight:900;letter-spacing:.8px;text-transform:uppercase}
  .footer-col a{display:block;color:#a9b8d0;font-size:.86rem;font-weight:650;margin:.48rem 0}
  .footer-col a:hover{color:var(--accent2)}
  .footer-app p{margin:0 0 .95rem;color:#a9b8d0;font-size:.84rem;line-height:1.4;font-weight:650}
  .store-badges{display:flex;gap:.6rem;flex-wrap:wrap;margin-bottom:1.15rem}
  .store-badges span{display:inline-flex;align-items:center;justify-content:center;min-width:104px;height:36px;border:1px solid rgba(255,255,255,.55);border-radius:5px;background:#02050a;color:#fff;font-size:.72rem;font-weight:900;letter-spacing:.2px}
  .footer-socials{display:flex;gap:.65rem;flex-wrap:wrap}
  .footer-social{width:38px;height:38px;border-radius:50%;display:grid;place-items:center;border:1px solid rgba(122,209,255,.18);background:rgba(255,255,255,.035);color:#e9f3ff;font-size:1rem;font-weight:900}
  .footer-social .social-icon-image{width:58%;height:58%}
  .footer-social .social-icon-mask{width:58%;height:58%}
  .footer-social:hover{background:rgba(122,209,255,.14);border-color:rgba(122,209,255,.36)}
  .footer-bottom{margin-top:1.65rem;padding-top:1.2rem;border-top:1px solid rgba(122,209,255,.12);display:block;color:#9eacc3;font-weight:650;text-align:center}
  /* Kyle kept testing at widths this treatment didn't cover yet -- first the plain 720px
     single-column cutoff was too narrow (his screenshot was wider, still showing the 3-column
     tablet grid), then even 820px (matching the header's own hamburger threshold) still wasn't
     wide enough (a later screenshot around ~1074px was STILL side by side). Folded straight into
     the existing 1100px tablet breakpoint instead of guessing a new number again -- below that,
     it's always logo/icons/text stacked now, with no separate "tablet" in-between state left.
     The old separate 1100px block (kept .footer-main as a 3-column tablet grid) is replaced
     entirely by this one, including its :has(.footer-app.compact) specificity override (still
     needed for the same reason -- :has() outranks a plain .footer-main rule regardless of which
     one is written second). */
  @media(max-width:1100px){.site-footer{padding-left:1rem;padding-right:1rem}.footer-main,.footer-nav-groups{grid-template-columns:1fr}.footer-main:has(.footer-app.compact){grid-template-columns:1fr}.footer-nav-groups{grid-column:auto;gap:0}.footer-brand,.footer-col,.footer-app{border-left:0;border-top:1px solid rgba(122,209,255,.12);padding:1rem 0 0}.footer-brand{border-top:0;padding-top:0}
    /* Kyle: on mobile the footer should just be logo + trademark line + social icons, no link
       columns -- the nav-group links (Explore/Weather Tools/BubbleHQ) are already reachable via
       the hamburger menu up top, so this isn't losing access to anything, just decluttering.
       The logo (.footer-wordmark) is already centered unconditionally; .footer-socials isn't --
       it's flex with no justify-content, so it left-aligns by default once it's the only thing
       left in the single-column mobile stack. Center it too so the icon row sits under the
       logo instead of hugging the left edge under a centered image. */
    .footer-nav-groups{display:none}
    .footer-socials{justify-content:center}
    /* justify-content:center on .footer-wordmark/.footer-socials only centers content WITHIN
       their own box -- if that box isn't actually stretching to the full single-column width
       (a real mobile Safari quirk with a flex child inside a 1fr grid track sized around an
       image with an intrinsic size), centering happens inside a too-narrow box instead of the
       full row, which reads as "not centered" even though the rule is doing exactly what it
       says. Forcing the width explicitly removes the ambiguity. */
    .footer-brand,.footer-wordmark,.footer-app,.footer-socials{width:100%}
  }

  /* ---- story post page ---- */
  .post{overflow:hidden;padding:0}
  .post-hero{width:100%;aspect-ratio:16/7.5;object-fit:cover;display:block}
  .post-body{padding:1.8rem 1.6rem 1.9rem}
  .post-cat{display:inline-block;background:var(--bad);color:#fff;font-size:.62rem;font-weight:900;letter-spacing:.6px;text-transform:uppercase;padding:.28rem .6rem;border-radius:5px;margin-bottom:.8rem}
  .post-title{font-size:2rem;font-weight:900;line-height:1.15;margin:0 0 .7rem;letter-spacing:.2px}
  .post-meta{color:var(--mut);font-size:.82rem;font-weight:600;margin-bottom:1.3rem}
  .post-meta-pipe{color:#445977;margin:0 .25rem}
  .post-meta-cat{display:inline-flex;align-items:center;background:rgba(91,180,255,.14);border:1px solid rgba(91,180,255,.38);color:#bfe4ff;font-size:.66rem;font-weight:900;letter-spacing:.55px;text-transform:uppercase;padding:.18rem .48rem;border-radius:5px;vertical-align:middle}
  .page-dek{color:#a9bad6;font-size:1.05rem;line-height:1.55;margin:-.25rem 0 1.25rem;font-weight:500}
  .post-feature{margin:0 0 1.35rem;padding-bottom:1.2rem;border-bottom:1px solid var(--line)}
  .post-feature figcaption{display:flex;justify-content:space-between;gap:1rem;color:var(--mut);font-size:.72rem;line-height:1.45;margin-top:.55rem}
  .post-feature figcaption small{color:#7f90aa;font-size:inherit;text-align:right;white-space:nowrap}
  .post-content{font-size:1.02rem;line-height:1.75;color:#dce6f5}
  .post-content p{margin:0 0 1.1rem}
  .post-content p:last-child{margin-bottom:0}
  .post-content h2,.post-content h3{color:var(--accent2);font-weight:900;letter-spacing:.2px;
    margin:2.3rem 0 1rem;padding-bottom:.5rem;border-bottom:2px solid rgba(125,209,255,.25)}
  .post-content h2:first-child,.post-content h3:first-child{margin-top:0}
  .post-content strong,.post-content b{color:var(--accent2);font-weight:800}
  .post-content img{max-width:100%;height:auto;border-radius:6px;display:block}
  .post-content a{color:var(--accent2)}
  .post-content blockquote{margin:1.5rem 0;padding:.95rem 1.3rem;border-left:3px solid var(--accent);
    background:rgba(61,139,255,.08);border-radius:0 10px 10px 0;font-size:1.1rem;font-style:italic;color:var(--txt)}
  .post-content blockquote p{margin:0}
  .post-content blockquote p+p{margin-top:.5rem}
  .post-content .support-box{margin:1.6rem 0;padding:1.3rem 1.4rem;border-radius:12px;
    border:1px solid rgba(125,209,255,.3);background:linear-gradient(135deg,rgba(61,139,255,.14),rgba(125,209,255,.05))}
  .post-content .support-box p{margin:0 0 .8rem}
  .post-content .support-box p:last-child{margin-bottom:0}
  .post-content .support-btn{display:flex;align-items:center;justify-content:center;gap:.55rem;width:100%;
    box-sizing:border-box;margin-top:.4rem;background:linear-gradient(135deg,var(--accent),#173a7a);
    border:1px solid rgba(255,255,255,.25);border-radius:8px;color:#fff;padding:.8rem 1rem;
    font-size:.92rem;font-weight:900;letter-spacing:.3px;text-decoration:none;
    box-shadow:0 6px 18px rgba(4,10,30,.3);transition:filter .15s}
  .post-content .support-btn i{font-style:normal;font-size:1.05rem}
  .post-content .support-btn:hover{filter:brightness(1.1)}

  /* featured story card (homepage sidebar) = clickable, real headline */
  .story{display:block;cursor:pointer}
  .story .body h3{color:var(--txt)}
  .story:hover .body h3{color:var(--accent2)}
  .story-excerpt{color:var(--mut);font-size:.82rem;line-height:1.45;margin:.45rem 0 0}
