/* nodewatch: the airflow page (airflow-view.html, served as /airflow). One full-viewport canvas and a few
 * quiet overlays; tokens and faces come from theme/ira.css. The background is one flat grey that follows the sun of the
 * day shown, black at night to light grey by day: the script keeps --bg-rgb at that grey and flips data-theme between
 * dark (cream ink) and light (navy ink) as it crosses mid grey, so every colour here is a token or --bg-rgb. Type scales with the
 * viewport: a fluid root size on the page, the dashboard's 0.925vw on the kiosk so 4K and 5K are one layout. */
:root { font-size: clamp(15px, 0.42vw + 0.62vh + 5px, 46px); --bg-rgb: 0 0 0; background: rgb(var(--bg-rgb)); --small: max(0.68rem, 10.5px); }
:root.kiosk { font-size: 0.925vw; cursor: none; --small: 0.8rem; }
html, body { margin: 0; height: 100%; overflow: hidden; overscroll-behavior: none; }
body {
  --pad-x: max(1.25rem, env(safe-area-inset-left), env(safe-area-inset-right));
  --pad-top: max(1.1rem, env(safe-area-inset-top));
  --pad-bottom: max(1rem, env(safe-area-inset-bottom));
  --halo: 0 0 0.9rem rgb(var(--bg-rgb) / 0.95), 0 0 0.25rem rgb(var(--bg-rgb) / 0.8);
  background: rgb(var(--bg-rgb)); color: var(--ink); font-family: var(--font-body); -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none;
}
body.idle { cursor: none; }

#scene { position: fixed; inset: 0; width: 100vw; height: 100vh; height: 100dvh; display: block; touch-action: none; outline: none; }

a { color: inherit; text-decoration: none; }
.kicker { display: block; font: 500 var(--small)/1.3 var(--font-mono); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--ink-2); text-shadow: var(--halo); }

/* ---- the way back: small, out of the way, hides with the controls ---- */
.back {
  position: fixed; z-index: 3; top: var(--pad-top); left: var(--pad-x); padding: 0.35rem 0; font: 500 var(--small)/1 var(--font-mono);
  letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--ink-2); text-shadow: var(--halo); transition: opacity 0.6s, color 0.2s;
}
.back:hover, .back:focus-visible { color: var(--ink); }

/* ---- the three headline items: regime (top left), air changes (top right), clock (bottom left) ---- */
.headline {
  position: fixed; z-index: 2; top: calc(var(--pad-top) + 2rem); left: var(--pad-x); right: var(--pad-x);
  display: flex; justify-content: space-between; align-items: flex-start; gap: 2rem; pointer-events: none;
}
.hl-item { display: block; pointer-events: auto; }
.hl-regime { max-width: min(24rem, 44vw); }
.regime { display: block; margin-top: 0.35rem; font: 500 2.05rem/1.12 var(--font-display); letter-spacing: -0.005em; text-wrap: balance; text-shadow: var(--halo); transition: opacity 0.35s; }
.hl-ach { text-align: right; }
.ach { display: block; margin-top: 0.1rem; font: 500 3.5rem/1.05 var(--font-display); font-variant-numeric: tabular-nums lining-nums; text-shadow: var(--halo); transition: opacity 0.35s; }
.ach-range { display: block; margin-top: 0.15rem; font: 400 var(--small)/1.3 var(--font-mono); color: var(--ink-2); text-shadow: var(--halo); }
.fading { opacity: 0.25; }
/* the grade: one to three quiet dots */
.grade { display: inline-flex; gap: 0.22em; margin-left: 0.5em; vertical-align: 0.05em; }
.grade i { width: 0.42em; height: 0.42em; border-radius: 50%; box-sizing: border-box; border: 1px solid var(--ink-3); }
.grade[data-g="0"] i:nth-child(-n+1), .grade[data-g="1"] i:nth-child(-n+2), .grade[data-g="2"] i { background: var(--ink-2); border-color: var(--ink-2); }

/* ---- the highest and lowest corner sensor of the hour shown, in the space beside the building: lowest on the left,
   highest on the right, like the key. The number is drawn in the key's own colour for that value (set by the script,
   so it moves with the reading, the key and the sky); the camera keeps the building out from under them ---- */
.ext { display: contents; }
.ext-item { position: fixed; top: 50%; transform: translateY(-50%); display: block; pointer-events: auto; }
.ext-lo { left: var(--pad-x); }
.ext-hi { right: var(--pad-x); text-align: right; }
.ext-value { display: block; margin-top: 0.15rem; font: 500 4rem/1 var(--font-display); font-variant-numeric: tabular-nums lining-nums; text-shadow: var(--halo); white-space: nowrap; }
.ext-unit { font: 400 0.34em/1 var(--font-mono); margin-left: 0.12em; vertical-align: 1.35em; opacity: 0.85; }

