/*
 * Gear Ratio Calculator -- the drivetrain artwork, its motion, and the chart.
 *
 * Read the note at the top of grc.css about `stroke`: it is an INHERITED SVG
 * presentation property, so a stroke rule on any selector that can also match
 * an ancestor of an SVG paints every shape inside it. The sister tool shipped
 * a white stroke over its whole chart that way. Every stroke below is on a
 * class that only ever lands on an SVG child element, and nothing in here is
 * allowed on <body>.
 */

.grc-art {
  display: block; width: 100%; height: auto;
  /* grc-art.js writes the drawn viewBox ratio inline; this is the fallback. */
  aspect-ratio: 1200 / 300;
  overflow: visible;
}

/*
 * The frame reserves the drawn aspect ratio so the hero does not shift when the
 * artwork is injected. grc-app.js overwrites this inline once it knows which of
 * the two compositions it is drawing -- the media query is what holds the right
 * box for the first paint, before any script has run.
 */
.grc-artframe {
  width: 100%;
  aspect-ratio: 1200 / 300;
  margin: calc(4px * var(--grc-ui-scale)) 0;
}
@media (max-width: 800px) {
  .grc-artframe, .grc-art { aspect-ratio: 640 / 456; }
}

/* ---------- labels ---------- */

.grc-art-label {
  font-family: var(--grc-font-ui); font-size: 12px;
  letter-spacing: .14em; text-transform: uppercase;
  fill: var(--grc-faint); stroke: none;
}

/* ---------- tachometer ---------- */

.grc-tach-face { stroke: none; }
.grc-tach-bezel { fill: none; stroke: rgba(255, 255, 255, .1); stroke-width: 2; }
.grc-tach-track { fill: none; stroke: rgba(255, 255, 255, .1); stroke-width: 6; stroke-linecap: round; }
.grc-tach-red { fill: none; stroke: var(--grc-red); stroke-width: 6; stroke-linecap: round; opacity: .85; }
.grc-tach-tick { stroke: var(--grc-muted); stroke-width: 2; stroke-linecap: round; }
.grc-tach-tick.is-red { stroke: var(--grc-red); }
.grc-tach-num {
  font-family: var(--grc-font-display); font-size: 15px; font-weight: 500;
  fill: var(--grc-dim); stroke: none;
}
.grc-tach-num.is-red { fill: var(--grc-red); }
.grc-tach-needle {
  fill: var(--grc-red); stroke: none;
  transition: transform .28s var(--grc-ease-out);
  filter: drop-shadow(0 0 6px rgba(225, 29, 42, .6));
}
.grc-app[data-grc-dragging="1"] .grc-tach-needle { transition: transform .06s linear; }
.grc-tach-cap { fill: var(--grc-surface-3); stroke: rgba(255, 255, 255, .18); stroke-width: 2; }

/* ---------- engine, case, shaft ---------- */

.grc-block { stroke: rgba(255, 255, 255, .1); stroke-width: 1.5; }
.grc-block-fin { fill: var(--grc-surface-3); stroke: rgba(255, 255, 255, .08); stroke-width: 1; }
.grc-case { fill: rgba(30, 30, 38, .55); stroke: rgba(255, 255, 255, .1); stroke-width: 1.5; }
.grc-shaft { stroke: rgba(255, 255, 255, .08); stroke-width: 1; }
.grc-shaft-mark { fill: rgba(255, 255, 255, .22); stroke: none; }
.grc-road { stroke: var(--grc-line-strong); stroke-width: 2; }
.grc-road-dash { fill: rgba(255, 255, 255, .16); stroke: none; }

/* ---------- gears ---------- */

.grc-gear-body { stroke: rgba(255, 255, 255, .14); stroke-width: 1.5; stroke-linejoin: round; }
.grc-gear-hub { fill: var(--grc-bg); stroke: rgba(255, 255, 255, .16); stroke-width: 2; }
.grc-gear-hole { fill: var(--grc-bg-2); stroke: rgba(255, 255, 255, .08); stroke-width: 1; }

/* ---------- wheel ---------- */

