/* Gas Exchange Suite: shared chrome and analysis components. Loaded by the landing (chrome and
   tokens) and the CO₂ and Light tools; Dynamic and Quick Viewer adopt it in wave 2.
   The palette follows Quick Viewer so the suite reads as one; the DMS mark uses the studio brass.
   The theme lives on <html data-theme>, set before first paint by suite-theme.js. The studio's shared tool
   layer (tool-interactions.css/js) supplies the DMS mark's seconds hand (.dms-clock-hand), the press
   feedback of every control and the reduced-motion bridge; nothing here repeats them. */

/* The font URL carries its content hash (scripts/check-dist.mjs); pages preload the same URL via assetUrl. */
@font-face { font-family: "Space Grotesk"; src: url("/assets/fonts/SpaceGrotesk-Variable.woff2?v=0640890476fc1198") format("woff2"); font-weight: 300 700; font-display: swap; }
@font-face { font-family: "Space Grotesk Fallback"; src: local("Helvetica Neue"), local("HelveticaNeue"), local("Arial"); size-adjust: 107.5%; }

:root {
  --font-text: "Space Grotesk", "Space Grotesk Fallback", "Helvetica Neue", Arial, sans-serif;
  --font-math: "STIX Two Math", "STIX Two Text", "Cambria Math", "Latin Modern Math", "Times New Roman", serif;
  --heading-weight: 500;
  --track-title: -0.03em;
  --track-heading: -0.012em;
  --radius: 14px;
  --radius-small: 8px;
  --motion-instant: 90ms;
  --motion-quick: 160ms;
  --motion-medium: 260ms;
  --motion-settle: 560ms;
  --ease-standard: cubic-bezier(.2, .7, .2, 1);
  /* x(t) = 1 − (1 + ωt)e^(−ωt) with ω = 9.2 over the duration: a critically damped spring, no overshoot. */
  --ease-spring: linear(0, .078 5%, .235 10%, .401 15%, .549 20%, .669 25%, .762 30%, .882 40%, .944 50%, .974 60%, .988 70%, .995 80%, 1);
  --brass-hi: #e6d2a0; --brass: #bfa673; --brass-mid: #977e4c; --brass-lo: #66512b;
  color-scheme: light;
  --bg: #f2f4f5; --surface: #ffffff; --surface-soft: #eaf0f4; --surface-raised: #f7f9fc;
  --ink: #14202d; --muted: #586778; --faint: #5d6c7e;
  --line: #c7d2de; --line-soft: #dfe6ed; --header-line: #1938581a; --input: #ffffff;
  --accent: #204c80; --accent-ink: #ffffff; --accent-soft: #e5edf6; --bronze: #815f31;
  --focus: #1d63ad; --danger: #a93822; --caution: #8a5a12;
  --mark-ink: var(--brass-lo);
  --shadow: 0 18px 48px #17314d0d;
}
html[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0c1118; --surface: #121b26; --surface-soft: #101720; --surface-raised: #182332;
  --ink: #f1f5fa; --muted: #a1afc0; --faint: #8796a9;
  --line: #2c3848; --line-soft: #202d3c; --header-line: #ffffff14; --input: #0e1620;
  --accent: #a7c9f8; --accent-ink: #10233e; --accent-soft: #223449; --bronze: #d3b27f;
  --focus: #a7c9f8; --danger: #ffb6a6; --caution: #e7c27d;
  --mark-ink: var(--brass);
  --shadow: 0 18px 48px #00000024;
}
/* The shared tool layer keys its own focus ring and press accents to these hooks; :root outranks its dark-ground
   defaults, so every focus ring on a suite page has one colour in both themes. */
:root[data-tool-profile][data-theme] { --dms-tool-focus: var(--focus); --dms-tool-accent: var(--accent); --dms-tool-accent-2: var(--bronze); }

