/* Skip-to-content link */
.skip-link {
  position: fixed;
  top: -100%;
  left: var(--space-m, 1rem);
  z-index: 9999;
  padding: 0.5rem 1rem;
  background: var(--c-blue, #045cfa);
  color: #fff;
  font-family: var(--f-display, sans-serif);
  font-size: 0.875rem;
  font-weight: 600;
  border-radius: 2px;
  text-decoration: none;
  transition: top 0.15s ease;
}
.skip-link:focus {
  top: var(--space-m, 1rem);
  outline: 2px solid #fff;
  outline-offset: 2px;
}

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--c-canvas); color: var(--c-text);
  font-family: var(--f-body); font-size: var(--fs-step-0); line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1,h2,h3 { font-family: var(--f-display); line-height: 1.05; font-weight: 700; }
a { color: inherit; text-decoration: none; }
img, video { display: block; max-width: 100%; height: auto; }
.container { max-width: var(--content-max); margin-inline: auto; padding-inline: var(--space-m); }
/* Anchor targets (rail/nav #section jumps) clear the sticky header */
:is(section, main)[id] { scroll-margin-top: var(--anchor-offset); }
.mono-label { font-family: var(--f-mono); font-size: var(--fs-step--1); letter-spacing: .12em; text-transform: uppercase; color: var(--c-blue-text); }
/* Terminal-type caret while a [data-type] label types itself in (mono-type.js) */
.mono-label.is-typing::after { content: "▍"; margin-left: 1px; color: var(--c-blue); animation: mono-caret 1s steps(1) infinite; }
@keyframes mono-caret { 50% { opacity: 0; } }
/* CSS-animation kill-switch: gated on the ABSENCE of html.motion-ready (the JS gate, which
   honors the in-UI toggle), NEVER on the raw media query. The old @media !important rule
   silently nuked every CSS animation on machines whose OS reports reduced-motion even with
   the toggle forcing motion ON (found live 2026-08-01: computed animation-duration 1e-06s —
   the invisible teaser hover-draws and static marching dashes were exactly this). Same class
   of defect as the marquee gap; the gotcha now applies to the entire CSS layer. */
html:not(.motion-ready) .mono-label.is-typing::after { display: none; animation: none; }
html:not(.motion-ready) *,
html:not(.motion-ready) *::before,
html:not(.motion-ready) *::after {
  animation-duration: .001ms !important; transition-duration: .001ms !important; scroll-behavior: auto !important;
}
/* [data-rv] hidden/reveal states live in motion.css, gated on html.motion-ready — an earlier
   UNCONDITIONAL copy here made every data-rv section invisible for no-JS visitors (motion.css's
   own comment documents the intended no-JS/SSR-visible design). Removed 2026-07-15. */
.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; }
/* Programmatic focus targets (e.g. Blazor FocusOnNavigate's h1, tabindex=-1) aren't keyboard-tabbable, so they need no focus ring; keyboard :focus-visible elsewhere is unaffected. */
[tabindex="-1"]:focus { outline: none; }

/* View Transitions: snappy cross-fade; disabled under reduced-motion */
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.28s; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

/* ── Atmosphere layer (atmosphere.js) ───────────────────────────────────────────────────────
   [data-atmo] sections get an injected ambient canvas. The canvas is absolutely positioned so
   it never participates in grid/flex flow; content is lifted above it. Canvas exists only when
   motion is on — without JS or with reduced motion the section renders exactly as before. */
[data-atmo] { position: relative; }
.atmo-canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; }
[data-atmo] > :not(.atmo-canvas) { position: relative; z-index: 1; }

/* ── AME.Blazor.Controls token bridge ───────────────────────────────────────────────────────
   The controls' stylesheet defines --ame-* as var(--rz-*, <light fallback>): the --rz-* layer
   is the theming seam and NOTHING else defines it, so mapping it onto the site's own dark
   tokens themes every control (and the JS chart engine, which reads the computed values)
   without AMEThemeProvider. Semantics per the controls' dark palette: base-50 = page bg,
   base-100 = raised surface (lighter than the page in dark themes). */
:root {
  --rz-base-50: var(--c-canvas);
  --rz-base-100: var(--c-surface);
  --rz-base-200: var(--c-line);
  --rz-border: var(--c-line);
  --rz-text-color: var(--c-text);
  --rz-text-tertiary-color: var(--c-muted);
  --rz-text-disabled-color: var(--c-muted);
  --rz-primary: var(--c-blue);
  --rz-secondary: var(--c-muted);
  --rz-success: var(--c-brand-green-text);
  --rz-warning: var(--c-amber);
  --rz-danger: #FF7A6B;
  --rz-info: var(--c-blue);
}

