/* ---------------------------------------------------------------------
   Bay Area Air Quality Episode Finder — public UI styles.

   Palette: NASA Web Design System published tokens.
   Type: NASA Horizon Design System stack — Inter (headings),
         Public Sans (body), DM Mono (numerical and technical data).
   --------------------------------------------------------------------- */

:root {
  --primary:          #105bd8;
  --primary-darker:   #0b3d91;   /* insignia blue */
  --primary-darkest:  #061f4a;
  --base:             #212121;
  --gray-dark:        #323a45;
  --gray:             #5b616b;
  --gray-light:       #aeb0b5;
  --gray-lighter:     #d6d7d9;
  --gray-lightest:    #f1f1f1;
  --cool-light:       #dce4ef;
  --alt-darkest:      #046b99;
  --alt-lightest:     #e1f3f8;
  --secondary:        #dd361c;
  --secondary-dark:   #c62d1f;
  --secondary-light:  #f9e0de;
  --green:            #2e8540;
  --white:            #ffffff;

  /* Exploration script 06's diverging anomaly ramp, reused unchanged so
     the legend matches the documented display convention. */
  --a1:#2166ac; --a2:#92c5de; --a3:#f7f7f7; --a4:#f4a582; --a5:#b2182b;

  --display: 'Inter', system-ui, sans-serif;
  --body:    'Public Sans', system-ui, sans-serif;
  --mono:    'DM Mono', ui-monospace, monospace;

  --edge: 1px solid var(--gray-lighter);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--white);
  color: var(--base);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 1240px; margin: 0 auto; padding: 0 24px; }

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--primary-darkest); color: var(--white);
  padding: 10px 16px; z-index: 1300;
}
.skip:focus { left: 0; }


/* --------------------------------------------------- provenance strip
   Federal sites open with an "official website" banner. This project is
   explicitly not an official source, so the pattern's position and
   restraint are kept and the content is inverted to say so. */
.origin { background: var(--gray-lightest); border-bottom: var(--edge); font-size: 12.5px; color: var(--gray-dark); }
.origin .wrap { display: flex; align-items: center; gap: 10px; padding-top: 7px; padding-bottom: 7px; flex-wrap: wrap; }
.origin b { color: var(--base); }
.flag { display: inline-block; width: 3px; height: 15px; background: var(--secondary); flex: none; }

/* ----------------------------------------------------------- masthead */
.masthead { background: var(--primary-darkest); color: var(--white); }
.masthead .wrap { padding-top: 30px; padding-bottom: 30px; }
.mast-flex { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }

/* Discreet plain text link to the About dialog: a normal link, not a
   button, badge, or logo. */