*, *::before, *::after { box-sizing: border-box; }
html { min-width: 320px; scroll-padding-top: 24px; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--ink); font: 400 15px/1.55 var(--font-text); -webkit-font-smoothing: antialiased; }
button, input, select, textarea { font: inherit; color: inherit; }
button, a, input, select, summary, label { -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
button { cursor: pointer; }
button:disabled { cursor: not-allowed; opacity: .45; }
h1, h2, h3, p { margin: 0; }
sub, sup { font-size: .72em; line-height: 0; }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
:focus:not(:focus-visible) { outline: none; }
.sr-only, .visually-hidden { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0 0 0 0) !important; white-space: nowrap !important; border: 0 !important; }
.skip-link { position: absolute; left: 16px; top: 10px; z-index: 100; padding: 12px 16px; border-radius: var(--radius-small); background: var(--ink); color: var(--bg); font-weight: 600; text-decoration: none; transform: translateY(-200%); }
.skip-link:focus { transform: none; }
/* Variables in the equations' own glyphs, so α, θ and Γ* read the same on cards and in formulae. */
/* line-height 1: the larger math glyphs never deepen a line, so a card labelled α aligns with one labelled Curve. */
.sym { font-family: var(--font-math); font-style: italic; font-weight: 400; font-size: 1.12em; line-height: 1; letter-spacing: 0; padding-right: .06em; }
.nowrap { white-space: nowrap; }

/* Page frame: breadcrumb header, one working area, a quiet footer. */
/* Keep opaque workspaces above the fixed artwork even when native scrolling
   presents an older canvas frame. The transparent wrapper preserves the margins. */
.app { position: relative; z-index: 3; width: min(1520px, 100%); margin-inline: auto; padding: 0 clamp(16px, 3.2vw, 48px) 28px; }
.suite-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 88px; border-bottom: 1px solid var(--header-line); }
.page-identity { display: flex; align-items: center; flex-wrap: wrap; column-gap: 18px; min-width: 0; }
.suite-back { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; color: var(--muted); font-size: 15px; font-weight: 500; letter-spacing: var(--track-heading); text-decoration: none; transition: color var(--motion-quick) var(--ease-standard); }
.suite-back svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.identity-divider { color: var(--faint); font-size: 22px; font-weight: 300; }
.page-identity h1 { font-size: 26px; line-height: 1.2; font-weight: var(--heading-weight); letter-spacing: var(--track-heading); }

/* Module glyph: each tool's animated curve beside its title, at header scale (30 px tall, 28 px on phones). One
   motion language across the suite, paced by a nine-second breath: a probe of light travels the curve from its first
   point to its plateau (eased, fading in and out), gold dashes flow along the curve twice a breath, and the module's
   own ambient figure at the origin (CO₂ bubbles rising, light waves spreading) breathes with it. Markup: a
   span.module-glyph[data-glyph] (aria-hidden) holding the drawing's svg (viewBox "4 4 76 60") and an i.mg-probe.
   1em is one drawing unit, so the probe (an HTML dot) travels on the compositor with keyframes in em. The drawing's
   own motion is under 2 px a second and steps eight times a second on one shared 125 ms grid (every segment of its
   keyframes is a whole number of steps and the delays are whole breaths' thirds), which reads as continuous and
   repaints a busy tool page eight times a second instead of sixty. The glyph rests while its header is off screen ([data-rest] on the
   header), and under reduced motion it is a complete still with the probe half way up the curve. */