/* ── Dew-point calculator (WASM island) ─────────────────────────────────────────────────────
   Global, not scoped: the component lives in the client project, so it carries no server-side
   scope attribute. Visual language mirrors the AME Portal page's panels. --c-gas is the
   product accent (brand green); redeclared here because .portal's scope does not reach a
   client-rendered subtree. */
.calc { --c-gas: var(--c-brand-green-text); margin-top: var(--space-m); }
.calc-loading { font-family: var(--f-mono); font-size: var(--fs-step--1); color: var(--c-muted); margin-bottom: var(--space-s); }
.calc-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-m); }
@media (min-width: 900px) { .calc-grid { grid-template-columns: 1.1fr 1fr 1fr; } }

.calc-panel {
  border: 1px solid var(--c-line); border-radius: 6px; background: var(--c-surface);
  padding: var(--space-m); display: flex; flex-direction: column; gap: .6rem;
}
.calc-panel-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem 1rem; margin-bottom: .2rem; }
.calc-panel-title {
  font-family: var(--f-mono); font-size: .68rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--c-blue-text); font-weight: 500;
}
.calc-panel-note { font-family: var(--f-mono); font-size: .62rem; color: var(--c-muted); }

.calc-row-controls { display: flex; gap: .5rem; flex-wrap: wrap; }
.calc-select, .calc-num {
  font-family: var(--f-mono); font-size: var(--fs-step--1); color: var(--c-text);
  background: var(--c-canvas); border: 1px solid var(--c-line); border-radius: 4px; padding: .45em .6em;
}
.calc-select { flex: 1 1 10rem; }
/* Inside a .calc-field (COLUMN flex) the 10rem flex-basis above becomes HEIGHT — the giant
   reference-conditions dropdown. Neutralize the basis in the column context. */
.calc-field .calc-select { flex: 0 0 auto; }
.calc-select:focus-visible { outline: 2px solid var(--c-blue); outline-offset: 1px; }
.calc-select:disabled { opacity: .5; }
/* Numeric inputs are AMENumeric (the portal's own control): size the WRAPPER, not the control's
   internals, so this survives any internal markup change in the library. */
.calc-numwrap { display: inline-block; width: 7.5rem; }
.calc-numwrap input { width: 100%; text-align: right; }
/* Warnings stack (AMEAlert, severity-mapped, worst first) */
.calc-alerts { display: flex; flex-direction: column; gap: .5rem; width: 100%; }

.calc-comp { display: flex; align-items: center; justify-content: space-between; gap: var(--space-s); }
.calc-comp-name { font-size: var(--fs-step--1); color: var(--c-text); }
.calc-total {
  display: flex; justify-content: space-between; margin-top: .3rem; padding-top: .6rem;
  border-top: 1px solid var(--c-line); font-family: var(--f-mono); font-size: var(--fs-step--1);
  color: var(--c-muted);
}
.calc-total-ok { color: var(--c-gas); }
.calc-total-off { color: var(--c-amber); }

/* Mode toggle + Calculate/Normalize are AMEButton now — the control styles itself. */
.calc-modes { display: flex; gap: .4rem; flex-wrap: wrap; }

.calc-field { display: flex; flex-direction: column; gap: .3rem; }
.calc-label { font-size: var(--fs-step--1); color: var(--c-muted); }
.calc-input-wrap { display: flex; align-items: center; gap: .5rem; }
.calc-unit { font-family: var(--f-mono); font-size: .66rem; color: var(--c-muted); }

.calc-privacy { font-family: var(--f-mono); font-size: .62rem; color: var(--c-muted); line-height: 1.5; }

.calc-empty { font-family: var(--f-mono); color: var(--c-muted); font-size: 1.5rem; }
.calc-big { font-family: var(--f-display); font-size: clamp(2.2rem, 1.8rem + 2vw, 3.2rem); font-weight: 700; line-height: 1; color: var(--c-text); }
.calc-big-unit { font-size: .42em; color: var(--c-muted); margin-left: .15em; }
.calc-secondary { font-family: var(--f-mono); font-size: var(--fs-step--1); color: var(--c-muted); }
.calc-nosolution { font-size: var(--fs-step--1); color: var(--c-amber); line-height: 1.6; }

/* Converged badge is AMEStatusPill; warnings are AMEAlert — both style themselves. */

.calc-diag { display: grid; grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr)); gap: .5rem; margin: 0; }
.calc-diag dt { font-family: var(--f-mono); font-size: .58rem; letter-spacing: .1em; text-transform: uppercase; color: var(--c-muted); }
.calc-diag dd { font-family: var(--f-mono); font-size: var(--fs-step--1); color: var(--c-text); margin: .15rem 0 0; }

.calc-loading { display: flex; align-items: center; gap: .6rem; }
.calc-nosolution { font-size: var(--fs-step--1); color: var(--c-amber); line-height: 1.6; }

/* Chart host panel — the chart itself is AMEChart (the product's own control); its axes,
   crosshair, tooltip, zoom and export are the library's. SVG projection styles removed
   2026-07-31 with the hand-rolled chart. */