.clock { position: fixed; z-index: 2; left: var(--pad-x); bottom: calc(var(--pad-bottom) + 1.9rem); pointer-events: none; transition: opacity 0.5s; }
.clock-time { display: block; font: 300 3.1rem/1 var(--font-display); font-variant-numeric: lining-nums; color: color-mix(in oklab, var(--ink) 72%, transparent); text-shadow: var(--halo); }
.clock-day { display: block; margin-top: 0.3rem; font: 400 var(--small)/1.3 var(--font-mono); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--ink-2); text-shadow: var(--halo); }

/* ---- the tag never hides ---- */
.tag { position: fixed; z-index: 2; left: var(--pad-x); bottom: var(--pad-bottom); font: 400 var(--small)/1.3 var(--font-body); color: var(--ink-2); text-shadow: var(--halo); pointer-events: none; }

/* ---- one slim legend and the time multiplier ---- */
.aside { position: fixed; z-index: 2; right: var(--pad-x); bottom: var(--pad-bottom); text-align: right; pointer-events: none; }
.legend { display: flex; align-items: center; justify-content: flex-end; gap: 0.5rem; }
.legend-bar { width: 9rem; height: 0.28rem; border-radius: 0.14rem; }
.legend-end, .aside-line { font: 400 var(--small)/1.3 var(--font-mono); color: var(--ink-2); text-shadow: var(--halo); font-variant-numeric: tabular-nums; }
.aside-line { margin-top: 0.3rem; }
.perf { margin-left: 0.6em; color: var(--accent); }
.verify.differs { color: var(--ink); }      /* the station and the outdoor reading disagree: a shade more present, no alarm colours */
/* the inks change with the sky over the better part of a second, never in a blink */
.kicker, .regime, .ach, .ach-range, .clock-time, .clock-day, .tag, .legend-end, .aside-line, .back, .grade i { transition: color 0.8s, opacity 0.35s, background-color 0.8s, border-color 0.8s; }

/* ---- controls: minimal, and gone after a few seconds without input ---- */
.controls {
  position: fixed; z-index: 3; left: 50%; bottom: var(--pad-bottom); transform: translateX(-50%); width: min(44rem, 52vw);
  display: flex; align-items: center; gap: 0.7rem; padding: 0.4rem 0.6rem; border-radius: 2rem;
  background: rgb(var(--bg-rgb) / 0.6); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); border: var(--hairline) solid var(--line);
  transition: opacity 0.6s, visibility 0.6s;
}
body.idle .controls, body.idle .back { opacity: 0; visibility: hidden; }      /* the Show motion button stays: it is the only way in */
html.kiosk .controls, html.kiosk .back, html.kiosk .motion { display: none; }
.controls button {
  font: 500 var(--small)/1 var(--font-mono); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--ink-2);
  background: none; border: 0; border-radius: 1rem; padding: 0.5rem 0.65rem; cursor: pointer; white-space: nowrap; min-height: 1.9rem;
}
.controls button:hover { color: var(--ink); }
.controls button[aria-pressed="true"]:not(.play) { color: var(--accent-ink); background: var(--accent); }
.controls button:focus-visible, .back:focus-visible, .motion:focus-visible, .headline:focus-visible { outline: 2px solid var(--accent); outline-offset: var(--focus-offset); }
.controls .short { display: none; }
.seg { display: flex; border: var(--hairline) solid var(--line); border-radius: 1rem; }
.play { width: 1.9rem; height: 1.9rem; padding: 0 !important; display: grid; place-items: center; flex: none; }
.play span { display: block; width: 0.62rem; height: 0.7rem; box-sizing: border-box; }
.icon-pause { border-left: 0.2rem solid currentColor; border-right: 0.2rem solid currentColor; }
.icon-play { border-left: 0.62rem solid currentColor; border-top: 0.35rem solid transparent; border-bottom: 0.35rem solid transparent; }
.scrub { flex: 1 1 4rem; min-width: 3rem; height: 1.9rem; margin: 0; background: none; -webkit-appearance: none; appearance: none; cursor: pointer; }
.scrub::-webkit-slider-runnable-track { height: 2px; background: var(--ink-3); border-radius: 1px; }
.scrub::-moz-range-track { height: 2px; background: var(--ink-3); border-radius: 1px; }
.scrub::-webkit-slider-thumb { -webkit-appearance: none; width: 0.7rem; height: 0.7rem; margin-top: calc(1px - 0.35rem); border-radius: 50%; background: var(--ink); border: 0; }
.scrub::-moz-range-thumb { width: 0.7rem; height: 0.7rem; border-radius: 50%; background: var(--ink); border: 0; }