.module-glyph { --mg-size: 30px; position: relative; display: inline-block; width: 76em; height: 60em; margin-right: 11px; font-size: calc(var(--mg-size) / 60); line-height: 0; vertical-align: -8px;
  --mg-warm: #b89233; --mg-mid: var(--accent); --mg-cool: #7fb2ff; --mg-spark: #e0a03e; --mg-flow: #f0bf57; }
html[data-theme="dark"] .module-glyph { --mg-warm: #d3b27f; --mg-cool: #c5dbff; }
.module-glyph > svg { display: block; width: 100%; height: 100%; }
.module-glyph > svg, svg.module-glyph { overflow: visible; filter: drop-shadow(0 3px 6px #10131714); }
html[data-theme="dark"] :is(.module-glyph > svg, svg.module-glyph) { filter: drop-shadow(0 3px 8px #00000040); }
.module-glyph .mg-warm { stop-color: var(--mg-warm); } .module-glyph .mg-mid { stop-color: var(--mg-mid); } .module-glyph .mg-cool { stop-color: var(--mg-cool); }
.module-glyph .mg-axis { fill: none; stroke: var(--ink); stroke-opacity: .16; stroke-width: 1.8; stroke-linecap: round; }
.module-glyph .mg-curve { fill: none; stroke-width: 4.2; stroke-linecap: round; }
.module-glyph .mg-flow { fill: none; stroke: var(--mg-flow); stroke-width: 1.8; stroke-linecap: round; stroke-dasharray: 5 9; opacity: .72; }
.module-glyph .mg-start { fill: var(--ink); } .module-glyph .mg-eye { fill: var(--surface); fill-opacity: .86; } .module-glyph .mg-end { fill: var(--accent); }
.module-glyph .mg-probe { opacity: 0; pointer-events: none; }
span.module-glyph .mg-probe { position: absolute; left: calc((var(--mg-x) - 8.8) * 1em); top: calc((var(--mg-y) - 8.8) * 1em); width: 9.6em; height: 9.6em; border: 1.4em solid #fff; border-radius: 50%; background: var(--mg-spark); box-shadow: 0 0 5.6em 1.2em color-mix(in srgb, var(--mg-spark) 55%, transparent); }
/* The earlier form, an svg.module-glyph with the probe as a circle inside it (keyframes in drawing units, px), still
   works; it repaints the page every frame, so a new glyph uses the span form. */
svg.module-glyph .mg-probe { fill: var(--mg-spark); stroke: #fff; stroke-width: 1.4; }
.module-glyph .mg-ambient { fill: var(--mg-warm); stroke: none; }
.module-glyph[data-glyph="light"] .mg-ambient { fill: none; stroke: var(--mg-warm); }
@keyframes mg-flow { from { stroke-dashoffset: 0; opacity: .55; } 50% { opacity: .92; } to { stroke-dashoffset: -28; opacity: .55; } }
@keyframes mg-probe-fade { 0%, 100% { opacity: 0; } 6%, 70% { opacity: 1; } 84% { opacity: 0; } }
/* Sine-shaped breaths, sampled so that the stepped motion still eases in and out. */
@keyframes mg-rise { 0%, 100% { translate: 0 0; opacity: .38; } 12.5%, 87.5% { translate: 0 -.44px; opacity: .46; } 25%, 75% { translate: 0 -1.5px; opacity: .64; } 37.5%, 62.5% { translate: 0 -2.56px; opacity: .82; } 50% { translate: 0 -3px; opacity: .9; } }
@keyframes mg-spread { 0%, 100% { scale: .92; opacity: .36; } 12.5%, 87.5% { scale: .947; opacity: .44; } 25%, 75% { scale: 1.01; opacity: .63; } 37.5%, 62.5% { scale: 1.073; opacity: .82; } 50% { scale: 1.1; opacity: .9; } }
/* Probe paths in drawing units (em on the span form's HTML probe). */
@keyframes mg-probe-co2 { 0% { translate: 0 0; } 4.88% { translate: .11em -.12em; } 9.75% { translate: .76em -.84em; } 14.63% { translate: 2.31em -2.55em; } 19.5% { translate: 4.9em -5.42em; } 24.38% { translate: 8.54em -9.4em; } 29.25% { translate: 13.2em -14.25em; } 34.13% { translate: 18.78em -19.51em; } 39% { translate: 25.17em -24.63em; } 43.88% { translate: 32.08em -29em; } 48.75% { translate: 39.09em -32.12em; } 53.63% { translate: 45.46em -34.25em; } 58.5% { translate: 50.73em -35.42em; } 63.38% { translate: 54.56em -35.87em; } 68.25% { translate: 56.87em -35.99em; } 73.13% { translate: 57.84em -36em; } 78%, 100% { translate: 58em -36em; } }
@keyframes mg-probe-light { 0% { translate: 0 0; } 4.88% { translate: .13em -.09em; } 9.75% { translate: .9em -.69em; } 14.63% { translate: 2.69em -2.16em; } 19.5% { translate: 5.57em -4.75em; } 24.38% { translate: 9.39em -8.59em; } 29.25% { translate: 13.92em -13.58em; } 34.13% { translate: 18.97em -19.39em; } 39% { translate: 24.5em -25.45em; } 43.88% { translate: 30.83em -30.67em; } 48.75% { translate: 37.39em -34.69em; } 53.63% { translate: 43.57em -37.37em; } 58.5% { translate: 48.76em -38.89em; } 63.38% { translate: 52.57em -39.61em; } 68.25% { translate: 54.87em -39.9em; } 73.13% { translate: 55.84em -39.99em; } 78%, 100% { translate: 56em -40em; } }
.module-glyph .mg-flow { animation: mg-flow 4.5s steps(18) infinite; }
.module-glyph .mg-probe { animation: var(--mg-probe) 9s linear infinite, mg-probe-fade 9s linear infinite; }
.module-glyph[data-glyph="co2"] { --mg-probe: mg-probe-co2; --mg-x: 14; --mg-y: 54; --mg-rest: 39.09em -32.12em; --mg-origin: 14px 54px; }
.module-glyph[data-glyph="light"] { --mg-probe: mg-probe-light; --mg-x: 14; --mg-y: 52; --mg-rest: 37.39em -34.69em; --mg-origin: 14px 52px; }
.module-glyph .mg-ambient > * { animation: mg-rise 9s steps(9) infinite; transform-origin: var(--mg-origin); }
.module-glyph[data-glyph="light"] .mg-ambient > * { animation-name: mg-spread; }
.module-glyph .mg-ambient > :nth-child(2) { animation-delay: -3s; } .module-glyph .mg-ambient > :nth-child(3) { animation-delay: -6s; }
[data-rest] .module-glyph * { animation-play-state: paused; }
/* Phones: the title (glyph included) takes the header's full width on its own row under the back link and the theme
   toggle, so glyph and title share one line from 360 px (on the narrowest phones a long title wraps as it did before). */
@media (max-width: 600px) {
  .module-glyph { --mg-size: 28px; margin-right: 10px; vertical-align: -7px; }
  .suite-header { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 16px; }
  .suite-header .page-identity { display: contents; }
  .suite-header .suite-back { grid-area: 1 / 1; justify-self: start; }
  .suite-header .theme-toggle { grid-area: 1 / 2; }
  .suite-header .page-identity h1 { grid-area: 2 / 1 / 3 / -1; }
}
@media (prefers-reduced-motion: reduce) {
  .module-glyph * { animation: none !important; }
  .module-glyph .mg-probe { opacity: 1; translate: var(--mg-rest); }
}
@media (forced-colors: active) { .module-glyph { forced-color-adjust: none; } :is(.module-glyph > svg, svg.module-glyph) { filter: none; } }
.icon-button { display: grid; place-items: center; flex: 0 0 44px; width: 44px; height: 44px; padding: 0; border: 1px solid var(--line); border-radius: 50%; background: transparent; color: var(--ink); transition: background-color var(--motion-quick) var(--ease-standard); }
.icon-button svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
html[data-theme="dark"] .theme-moon, html:not([data-theme="dark"]) .theme-sun { display: none; }

.suite-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 24px; margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--header-line); color: var(--muted); font-size: 13px; }
.suite-footer p { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; }
/* Text links keep their line: 12 px of padding, taken back by the margin, makes the link's own box 44 px tall (so the
   target is whole even where the page ends at the screen's edge) without moving a pixel. The focus ring keeps to the
   text, 3 px clear, as on every other link. */
.suite-footer a:not(.suite-mark) { position: relative; padding-block: 12px; margin-block: -12px; color: inherit; text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 3px; transition: color var(--motion-quick) var(--ease-standard), text-decoration-color var(--motion-quick) var(--ease-standard); }
.suite-footer a:not(.suite-mark):focus-visible { outline: none; }
.suite-footer a:not(.suite-mark):focus-visible::before { content: ""; position: absolute; inset: 9px -3px; outline: 2px solid var(--focus); pointer-events: none; }
.suite-mark { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; color: var(--mark-ink); font-size: 13px; font-weight: 600; letter-spacing: .18em; text-decoration: none; }
.suite-mark img { width: 28px; height: 28px; }

/* Controls */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 10px 15px; border: 1px solid var(--line); border-radius: var(--radius-small); background: var(--surface-raised); color: var(--ink); font-size: 14px; font-weight: 600; line-height: 1.2; letter-spacing: 0; text-decoration: none; white-space: nowrap; transition: background-color var(--motion-quick) var(--ease-standard), border-color var(--motion-quick) var(--ease-standard), color var(--motion-quick) var(--ease-standard); }
.btn.primary { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.btn.quiet { border-color: transparent; background: transparent; color: var(--muted); }
.ico, .btn svg { width: 17px; height: 17px; flex: 0 0 17px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.mini-btn, .licor-import .btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px; min-height: 44px; padding: 8px 13px; border: 1px solid var(--line); border-radius: var(--radius-small); background: var(--surface-raised); color: var(--ink); font-size: 13px; font-weight: 600; transition: background-color var(--motion-quick) var(--ease-standard), border-color var(--motion-quick) var(--ease-standard); }
select, input[type="number"], input[type="text"] { display: block; width: 100%; min-width: 0; min-height: 44px; padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--radius-small); background: var(--input); color: var(--ink); font-size: 14px; line-height: 1.4; font-variant-numeric: tabular-nums; }
select { height: 44px; appearance: none; -webkit-appearance: none; padding-right: 30px; text-overflow: ellipsis; }
.field:has(> select), .demo-picker:has(> select) { position: relative; }
.field:has(> select)::after, .demo-picker:has(> select)::after { content: ""; position: absolute; right: 12px; bottom: 16px; width: 12px; height: 12px; pointer-events: none; background: currentColor; mask: url("../../../assets/images/icons/arrow-down.svg?v=a63cdbe7d2975510") center / contain no-repeat; }
.field { display: grid; gap: 6px; min-width: 0; color: var(--muted); font-size: 13px; font-weight: 500; }
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 10px 12px; align-items: end; }
.section-title { color: var(--ink); font-size: 14px; font-weight: 600; letter-spacing: var(--track-heading); }
.note { color: var(--muted); font-size: 13px; line-height: 1.5; }
.pill-toggle { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 9px 14px; border: 1px solid var(--line); border-radius: 999px; background: transparent; color: var(--muted); font-size: 13px; font-weight: 600; transition: background-color var(--motion-quick) var(--ease-standard), border-color var(--motion-quick) var(--ease-standard), color var(--motion-quick) var(--ease-standard); }
.pill-toggle[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--ink); }
.pill-toggle .sym { font-size: 1.12em; }
.pills { display: flex; flex-wrap: wrap; gap: 8px; }

/* Hover tone shifts on hover-capable pointers; the press (scale .985 and a tone shift) is the tool layer's. */
@media (hover: hover) {
  .btn:not(:disabled):hover, .mini-btn:not(:disabled):hover, .licor-import .btn:not(:disabled):hover, .pill-toggle:hover, .icon-button:hover { background-color: var(--accent-soft); border-color: var(--accent); }
  .btn.primary:not(:disabled):hover { background-color: color-mix(in srgb, var(--accent) 88%, var(--ink)); }
  .btn.quiet:not(:disabled):hover { color: var(--ink); border-color: transparent; }
  .suite-back:hover, .suite-footer a:not(.suite-mark):hover { color: var(--ink); text-decoration-color: currentColor; }
}

/* Workspace: results (toolbar, figure, metrics, checks) come first in reading order; on wide
   screens the model and data column sits to their left. */
.workspace { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; margin-top: 22px; align-items: start; }
@media (min-width: 1181px) {
  .workspace { grid-template-columns: 392px minmax(0, 1fr); grid-template-areas: "controls results"; }
  .results { grid-area: results; }
  .controls { grid-area: controls; }
}
.panel { min-width: 0; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow); }
.results { display: grid; gap: 16px; min-width: 0; }
.controls { display: grid; gap: 18px; padding: 18px; container: controls / inline-size; }
.controls > section:not(.data-grid-panel) { display: grid; gap: 12px; }
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.toolbar .export-menu { margin-left: auto; }
.demo-picker { flex: 1 1 210px; max-width: 280px; min-width: 0; }

.export-menu { position: relative; }
.export-menu > summary { list-style: none; }
.export-menu > summary::-webkit-details-marker { display: none; }
.export-menu > summary::after { content: ""; width: 7px; height: 7px; margin: -3px 0 0 2px; border: solid currentColor; border-width: 0 1.6px 1.6px 0; transform: rotate(45deg); }
.export-menu[open] > summary::after { margin-top: 3px; transform: rotate(-135deg); }
.menu-list { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; display: grid; min-width: 190px; padding: 6px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); box-shadow: 0 18px 40px #0f1d2e26; }
.menu-list button { justify-content: flex-start; width: 100%; border: 0; background: transparent; }

/* The figure is white paper in both themes. */
.figure-frame { position: relative; margin: 0; min-width: 0; border: 1px solid #d9e0e7; border-radius: 10px; background: #fff; color: #101317; overflow: hidden; }
.figure-mount { position: relative; min-width: 0; container-type: inline-size; touch-action: pan-y pinch-zoom; }
.figure-mount > svg { display: block; width: 100%; height: auto; user-select: none; -webkit-user-select: none; }
.figure-mount:focus-visible { outline-offset: -3px; }
.empty { display: grid; place-items: center; min-height: var(--figure-height, clamp(240px, 45vw, 560px)); padding: 20px; text-align: center; }
/* Before the first figure, the box already has the height responseFigure() draws at this width (main panel,
   residual panel, and the type-tier margins with one row of guide labels), so the figure lands without a shift. */
@supports (width: 1cqi) {
  .empty { min-height: var(--figure-height, calc(clamp(240px, 58cqi, 520px) + clamp(64px, 16cqi, 140px) + 88px)); }
  @container (min-width: 700px) { .empty { min-height: var(--figure-height, calc(clamp(240px, 58cqi, 520px) + clamp(64px, 16cqi, 140px) + 101px)); } }
}
.empty-title { color: #14202d; font-size: 16px; font-weight: 600; }
.empty-sub { margin-top: 6px; color: #586778; font-size: 14px; }
.figure-readout { position: absolute; z-index: 2; max-width: min(300px, calc(100% - 24px)); padding: 9px 12px; border-radius: 8px; background: #132133; color: #fff; font-size: 12px; line-height: 1.55; font-variant-numeric: tabular-nums; pointer-events: none; box-shadow: 0 6px 24px #0003; }
.figure-readout b { font-weight: 600; }
.figure-readout .row { display: flex; justify-content: space-between; gap: 14px; }
.figure-readout .row span:first-child { color: #c6d2e0; }
.figure-readout .sym { font-size: 1.1em; }

.metrics { display: grid; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: 10px; }
.metric-card { min-width: 0; padding: 12px 14px 13px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); }
.metric-card .k { color: var(--muted); font-size: 13px; font-weight: 500; }
.metric-card .v { margin-top: 3px; font-size: 21px; font-weight: 500; letter-spacing: var(--track-heading); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.metric-card .v.pending { color: var(--faint); }
.metric-card .s, .metric-card .ci { color: var(--muted); font-size: 12px; line-height: 1.45; }
.metric-card .ci { margin-top: 2px; font-variant-numeric: tabular-nums; }
.metrics-foot { display: grid; gap: 2px; }
.metrics-note { color: var(--faint); font-size: 12px; }
.definitions > summary, .checks details > summary { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; cursor: pointer; list-style: none; color: var(--muted); font-size: 14px; font-weight: 500; }
.definitions > summary::-webkit-details-marker, .checks details > summary::-webkit-details-marker { display: none; }
.definitions > summary::after, .checks details > summary::after { content: ""; width: 6px; height: 6px; margin: -3px 0 0 2px; border: solid currentColor; border-width: 0 1.5px 1.5px 0; transform: rotate(45deg); }
.definitions[open] > summary::after, .checks details[open] > summary::after { margin-top: 3px; transform: rotate(-135deg); }
.definitions dl { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 16px; margin: 2px 0 10px; font-size: 14px; }
.definitions dt { color: var(--ink); font-weight: 500; }
.definitions dd { margin: 0; color: var(--muted); }

.checks { display: grid; gap: 8px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); }
.checks-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; }
.checks-summary { color: var(--muted); font-size: 14px; }
.checks ul { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; font-size: 14px; }
.checks li { position: relative; padding-left: 16px; }
.checks li::before { content: ""; position: absolute; left: 1px; top: .6em; width: 6px; height: 6px; border-radius: 50%; background: var(--faint); }
.checks li[data-severity="caution"]::before { background: var(--caution); }
.checks li b { color: var(--caution); font-weight: 600; }

/* Model controls */
/* The extent box is a size container: its content can never widen the control column. Under 300 px the
   "Predict to" words give way to the value and its unit (the label above already names the control). */
.extent { display: grid; gap: 4px; container-type: inline-size; }
@container (max-width: 299px) { .extent-prefix { display: none; } }
.extent-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; }
.extent-head label { color: var(--muted); font-size: 13px; font-weight: 500; }
.extent-value, .inline-field { display: inline-flex; align-items: center; gap: 8px; color: var(--muted); font-size: 13px; white-space: nowrap; }
.extent-value input, .inline-field input { width: 92px; text-align: right; }
.option-line { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.range { --fill: 50%; width: 100%; height: 44px; margin: 0; background: transparent; -webkit-appearance: none; appearance: none; cursor: pointer; }
.range::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: linear-gradient(90deg, var(--accent) var(--fill), var(--line) var(--fill)); }
.range::-moz-range-track { height: 6px; border-radius: 3px; background: var(--line); }
.range::-moz-range-progress { height: 6px; border-radius: 3px; background: var(--accent); }
.range::-webkit-slider-thumb { width: 20px; height: 20px; margin-top: -7px; border: 2px solid var(--surface); border-radius: 50%; background: var(--accent); box-shadow: 0 1px 4px #0003; -webkit-appearance: none; appearance: none; }
.range::-moz-range-thumb { width: 16px; height: 16px; border: 2px solid var(--surface); border-radius: 50%; background: var(--accent); box-shadow: 0 1px 4px #0003; }
.range:focus-visible { outline-offset: 0; }
details.options-box { border: 1px solid var(--line-soft); border-radius: 10px; padding: 0 14px; }
details.options-box[open] { padding-bottom: 14px; }
details.options-box > summary { display: flex; align-items: center; justify-content: space-between; min-height: 44px; cursor: pointer; list-style: none; font-size: 14px; font-weight: 600; }
details.options-box > summary::-webkit-details-marker { display: none; }
details.options-box > summary::after { content: "+"; color: var(--faint); font-size: 18px; font-weight: 400; }
details.options-box[open] > summary::after { content: "−"; }
details.options-box > * + * { margin-top: 10px; }

/* Data grid: fixed columns, right-aligned tabular numbers, 44 px row actions. */
.data-grid-panel { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.data-grid-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 8px 6px 14px; border-bottom: 1px solid var(--line-soft); }
.data-grid-wrap { max-height: 470px; overflow: auto; overscroll-behavior: contain; container-type: inline-size; }
.data-grid { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 0; font-variant-numeric: tabular-nums; }
.data-grid col.index { width: 3.2ch; }
.data-grid col.action { width: 48px; }
.data-grid th { position: sticky; top: 0; z-index: 1; padding: 8px 10px 7px; vertical-align: bottom; border-bottom: 1px solid var(--line-soft); background: var(--surface-raised); color: var(--muted); font-size: 13px; font-weight: 600; text-align: right; line-height: 1.25; }
.data-grid th small { display: block; color: var(--faint); font-size: 11px; font-weight: 500; }
.data-grid th:first-child, .data-grid td:first-child { padding-inline: 4px; text-align: center; }
.data-grid td { border-bottom: 1px solid var(--line-soft); }
.data-grid tr:last-child td { border-bottom: 0; }
.row-index { color: var(--faint); font-size: 12px; }
.cell { padding: 0; }
.data-grid .grid-input { width: 100%; min-height: 44px; padding: 9px 10px; border: 0; border-radius: 0; background: transparent; text-align: right; font-size: 14px; font-variant-numeric: tabular-nums; }
.data-grid .grid-input:focus { background: var(--accent-soft); outline: 2px solid var(--focus); outline-offset: -2px; }
.row-remove { position: relative; display: grid; place-items: center; width: 44px; height: 44px; margin: 0 auto; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--faint); }
/* Inside the scrolling grid the ring sits within the button, so the scroll edge never clips it (the tool layer
   sets its offset with !important). */
:root[data-tool-profile] .data-grid .row-remove:focus-visible { outline-offset: -3px !important; }
.row-remove::before { content: ""; position: absolute; inset: 10px; border: 1px solid var(--line); border-radius: 50%; transition: border-color var(--motion-quick) var(--ease-standard), background-color var(--motion-quick) var(--ease-standard); }
.row-remove svg { position: relative; width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
@media (hover: hover) { .row-remove:hover { color: var(--danger); } .row-remove:hover::before { border-color: currentColor; } }
.row-remove:active::before { transform: scale(.92); }
/* Narrow grids (phones to about 400 px) trade cell padding for figures; headers and values keep one right edge. */
@container (max-width: 330px) { .data-grid th, .data-grid .grid-input { padding-inline: 5px; } }
/* The narrowest phones (under 320 px of panel): the grid runs to the panel's edges, three numeric columns gain
   ten pixels each, and a unit caption may break after "µmol" (its exponent groups never break). */
@container controls (max-width: 320px) { .data-grid-panel { margin-inline: -14px; border-inline: 0; border-radius: 0; } }
.table-note { padding: 10px 14px 12px; border-top: 1px solid var(--line-soft); color: var(--muted); font-size: 13px; line-height: 1.5; }

/* Equation */
.equation-panel { display: grid; gap: 12px; margin-top: 20px; padding: 16px 18px; }
.equation-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.equation-pill { padding: 4px 11px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); font-size: 13px; font-weight: 600; }
/* A wide equation scrolls sideways; a soft shade at an edge shows there is more (the local covers hide it at the
   ends). Narrow boxes set the math at 1rem, so every block of the CO₂ and Light equations fits at 320 px. */
.equation-math { --shade: color-mix(in srgb, var(--ink) 20%, transparent); container-type: inline-size; overflow-x: auto; padding: 14px 16px; border-radius: 10px;
  background: linear-gradient(90deg, var(--surface-raised) 40%, transparent) left / 28px 100% no-repeat local, linear-gradient(270deg, var(--surface-raised) 40%, transparent) right / 28px 100% no-repeat local, radial-gradient(farthest-side at 0 50%, var(--shade), transparent) left / 10px 100% no-repeat scroll, radial-gradient(farthest-side at 100% 50%, var(--shade), transparent) right / 10px 100% no-repeat scroll, var(--surface-raised); }
.equation-math math { font-size: 1.15rem; color: var(--ink); }
@container (max-width: 259px) { .equation-math math { font-size: 1rem; } }
.equation-block + .equation-block { margin-top: 10px; }
.equation-note { color: var(--muted); font-size: 13px; }

.noscript-note { margin-top: 22px; padding: 16px 18px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: var(--ink); font-size: 15px; }
html.no-js [data-requires-js] { display: none !important; }

@media (max-width: 860px) {
  .suite-header { min-height: 76px; }
  .page-identity h1 { font-size: 22px; }
}
@media (max-width: 600px) {
  .suite-header { align-items: flex-start; padding-top: 14px; min-height: 0; padding-bottom: 12px; }
  .page-identity { display: grid; row-gap: 0; }
  .identity-divider { display: none; }
  .suite-back { font-size: 14px; }
  .page-identity h1 { font-size: 24px; line-height: 1.25; }
  .toolbar .btn, .toolbar .export-menu > summary { padding-inline: 12px; }
  .demo-picker { flex-basis: 100%; max-width: none; }
  .toolbar .export-menu { margin-left: 0; }
  /* The export menu opens full width under the toolbar, whose last row holds Export, so it never leaves the screen. */
  .toolbar { position: relative; }
  .toolbar .export-menu { position: static; }
  .toolbar .menu-list { left: 0; right: 0; min-width: 0; }
  /* A toolbar of four peers (Light) sits in two even pairs instead of a ragged wrap. */
  .toolbar.pairs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .toolbar.pairs > .btn, .toolbar.pairs .export-menu > summary { width: 100%; }
  .controls { padding: 14px; }
  .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .metric-card .v { font-size: 19px; }
}
/* Phones: 16 px fields stop iOS from zooming on focus. */
@media (pointer: coarse) {
  select, input[type="number"], input[type="text"], .data-grid .grid-input { font-size: 16px; }
}
@media (forced-colors: active) {
  .panel, .metric-card, .checks, .figure-frame, .data-grid-panel, .menu-list { border: 1px solid CanvasText; }
  .range { forced-color-adjust: none; }
  .range::-webkit-slider-runnable-track { background: CanvasText; }
  .range::-moz-range-track { background: CanvasText; }
  .range::-webkit-slider-thumb { background: Highlight; border-color: Canvas; }
  .range::-moz-range-thumb { background: Highlight; border-color: Canvas; }
  .pill-toggle[aria-pressed="true"] { border: 2px solid Highlight; }
  .figure-frame { forced-color-adjust: none; }
}
@media print {
  .suite-header .icon-button, .toolbar, .controls .pills, .skip-link { display: none !important; }
}