.calc-chart {
  margin: var(--space-m) 0 0; padding: var(--space-m);
  border: 1px solid var(--c-line); border-radius: 6px; background: var(--c-surface);
}

/* ── Contact success ceremony (markup injected by js/contact-form.js — JS-created nodes carry
      no Blazor scope attribute, so these rules must live globally, like the progress rail) ── */
.contact-success {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-m);
  padding-block: var(--space-l);
}
.contact-success-icon {
  width: 64px;
  height: 64px;
  color: var(--c-brand-green-text);
}
.cs-ring, .cs-check {
  stroke-dasharray: 60;
  stroke-dashoffset: 60;
}
.contact-success.is-in .cs-ring {
  transition: stroke-dashoffset 0.7s var(--ease-out);
  stroke-dashoffset: 0;
}
.contact-success.is-in .cs-check {
  transition: stroke-dashoffset 0.45s var(--ease-out) 0.55s;
  stroke-dashoffset: 0;
}
@media (prefers-reduced-motion: reduce) {
  .cs-ring, .cs-check { stroke-dashoffset: 0; }
  .contact-success.is-in .cs-ring, .contact-success.is-in .cs-check { transition: none; }
}

/* ── Loop-check progress rail (built by js/motion/progress-rail.js; desktop only) ────────── */
.progress-rail {
  position: fixed; right: 20px; top: 50%; transform: translateY(-50%);
  z-index: 40; display: flex; flex-direction: column; align-items: center;
  justify-content: space-between; gap: .35rem; min-height: 42vh; max-height: 62vh;
  opacity: 0; transition: opacity .5s var(--ease-out);
  padding-block: 6px;
}
.progress-rail.is-ready { opacity: 1; }
/* JS only builds the rail ≥1380px; this guards a post-build viewport shrink (enhanced nav). */
@media (max-width: 1379px) { .progress-rail { display: none; } }

.progress-rail-track {
  position: absolute; top: 10px; bottom: 10px; left: 50%; width: 1px;
  transform: translateX(-50%); background: var(--c-line); border-radius: 1px;
}
.progress-rail-fill {
  position: absolute; left: 0; top: 0; width: 1px; height: 0;
  background: var(--c-blue); box-shadow: 0 0 6px var(--c-blue);
  transition: height .12s linear;
}

.progress-rail-tick {
  position: relative; z-index: 1; width: 22px; height: 22px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; cursor: pointer; color: var(--c-muted);
}
.progress-rail-tick::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  border: 1px solid var(--c-muted); background: var(--c-canvas);
  transition: background var(--dur-micro) var(--ease-out),
              border-color var(--dur-micro) var(--ease-out), transform var(--dur-micro) var(--ease-out);
}
.progress-rail-tick:hover::before { border-color: var(--c-blue-text); }
.progress-rail-tick.is-active::before {
  border-color: var(--c-blue); background: var(--c-blue);
  box-shadow: 0 0 0 3px rgba(4, 92, 250, .25); transform: scale(1.15);
}
/* Done ticks swap the dot for a drawn check — the "loop-check" completing itself */
.progress-rail-tick.is-done::before { opacity: 0; }
.progress-rail-tick svg {
  position: absolute; width: 15px; height: 15px; color: var(--c-blue);
  opacity: 0; transition: opacity var(--dur-micro) var(--ease-out);
}
.rail-check-path { stroke-dasharray: 26; stroke-dashoffset: 26; transition: stroke-dashoffset .4s var(--ease-out); }
.progress-rail-tick.is-done svg { opacity: 1; }
.progress-rail-tick.is-done .rail-check-path { stroke-dashoffset: 0; }

.progress-rail-label {
  position: absolute; right: 26px; top: 50%; transform: translateY(-50%) translateX(4px);
  white-space: nowrap; font-family: var(--f-mono); font-size: var(--fs-step--1);
  letter-spacing: .04em; color: var(--c-text); background: rgba(12, 20, 31, .9);
  padding: .15em .5em; border: 1px solid var(--c-line); border-radius: 3px;
  opacity: 0; pointer-events: none; transition: opacity var(--dur-micro) var(--ease-out),
              transform var(--dur-micro) var(--ease-out);
}
.progress-rail-tick:hover .progress-rail-label,
.progress-rail-tick:focus-visible .progress-rail-label,
.progress-rail-tick.is-active .progress-rail-label { opacity: 1; transform: translateY(-50%) translateX(0); }
.progress-rail-tick:focus-visible { outline: 2px solid var(--c-blue); outline-offset: 2px; border-radius: 4px; }

@media (prefers-reduced-motion: reduce) {
  .progress-rail, .progress-rail-fill, .progress-rail-tick::before,
  .progress-rail-tick svg, .rail-check-path, .progress-rail-label { transition: none; }
}
