/* ==========================================================================
   explorer.css — layout and components for the FleetModel scenario explorer
   --------------------------------------------------------------------------
   Every colour, size, space, radius and duration comes from e3-tokens.css
   (which is itself derived from E3Website/tokens/e3.tokens.json — see that
   file's header). NO raw hex appears below; a structural test greps for it.

   The E3 rules this file implements, in order of appearance:
   - one gutter token governs every section edge (DESIGN_RULES/layout.md)
   - content caps at measure.section (80rem); whitespace grows, not measure
   - hierarchy by size and ink opacity, never by new greys or heavy weights
   - hard offset shadows only — no blur, ever
   - the −3° skewed-block motif is scoped to ONE interactive surface (the
     report CTA): dense repeating chrome (chips, cards, pills) renders flat
   - :focus-visible is 2px ink, offset 2px, never removed
   - prefers-reduced-motion kills every transition and animation
   ========================================================================== */

/* --- Reset / page -------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-stack);
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  line-height: var(--lh-body-zh);
  letter-spacing: var(--track-body);
}

/* The single source of left/right inset — no inner container adds its own. */
:root {
  --gutter-x: clamp(var(--space-5), 5vw, var(--space-24));
  --section-pad-y: clamp(var(--space-10), 6vw, var(--space-20));
}

.wrap {
  width: min(100%, var(--measure-section));
  margin-inline: auto;
  padding-inline: var(--gutter-x);
}

/* --- Type primitives ----------------------------------------------------- */

h1,
h2,
h3 {
  margin: 0;
  font-weight: var(--fw-display);
}

h1 {
  font-size: var(--fs-h1);
  line-height: var(--lh-h1);
  letter-spacing: var(--track-h1);
}

h2 {
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  letter-spacing: var(--track-h2);
}

h3 {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  letter-spacing: var(--track-h3);
}

p {
  margin: 0;
}

a {
  color: var(--accent-text);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

/* Eyebrow recipe — DESIGN_RULES/patterns.md § Eyebrow Label, verbatim. */
.eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-heading);
  text-transform: uppercase;
  letter-spacing: var(--track-eyebrow);
  line-height: var(--lh-flush);
  color: var(--ink);
  opacity: var(--ink-4);
}

/* The zh partner of a Latin line sits smaller and quieter (brand.md). */
.sub-en {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--fs-small);
  font-weight: var(--fw-light);
  letter-spacing: var(--track-body);
  color: var(--ink);
  opacity: var(--ink-3);
}

.meta {
  font-size: var(--fs-meta);
  color: var(--muted);
}

/* --- Header (quiet: the page's boldness is spent on the CTA) ------------- */

.site-header {
  border-bottom: 1px solid var(--line);
  padding-block: var(--space-6) var(--space-8);
}

.site-header .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-6);
}

.report-nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.report-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-small);
}

.report-nav a {
  display: inline-block;
  padding-block: var(--space-1);
}

/* --- Sections ------------------------------------------------------------ */

main {
  display: block;
}

.section {
  padding-block: var(--section-pad-y);
}

.section--band {
  background: var(--surface);
}

.section-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-8);
}

.section-note {
  max-width: var(--measure-prose);
  font-size: var(--fs-small);
  color: var(--muted);
}

/* --- Controls: flat, keyboard-first ------------------------------------- */

.axis-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  gap: var(--space-8);
}

.axis {
  margin: 0;
  padding: var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
}

.axis legend {
  padding-inline: var(--space-2);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-heading);
  text-transform: uppercase;
  letter-spacing: var(--track-eyebrow);
  color: var(--ink);
  opacity: var(--ink-4);
}

.axis-label {
  display: block;
  margin-bottom: var(--space-3);
  font-size: var(--fs-body);
}

/* The Latin partner of a zh axis label: smaller and quieter, never a second
   heading (brand.md § zh-first pairing). */
.axis-label-en {
  display: block;
  font-size: var(--fs-meta);
  font-weight: var(--fw-light);
  color: var(--ink);
  opacity: var(--ink-3);
}

.axis-value {
  display: inline-block;
  min-height: 1.5rem;
  font-weight: var(--fw-heading);
  color: var(--ink);
}