.about-link { flex: none; color: #cddcf0; font-size: 14px; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; padding: 8px 2px; }
.about-link:hover { color: var(--white); }
.about-link:focus-visible { outline: 3px solid var(--white); outline-offset: 2px; }
.eyebrow { font-family: var(--mono); font-size: 11.5px; letter-spacing: .14em; text-transform: uppercase; color: #9fc0e8; margin: 0 0 12px; }
h1 { font-family: var(--display); font-size: clamp(27px, 3.6vw, 40px); font-weight: 800; letter-spacing: -.021em; line-height: 1.08; margin: 0 0 12px; max-width: 24ch; }
.standfirst { font-size: 16.5px; font-weight: 300; color: #cddcf0; max-width: 64ch; margin: 0; }

/* --------------------------------------------------- instrument strip */
.instrument { border-bottom: var(--edge); }
.instrument .wrap { display: flex; flex-wrap: wrap; padding-top: 0; padding-bottom: 0; }
.icell { padding: 11px 26px 11px 0; margin-right: 26px; border-right: var(--edge); display: flex; align-items: baseline; gap: 9px; white-space: nowrap; }
.icell:last-child { border-right: 0; margin-right: 0; }
.ikey { font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--gray); font-weight: 600; }
.ival { font-family: var(--mono); font-size: 13px; }
.ival.pending { color: var(--gray-light); }
.ival.flagged { color: var(--alt-darkest); }
.ival.bad { color: var(--secondary-dark); }
.ival.good { color: var(--green); }

/* -------------------------------------------------------------- shell */
.shell { display: grid; grid-template-columns: 290px minmax(0,1fr); border-top: var(--edge); margin-top: 26px; align-items: start; }
@media (max-width: 940px) {
  .shell { grid-template-columns: 1fr; }
  .rail { border-right: 0; border-bottom: var(--edge); padding-right: 0; }
  .work { padding-left: 0; }
}

/* --------------------------------------------------------------- rail */
.rail { border-right: var(--edge); padding: 22px 24px 30px 0; }
.rail-head { font-family: var(--display); font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--gray-dark); margin: 0 0 18px; padding-bottom: 10px; border-bottom: var(--edge); }
.fld { margin-bottom: 19px; }
.fld > label, .fld > .flabel { display: block; font-size: 12.5px; font-weight: 600; color: var(--gray-dark); margin-bottom: 6px; }
/* Fixed (read-only) parameters of this slice: displayed as values, not
   as inert form controls that only look interactive. */
.ctl-static { margin: 0; background: var(--gray-lightest); border: 1px solid var(--gray-lighter); color: var(--gray-dark); font-family: var(--mono); font-size: 13.5px; padding: 9px 10px; }
.ctl { width: 100%; background: var(--white); border: 1px solid var(--gray-light); border-radius: 0; color: var(--base); font-family: var(--mono); font-size: 13.5px; padding: 9px 10px; }
.ctl:focus-visible { outline: 3px solid var(--primary); outline-offset: 0; }
.ctl[disabled] { background: var(--gray-lightest); color: var(--gray); }
.hint { font-size: 12px; color: var(--gray); margin: 6px 0 0; line-height: 1.45; }
.pair { display: flex; gap: 8px; }
.pair .ctl { min-width: 0; }
.go { width: 100%; background: var(--primary); color: var(--white); border: 0; border-radius: 0; padding: 12px; font-family: var(--body); font-size: 14px; font-weight: 700; cursor: pointer; }
.go:hover:not([disabled]) { background: var(--primary-darker); }
.go:focus-visible { outline: 3px solid var(--base); outline-offset: 2px; }
.go[disabled] { background: var(--gray-light); cursor: not-allowed; }

/* Animated Loading dots: decorative (the span is aria-hidden), pure
   CSS, and only rendered in the is-loading state. The dots are a
   FIXED literal '...' — the content property is never animated — and
   the cycle progressively reveals them by stepping the width of an
   overflow-hidden box through 0/1ch/2ch/3ch (monospace, so one dot is
   exactly 1ch). The parent span reserves a stable 3ch box, so the
   animation never shifts layout. */
.go .dots { display: none; }
.go.is-loading .dots {
  display: inline-block;
  width: 3ch;
  text-align: left;
  vertical-align: bottom;
  font-family: var(--mono);
}
.go.is-loading .dots::after {
  content: '...';
  display: inline-block;
  overflow: hidden;
  white-space: pre;
  vertical-align: bottom;
  width: 0;
  animation: loading-dots 1.6s infinite;
}
@keyframes loading-dots {
  0%, 24%   { width: 0; }
  25%, 49%  { width: 1ch; }
  50%, 74%  { width: 2ch; }
  75%, 100% { width: 3ch; }
}

/* Asynchronous status (ARIA live region) and retry buttons. */
.status-live { font-family: var(--mono); font-size: 12px; color: var(--gray-dark); margin: 12px 0 0; min-height: 1.4em; line-height: 1.5; }
.retry { margin-top: 10px; background: var(--white); border: 1px solid var(--primary); color: var(--primary-darker); font-family: var(--body); font-size: 13px; font-weight: 600; padding: 8px 14px; cursor: pointer; }
.retry:hover { background: var(--cool-light); }
.retry:focus-visible { outline: 3px solid var(--base); outline-offset: 2px; }
.retry.inblock { margin-top: 8px; }

/* --------------------------------------------------------------- work */
.work { padding: 22px 0 0 26px; }
.block { padding-bottom: 26px; margin-bottom: 26px; border-bottom: var(--edge); }
.block:last-child { border-bottom: 0; }
.bhead { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; flex-wrap: wrap; margin-bottom: 14px; }
.btitle { font-family: var(--display); font-size: 13px; font-weight: 700; letter-spacing: .085em; text-transform: uppercase; color: var(--primary-darker); margin: 0; }
.bmeta { font-size: 12.5px; color: var(--gray); }

/* ---------------------------------------------------------------- map */
#map { height: 380px; border: 1px solid var(--gray-lighter); background: var(--gray-lightest); }
.leaflet-container { font-family: var(--body); }
.map-state {
  border: 1px solid var(--gray-lighter); border-top: 0;
  background: var(--alt-lightest); color: var(--alt-darkest);
  font-family: var(--mono); font-size: 12px; padding: 8px 12px;
}

/* ------------------------------------------------------------ legend */
.legend { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 14px; }
.legend-row { display: flex; align-items: flex-start; gap: 8px; }
.ramp-wrap { display: flex; flex-direction: column; align-items: center; }
/* One continuous gradient surface (background set from backend palette
   metadata by app.js) — never a row of categorical colour boxes. */
.ramp { height: 13px; width: 200px; border: 1px solid var(--gray-light); }
.rlab { font-family: var(--mono); font-size: 11px; color: var(--gray); }
/* Centered under the ramp: with the backend's symmetric range, the 50%
   midpoint of the gradient is zero. */
.rzero { margin-top: 2px; }

/* Consolidated map reading guide ("How to read this map"). */
.howto { margin-top: 14px; border: var(--edge); border-left: 4px solid var(--primary-darker); background: var(--gray-lightest); padding: 12px 16px; }
.howto h3 { font-family: var(--display); font-size: 12.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--primary-darker); margin: 0 0 6px; }
.howto p { margin: 0; font-size: 13.5px; color: var(--gray-dark); line-height: 1.55; max-width: 92ch; }