.grc-tire { fill: #17171c; stroke: #34343e; stroke-width: 7; }
.grc-tread { stroke: rgba(255, 255, 255, .13); stroke-width: 3; stroke-linecap: round; }
.grc-rim { fill: none; stroke: #5a5a68; stroke-width: 5; }
.grc-spoke { stroke: #6e6e7e; stroke-width: 5; stroke-linecap: round; }
.grc-hubcap { fill: var(--grc-surface-3); stroke: #6e6e7e; stroke-width: 2; }

/* ---------- motion ---------- */

/*
 * One keyframe set, six durations. Setting animation-duration from a custom
 * property means a speed change is a single style write on the root element
 * and the compositor keeps running -- no JavaScript in the frame loop.
 *
 * A duration of 0s is how "stopped" is expressed: the animation is still
 * attached but never advances, so nothing has to be added or removed from the
 * element when the engine is at idle or the tool is out of view.
 */
@keyframes grc-spin { to { transform: rotate(360deg); } }
@keyframes grc-slide-x { to { transform: translateX(-44px); } }
@keyframes grc-slide-shaft { to { transform: translateX(-16px); } }

[data-grc-spin] {
  transform-box: fill-box;
  transform-origin: center;
  animation-name: grc-spin;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-duration: 0s;
  will-change: transform;
}
/* Meshing gears turn opposite ways. Getting this wrong is the kind of detail
   the audience for this page notices immediately. */
.grc-spin--rev { animation-direction: reverse; }

[data-grc-spin="engine"] { animation-duration: var(--grc-p-engine, 0s); }
[data-grc-spin="trans"]  { animation-duration: var(--grc-p-trans, 0s); }
[data-grc-spin="pinion"] { animation-duration: var(--grc-p-pinion, 0s); }
[data-grc-spin="ring"]   { animation-duration: var(--grc-p-ring, 0s); }
[data-grc-spin="wheel"]  { animation-duration: var(--grc-p-wheel, 0s); }

/* The shaft and the road slide instead of turning. */
[data-grc-spin="shaft"] {
  transform-origin: center;
  animation-name: grc-slide-shaft;
  animation-duration: var(--grc-p-shaft, 0s);
}
[data-grc-spin="road"] {
  transform-origin: center;
  animation-name: grc-slide-x;
  animation-duration: var(--grc-p-road, 0s);
}

/*
 * Nothing loops while the tool is off screen. The hero is one viewport tall,
 * so without this the drivetrain would spin for the entire length of the
 * article underneath it.
 */
.grc-app:not([data-grc-visible="1"]) [data-grc-spin] { animation-play-state: paused; }

/* Past the redline. */
.grc-art.is-redline .grc-tach-face { animation: grc-redline-pulse 1.1s ease-in-out infinite; }
@keyframes grc-redline-pulse {
  0%, 100% { fill: #0d0d10; }
  50% { fill: #2a0d10; }
}
.grc-art.is-redline .grc-gear-body { stroke: rgba(225, 29, 42, .5); }

/* ---------- the chart ---------- */

.grc-chart { font-family: var(--grc-font-ui); }
.grc-chart-grid { stroke: rgba(255, 255, 255, .06); stroke-width: 1; }
.grc-chart-axis { stroke: var(--grc-line-strong); stroke-width: 1; }
.grc-chart-tick {
  font-size: 11px; fill: var(--grc-faint); stroke: none;
  font-variant-numeric: tabular-nums;
}
.grc-chart-axislabel {
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  fill: var(--grc-muted); stroke: none;
}

/* The band above redline, and the line marking it. */
.grc-chart-redband { fill: rgba(225, 29, 42, .09); stroke: none; }
.grc-chart-redline { stroke: var(--grc-red); stroke-width: 1.5; stroke-dasharray: 5 4; }
.grc-chart-redlabel { font-size: 11px; fill: var(--grc-red); stroke: none; letter-spacing: .08em; }

/*
 * One line per gear. Colour comes from the sequential ramp in grc.css, and
 * grc-chart.js reads those custom properties rather than keeping a second
 * copy of the hex values. The dash pattern is set per line in JS, so the
 * series stay distinguishable in greyscale, in print, and to anyone who
 * cannot separate the adjacent steps of a cyan ramp by hue.
 */
.grc-chart-line { fill: none; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.grc-chart-line--ghost { stroke-width: 2; opacity: .5; stroke-dasharray: 2 5; }
.grc-chart-endlabel {
  font-family: var(--grc-font-display); font-size: 13px; font-weight: 600;
  stroke: none; paint-order: stroke;
}

/* The proposed setup in compare mode: amber, dashed, always behind. */
.grc-chart-line--proposed { stroke: var(--grc-warn); stroke-width: 2; stroke-dasharray: 7 5; opacity: .85; }

/* Crosshair */
.grc-chart-cross { stroke: rgba(255, 255, 255, .3); stroke-width: 1; stroke-dasharray: 3 4; }
.grc-chart-dot { fill: var(--grc-text); stroke: var(--grc-bg); stroke-width: 2; }
.grc-chart-readout {
  font-family: var(--grc-font-ui); font-size: 12px; fill: var(--grc-text); stroke: none;
  font-variant-numeric: tabular-nums;
}
.grc-chart-readout-bg { fill: rgba(10, 10, 11, .9); stroke: var(--grc-line-strong); stroke-width: 1; }

/* The marker showing where the tool's current rpm and gear sit on the chart. */
.grc-chart-here { fill: var(--grc-red); stroke: var(--grc-bg); stroke-width: 2; }
.grc-chart-here-ring {
  fill: none; stroke: var(--grc-red); stroke-width: 1.5; opacity: .6;
  animation: grc-here-pulse 2.4s ease-out infinite;
}
@keyframes grc-here-pulse {
  0% { r: 6; opacity: .7; }
  100% { r: 16; opacity: 0; }
}

/* The to-scale tire drawing in the inputs card. */
.grc-tirepreview { display: block; width: 100%; aspect-ratio: 3 / 2; max-height: calc(120px * var(--grc-ui-scale)); }
.grc-tirepreview .grc-tire { stroke-width: 5; }
.grc-tirepreview-ref { fill: none; stroke: var(--grc-line-strong); stroke-width: 1.5; stroke-dasharray: 4 4; }
.grc-tirepreview-dim { font-size: 11px; fill: var(--grc-faint); stroke: none; font-family: var(--grc-font-ui); }