/* Tap targets ≥44px (semantics-a11y.md § Contrast & Size Floor). */
.axis input[type="range"] {
  width: 100%;
  min-height: 2.75rem;
  accent-color: var(--accent-graphic);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Dense repeating chrome renders FLAT — the skew is a gesture, and a gesture
   repeated twenty times stops being one (layout.md § motif Rule). */
.chip {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  font-size: var(--fs-small);
  line-height: var(--lh-flush);
  cursor: pointer;
  transition: background var(--motion-micro) var(--ease),
    border-color var(--motion-micro) var(--ease);
}

.chip[aria-pressed="true"],
.chip:hover {
  border-color: var(--structure);
  background: var(--surface);
}

/* --- Results: flat cards + charts ---------------------------------------- */

.card-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: var(--space-5);
  margin-bottom: var(--space-12);
}

.card {
  padding: var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
}

.card-label {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-heading);
  text-transform: uppercase;
  letter-spacing: var(--track-eyebrow);
  color: var(--ink);
  opacity: var(--ink-4);
}

.card-value {
  margin-top: var(--space-2);
  font-size: var(--fs-h2);
  font-weight: var(--fw-display);
  line-height: var(--lh-h2);
  letter-spacing: var(--track-h2);
}

.card-unit {
  margin-top: var(--space-1);
  font-size: var(--fs-meta);
  color: var(--muted);
}

/* The Δ card. Direction is carried by the ▼/▲ glyph in the text AND by the
   status text tier — colour is never the sole signal of a state
   (semantics-a11y.md § Forms). A Δ of zero keeps the plain ink. */
.delta {
  font-variant-numeric: tabular-nums;
}

.delta.is-better {
  color: var(--status-ok-text);
}

.delta.is-worse {
  color: var(--status-alert-text);
}

/* Two columns at most. An SVG's type scales with the drawing, so a chart
   squeezed into a third of the page renders its 13px tick labels at ~7px;
   capping the track at two keeps the rendered scale near the charts' own
   design width (see FRAME in charts.js) and the labels legible. */
.chart-grid {
  display: grid;
  /* `min(28rem, 100%)`, not a bare 28rem: a track floor wider than the
     container cannot shrink, and the charts would spill through the gutter
     on a phone. */
  grid-template-columns: repeat(auto-fit, minmax(min(28rem, 100%), 1fr));
  gap: var(--space-10);
}

/* <figure> ships a 40px UA side margin; it would shrink every chart inside
   its own grid track and, with it, the rendered size of the SVG's type. */
.chart {
  margin: 0;
  min-width: 0;
}

.chart h3 {
  margin-bottom: var(--space-3);
}

.chart svg {
  width: 100%;
  height: auto;
}

/* --- Chart internals -----------------------------------------------------
   charts.js writes no colour at all: SVG presentation attributes cannot
   resolve var() reliably, so every coloured node carries a CLASS and the
   mapping onto tokens lives here. Chrome (axes, gridlines, tick labels) uses
   structure / line / muted; only the four powertrain series may use the
   sanctioned --pt-* field palette. Charts stay flat — no border, no shadow,
   no fill behind the plot area. */