/* Compact not-yet-assessed statement near the footer. */
.notyet p { margin: 0; max-width: 78ch; color: var(--gray-dark); font-size: 14.5px; }

/* ----------------------------------------------------------- readouts
   Explicit responsive breakpoints (not auto-fit, which left the fourth
   card alone on a second row): four equal cards on wide desktops, two
   per row at medium widths, one per row on narrow/mobile screens. */
.readouts { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 16px; }
@media (max-width: 1120px) { .readouts { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 620px)  { .readouts { grid-template-columns: 1fr; } }
.ro { border: var(--edge); border-top: 3px solid var(--primary-darker); padding: 15px 16px 14px; }
.rokey { font-size: 12px; font-weight: 600; color: var(--gray-dark); margin: 0 0 9px; }
.roval { font-family: var(--mono); font-size: 26px; font-weight: 500; line-height: 1; margin: 0; }
.roval.awaiting { color: var(--gray-light); }

.rounit { font-family: var(--mono); font-size: 11px; color: var(--gray); margin: 6px 0 0; min-height: 1.3em; }

/* The provenance rail: every number states the chain that produced
   it. Caveats live in the three information blocks, stated once. */
.prov { margin-top: 12px; padding-top: 9px; border-top: var(--edge); font-family: var(--mono); font-size: 10.5px; line-height: 1.65; color: var(--gray); }
.prov span { display: block; }

/* Scientific warnings (non-NOMINAL contributors, partial baseline
   window, projection incompatibility, map warnings). */
.warnbox { margin-top: 16px; border-left: 4px solid var(--alt-darkest); background: var(--alt-lightest); padding: 11px 15px; }
.warnbox p { margin: 0 0 8px; font-size: 13.5px; color: var(--gray-dark); max-width: 88ch; }
.warnbox p:last-child { margin-bottom: 0; }

/* ---------------------------------------------------- detail table */
.detail { margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(252px, 1fr)); gap: 0 28px; }
.drow { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 7px 0; border-bottom: 1px dotted var(--gray-lighter); }
.drow dt { font-size: 12.5px; color: var(--gray-dark); }
.drow dd { margin: 0; font-family: var(--mono); font-size: 12.5px; text-align: right; overflow-wrap: anywhere; }

/* ------------------------------------------------------------ footer */
footer { background: var(--primary-darkest); color: #cddcf0; margin-top: 34px; }
footer .wrap { padding-top: 24px; padding-bottom: 30px; display: flex; gap: 26px; flex-wrap: wrap; font-size: 13.5px; }
footer a { color: var(--white); text-decoration: underline; text-underline-offset: 3px; }
footer a:hover { color: #9fc0e8; }
footer .attrib { font-family: var(--mono); font-size: 12px; }

/* ------------------------------------------------------ about dialog */
#aboutDialog { width: min(620px, calc(100vw - 32px)); border: 1px solid var(--gray-lighter); padding: 0; overflow: hidden; }
#aboutDialog::backdrop { background: rgba(6, 31, 74, 0.55); }
.dlg-inner { padding: 18px 26px 24px; max-height: min(85vh, 640px); overflow-y: auto; }
.dlg-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.dlg-head h2 { font-family: var(--display); font-size: 22px; font-weight: 800; letter-spacing: -.015em; margin: 6px 0 12px; }
.dlg-close { flex: none; width: 40px; height: 40px; margin: -4px -12px 0 0; background: none; border: 0; font-size: 24px; line-height: 1; color: var(--gray-dark); cursor: pointer; }
.dlg-close:hover { color: var(--base); background: var(--gray-lightest); }
.dlg-close:focus-visible { outline: 3px solid var(--primary); outline-offset: 0; }
.dlg-text { font-size: 15px; color: var(--gray-dark); line-height: 1.6; margin: 0 0 18px; }
.contact-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 13px; }
/* [icon] [link text] rows with one consistent icon column. */
.contact-list li { display: flex; align-items: center; gap: 11px; font-size: 15px; color: var(--gray-dark); }
.contact-list svg { flex: none; width: 20px; height: 20px; color: var(--primary-darker); }
.contact-list a { color: var(--primary-darker); text-decoration: underline; text-underline-offset: 3px; overflow-wrap: anywhere; }
.contact-list a:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }
.dlg-foot { margin-top: 20px; padding-top: 13px; border-top: var(--edge); font-size: 12.5px; color: var(--gray); }
.dlg-foot p { margin: 0 0 6px; }
.dlg-foot p:last-child { margin-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  /* Static loading presentation: no dot cycling, fixed ellipsis. The
     colour change and disabled state are unaffected. */
  .go.is-loading .dots::after { content: '…'; animation: none; width: auto; }
}