.motion {
  position: fixed; z-index: 3; left: 50%; bottom: calc(var(--pad-bottom) + 3.4rem); transform: translateX(-50%); font: 500 var(--small)/1 var(--font-mono);
  letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--accent-ink); background: var(--accent); border: 0; border-radius: 1rem; padding: 0.6rem 0.9rem; cursor: pointer; transition: opacity 0.6s, visibility 0.6s;
}
.notice { position: fixed; z-index: 2; left: 50%; top: 50%; transform: translate(-50%, -50%); max-width: 80vw; text-align: center; font: 400 max(0.8rem, 11px)/1.4 var(--font-mono); color: var(--ink-2); text-shadow: var(--halo); pointer-events: none; }

/* ---- no WebGL: a still of the scene and the way to the dashboard ---- */
.still { position: fixed; inset: 0; z-index: 1; background: #0a121b; }
.still img { width: 100%; height: 100%; object-fit: cover; opacity: 0.85; }
.still p { position: absolute; left: 50%; bottom: calc(var(--pad-bottom) + 4rem); transform: translateX(-50%); margin: 0; width: max-content; max-width: 86vw; text-align: center; padding: 0.7rem 1rem; border-radius: var(--radius);
  background: rgb(10 18 27 / 0.8); font: 400 0.8rem/1.4 var(--font-body); color: var(--ink); }
.still a { color: var(--accent); text-decoration: underline; text-underline-offset: 0.2em; white-space: nowrap; }
body.no-gl #scene, body.no-gl .controls, body.no-gl .legend, body.no-gl .aside-line:not(.verify), body.no-gl .motion { display: none; }
body.no-gl { --bg-rgb: 10 18 27; }      /* the still is a night scene: the page stays dark around it */

/* ---- embed (/embed/airflow, inside an <iframe> on the site): the loop and nothing to operate. The canvas takes no
   input at all, so a swipe or the wheel over the frame scrolls the host page; the one small link opens the full view ---- */
:root[data-view="embed"] .controls { display: none; }
:root[data-view="embed"] #scene { pointer-events: none; touch-action: auto; }
:root[data-view="embed"], :root[data-view="embed"] body { overscroll-behavior: auto; }

body.bare > :not(canvas) { display: none !important; }

/* ---- narrow and upright (a phone, a tall frame): the headline stacks at the top, everything else along the bottom;
   the middle stays clear ---- */
@media (max-width: 700px) and (orientation: portrait) {
  .headline { flex-direction: column; gap: 0.7rem; top: calc(var(--pad-top) + 1.7rem); }
  .hl-regime { max-width: 100%; }
  .regime { font-size: 1.5rem; }
  .hl-ach { text-align: left; }
  /* no room beside the building on an upright phone: the two readings share a row under the air changes */
  .ext { display: flex; align-self: stretch; justify-content: space-between; align-items: flex-end; gap: 1rem; pointer-events: none; }
  .ext-item { position: static; transform: none; }
  .ext-value { font-size: 2.3rem; }
  .ach { font-size: 2.3rem; display: inline-block; }
  .ach-range { display: inline-block; margin-left: 0.6rem; }
  .clock { bottom: calc(var(--pad-bottom) + 1.6rem); }
  .clock-time { font-size: 2.2rem; }
  .aside { bottom: calc(var(--pad-bottom) + 1.6rem); }
  .legend-bar { width: 5.5rem; }
  .controls { width: auto; left: var(--pad-x); right: var(--pad-x); transform: none; bottom: calc(var(--pad-bottom) + 5.6rem); gap: 0.25rem; padding: 0.3rem 0.35rem; }
  .controls button { padding: 0.5rem 0.45rem; letter-spacing: 0.04em; }
  .controls .long { display: none; } .controls .short { display: inline; }
  .motion { bottom: calc(var(--pad-bottom) + 9rem); }
}
/* short and wide (a phone on its side, a small 16:9 frame in a column of the site): the same corners, smaller type */
@media (max-height: 520px) and (orientation: landscape) {
  .regime { font-size: 1.4rem; } .ach { font-size: 2.2rem; } .clock-time { font-size: 2rem; }
  .hl-regime { max-width: 48vw; } .legend-bar { width: 5.5rem; } .ext-value { font-size: 2.1rem; }
}
@media (max-width: 700px) and (orientation: landscape) {
  .controls { width: auto; left: var(--pad-x); right: var(--pad-x); transform: none; bottom: calc(var(--pad-bottom) + 4.4rem); gap: 0.25rem; padding: 0.2rem 0.35rem; }
  .controls .long { display: none; } .controls .short { display: inline; }
}
@media (prefers-reduced-motion: reduce) { .regime, .ach, .controls, .back, .clock { transition: none; } }