.fm-chart {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.fm-chart .ax-axis {
  stroke: var(--structure);
  stroke-width: 1;
}

.fm-chart .ax-grid {
  stroke: var(--line);
  stroke-width: 1;
}

/* One tier up from --fs-meta: these labels are inside a drawing that CSS
   usually scales DOWN a little, so the smallest tier would land below the
   legibility floor once rendered. */
.fm-chart .ax-tick,
.fm-chart .ax-unit {
  font-family: var(--font-stack);
  font-size: var(--fs-small);
  fill: var(--muted);
}

/* The unit sits above the y axis, quieter still — it is a caption, not data. */
.fm-chart .ax-unit {
  font-weight: var(--fw-heading);
}

.fm-chart .area {
  stroke: none;
}

.fm-chart .line {
  fill: none;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* WTW and the three energy carriers are single series: they take the graphic
   accent, never a powertrain colour (which would imply a powertrain). */
.fm-chart .line--wtw,
.fm-chart .line--crude,
.fm-chart .line--electricity,
.fm-chart .line--h2,
.fm-chart .swatch--wtw {
  stroke: var(--accent-graphic);
  fill: var(--accent-graphic);
}

/* The 基準點 overlay: dashed AND quieter — the dash is what identifies it, so
   the comparison survives on a monochrome print or with colour vision loss. */
.fm-chart .line--baseline {
  stroke: var(--muted);
  stroke-dasharray: 6 4;
  stroke-width: 1.5;
}

.fm-chart .swatch--baseline {
  fill: var(--muted);
}

.fm-chart .pt-icev {
  fill: var(--pt-icev);
}

.fm-chart .pt-hev {
  fill: var(--pt-hev);
}

.fm-chart .pt-bev {
  fill: var(--pt-bev);
}

.fm-chart .pt-fcv {
  fill: var(--pt-fcv);
}

/* Empty state where a chart would be — same slot, same rhythm, no numbers. */
.chart-empty {
  padding-block: var(--space-10);
  font-size: var(--fs-small);
  color: var(--muted);
}

/* --- The 150ms result fade ----------------------------------------------
   An animation, not a transition: the node is new on every render, so there
   is no "from" state for a transition to interpolate. The reduced-motion
   kill switch below collapses it to 1ms. */

@keyframes fm-fade-in {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

.fade-in {
  animation: fm-fade-in var(--motion-micro) var(--ease) both;
}

/* Loading / 失敗 state for the current grid point. Flat, quiet, and out of
   the layout entirely when there is nothing to say. */
.point-status {
  margin-top: var(--space-6);
  font-size: var(--fs-small);
  color: var(--muted);
}

.point-status[hidden] {
  display: none;
}

/* Inline annotations use the status pair; colour is never the sole signal —
   the copy itself says what is going on (semantics-a11y.md § Forms). */
.note-alert {
  padding: var(--space-3) var(--space-4);
  border-left: var(--border-w) solid var(--status-alert);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--status-alert) var(--badge-tint), var(--paper));
  color: var(--status-alert-text);
  font-size: var(--fs-small);
}

.note-alert[hidden] {
  display: none;
}

/* --- The one signature moment: the skewed-block report CTA ---------------
   The full motif per DESIGN_RULES/layout.md § The Skewed-Block Motif:
   skew −3°, counter-skewed child so the label reads upright, 2px ink border,
   hard offset ink-alpha shadow (never blur, never grey), and a hover that
   does three things at once — nudge up-left, grow the shadow, DOUBLE the
   radius — all at motion.micro (150ms). Nothing else on this page skews. */

.cta-row {
  margin-top: var(--space-12);
}

.cta-note {
  margin-top: var(--space-5);
}

.cta {
  display: inline-block;
  padding: var(--space-3) var(--space-6);
  border: var(--border-w) solid var(--ink);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: var(--shadow-shift) var(--shadow-shift) var(--shadow-ink);
  color: var(--ink);
  font-size: var(--fs-body);
  font-weight: var(--fw-heading);
  line-height: var(--lh-flush);
  text-decoration: none;
  transform: skewX(var(--block-skew));
  transition: transform var(--motion-micro) var(--ease),
    box-shadow var(--motion-micro) var(--ease),
    border-radius var(--motion-micro) var(--ease);
}

.cta > span {
  display: inline-block;
  transform: skewX(var(--content-skew));
}

.cta:hover,
.cta:focus-visible {
  border-radius: var(--radius-hover);
  box-shadow: var(--shadow-shift-hover) var(--shadow-shift-hover) var(--shadow-ink);
  transform: skewX(var(--block-skew)) translate(-1px, -1px);
}

.cta:active {
  border-radius: var(--radius);
  box-shadow: var(--shadow-shift) var(--shadow-shift) var(--shadow-ink);
  transform: skewX(var(--block-skew)) translate(0, 0);
}

/* --- Footer -------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--line);
  padding-block: var(--space-10);
  font-size: var(--fs-small);
  color: var(--muted);
}

.site-footer p + p {
  margin-top: var(--space-3);
}

/* --- Focus: 2px ink, offset 2px, never removed --------------------------- */

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* --- Progressive enhancement -------------------------------------------- */

body:not(.js-ready) .js-only {
  display: none;
}

.no-js-note {
  display: none;
}

body:not(.js-ready) .no-js-note {
  display: block;
}

/* --- Reduced motion: the kill switch ------------------------------------
   The global rule collapses animation; transition-based states need the
   explicit reduce variant too (semantics-a11y.md § Motion). The skew, the
   border and the shadow stay — only their movement in time goes away. */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }

  .cta:hover,
  .cta:focus-visible {
    transform: skewX(var(--block-skew));
  }
}
