/* ============================================================================
   tire.css — TireFit's site-local layer. Loads AFTER datasite.css, adds only
   what the ring's Identity A does not already own.

   THE HAND (AAA+++ §5 — every site in the ring draws in a different one)
   ---------------------------------------------------------------------
   watts draws a switchboard. lux draws a ceiling plan. cook draws a probe.
   TireFit draws a DIMENSIONED ENGINEERING ELEVATION — the drawing a tyre
   engineer would staple to a fitment report:

     · 1.1px hairlines for geometry, 1.6px for the subject outline
     · dimension lines with 45° tick terminals, never arrowheads
     · extension lines that stop 3px short of what they measure
     · every label in --mono, uppercase, +.06em, never in the serif
     · the tolerance band drawn as a shaded ring, so the ±3% convention is a
       thing you can SEE the second tyre sitting inside or outside of

   Nothing here is an image and nothing here needs JS: the plate is emitted
   server-side as inline SVG and is complete with scripting off. calc.js only
   ever re-labels an already-drawn plate.

   MOTION (added 2026-08-04, §10). This file used to say "nothing here
   animates". The guarantee that mattered was never "no motion" — it was that
   the OUTPUT is a finished drawing: correct with JavaScript off, correct in
   print, correct to a crawler. That is unchanged. §10 animates the act of
   drawing the hero plate and nothing else, purely in CSS, with every
   element's final state identical to its natural state — so if the animation
   never runs, the plate is simply there. It lives inside
   `prefers-reduced-motion: no-preference`, the same opt-in the ring uses for
   .reveal, so for a reader who has asked for less motion it does not exist.
   ========================================================================== */

body[data-site="tire"] {
  --tf-line: color-mix(in srgb, var(--ink) 34%, transparent);
  --tf-line-2: color-mix(in srgb, var(--ink) 16%, transparent);
  --tf-subject: var(--ink-2);
  --tf-ok: #2F6B3F;
  --tf-marginal: #8A5A14;
  --tf-no: #A3352A;
}
:root[data-theme="dark"] body[data-site="tire"] {
  --tf-line: color-mix(in srgb, var(--ink) 44%, transparent);
  --tf-line-2: color-mix(in srgb, var(--ink) 20%, transparent);
  --tf-ok: #6FBF86;
  --tf-marginal: #D6A94F;
  --tf-no: #E1857C;
}

/* ============================================================ 1. THE PLATE
   The frame the drawing sits in. A drawing plate, not a card: it has a title
   block along the top and a border that is a drawn rule rather than a UI
   stroke, and it never floats (§3.2 — the one shadow on this site belongs to
   the calculator, nothing else). */
.tf-plate {
  margin: var(--s4) 0 0;
  border: 1px solid var(--tf-line-2);
  background: var(--surface);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.tf-plate-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 18px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--tf-line-2);
  background: var(--paper-2);
}
.tf-plate-t {
  font-family: var(--mono); font-size: .78rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-2); font-weight: 600;
}
.tf-plate-m {
  font-family: var(--mono); font-size: .74rem; letter-spacing: .06em;
  color: var(--muted); margin-left: auto;
}
.tf-plate-body { padding: 20px 18px 8px; }
.tf-plate svg { display: block; width: 100%; height: auto; }
.tf-plate figcaption { padding: 0 18px 14px; }

/* The drawing hand itself, applied to every plate SVG. */
.tf-draw .geo    { fill: none; stroke: var(--tf-line);   stroke-width: 1.1; }
.tf-draw .faint  { fill: none; stroke: var(--tf-line-2); stroke-width: 1.1; }
.tf-draw .subject{ fill: none; stroke: var(--tf-subject);stroke-width: 1.6; }
.tf-draw .rim    { fill: none; stroke: var(--tf-subject);stroke-width: 1.3; opacity: .75; }
.tf-draw .dim    { fill: none; stroke: var(--tf-line);   stroke-width: 1;   }
.tf-draw .ext    { fill: none; stroke: var(--tf-line-2); stroke-width: 1; stroke-dasharray: 2 3; }
.tf-draw .accent { fill: none; stroke: var(--accent);    stroke-width: 1.8; }
.tf-draw .band   { fill: var(--accent); opacity: .08; stroke: none; }
.tf-draw .hatch  { fill: none; stroke: var(--tf-line-2); stroke-width: 1; }
.tf-draw text {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .05em;
  fill: var(--muted); text-transform: uppercase;
}
.tf-draw text.val { fill: var(--ink-2); font-size: 11.5px; letter-spacing: .02em; text-transform: none; }
.tf-draw text.key { fill: var(--accent); font-weight: 600; }
.tf-draw .cl { stroke: var(--tf-line-2); stroke-width: 1; stroke-dasharray: 9 3 2 3; }

/* ========================================================= 2. THE VERDICT
   The single most useful thing on the site and the thing no competitor
   prints: not a table of two diameters, but an answer, on a rail, with the
   convention it is judged against drawn around it. */
.tf-verdict {
  margin: var(--s4) 0 0;
  border-top: 2px solid var(--vc, var(--accent));
  background: var(--surface);
  padding: 20px 22px 22px;
}
.tf-verdict[data-v="ok"]       { --vc: var(--tf-ok); }
.tf-verdict[data-v="marginal"] { --vc: var(--tf-marginal); }
.tf-verdict[data-v="no"]       { --vc: var(--tf-no); }
.tf-v-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px; }
.tf-v-word {
  font-size: 1.34rem; font-weight: 600; letter-spacing: -.02em; color: var(--vc);
}
.tf-v-band {
  font-family: var(--mono); font-size: .72rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
  border: 1px solid var(--tf-line-2); border-radius: 999px; padding: 3px 9px;
}
.tf-v-delta {
  margin-left: auto; font-variant-numeric: tabular-nums;
  font-size: 1.34rem; font-weight: 620; letter-spacing: -.03em; color: var(--ink);
}
.tf-v-line { margin-top: 10px; color: var(--ink-2); font-size: .95rem; line-height: 1.62; max-width: 62ch; }

/* The tolerance rail: −6% … +6%, with the ±3% convention shaded and the
   actual result sitting on it as a gate. Reads at a glance, and reads
   correctly in greyscale, which the colour alone would not. */
.tf-rail { margin-top: 18px; }
.tf-rail-t {
  display: flex; justify-content: space-between;
  font-family: var(--mono); font-size: .7rem; letter-spacing: .08em;
  color: var(--muted); text-transform: uppercase; margin-bottom: 7px;
}
.tf-rail-bar {
  position: relative; height: 30px;
  border: 1px solid var(--tf-line-2); border-radius: 3px;
  background: var(--paper-2); overflow: hidden;
}
.tf-rail-ok {
  position: absolute; top: 0; bottom: 0;
  left: 25%; right: 25%;
  background: color-mix(in srgb, var(--tf-ok) 13%, transparent);
  border-left: 1px dashed var(--tf-line); border-right: 1px dashed var(--tf-line);
}
.tf-rail-zero { position: absolute; top: 0; bottom: 0; left: 50%; width: 1px; background: var(--tf-line); }
.tf-rail-gate {
  position: absolute; top: -4px; bottom: -4px; width: 3px;
  background: var(--vc); transform: translateX(-1.5px);
}
.tf-rail-s {
  display: flex; justify-content: space-between; margin-top: 7px;
  font-family: var(--mono); font-size: .7rem; letter-spacing: .06em; color: var(--faint);
}

/* ====================================================== 3. THE SPEC STRIP
   Key/value pairs in the mono voice — the register the ring reserves for
   dates, units, codes and specifications (AAA+++ §3.1's third voice). */
.tf-specs {
  margin: var(--s4) 0 0;
  border-top: 1px solid var(--line);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
}
.tf-spec {
  padding: 14px 18px 15px 0;
  border-bottom: 1px solid var(--line);
}
.tf-spec dt {
  font-family: var(--mono); font-size: .68rem; letter-spacing: .11em;
  text-transform: uppercase; color: var(--muted);
}
.tf-spec dd {
  margin: 6px 0 0; font-size: 1.16rem; font-weight: 600; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums lining-nums; color: var(--ink);
}
.tf-spec dd em { font-style: normal; font-weight: 400; font-size: .84rem; color: var(--muted); margin-left: 5px; }

/* ==================================================== 4. SIDEWALL DECODER
   The "what do these numbers mean" block. The size is set large in the mono
   voice with each field tinted and a leader dropping to its explanation — a
   callout drawing done in HTML so it reflows on a phone instead of scaling a
   diagram down to nothing. */
.tf-decode { margin: var(--s4) 0 0; }
.tf-code {
  font-family: var(--mono); font-weight: 600;
  font-size: clamp(1.5rem, 6vw, 2.4rem); letter-spacing: .02em;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 2px;
}
.tf-code b { font-weight: 600; padding: 0 3px; border-bottom: 3px solid var(--accent); color: var(--ink); }
.tf-code b.d2 { border-bottom-color: color-mix(in srgb, var(--accent) 55%, var(--paper)); }
.tf-code b.d3 { border-bottom-color: color-mix(in srgb, var(--accent) 30%, var(--paper)); }
.tf-code i { font-style: normal; color: var(--muted); padding: 0 3px; }
.tf-legend { margin-top: var(--s3); border-top: 1px solid var(--line); }
.tf-legend div {
  display: grid; grid-template-columns: 4.5rem 1fr; gap: 4px 16px;
  padding: 13px 0; border-bottom: 1px solid var(--line); align-items: baseline;
}
.tf-legend dt {
  font-family: var(--mono); font-size: .95rem; font-weight: 600; color: var(--ink);
}
.tf-legend dd { margin: 0; color: var(--ink-2); font-size: .93rem; line-height: 1.6; }
.tf-legend dd b { color: var(--ink); font-weight: 600; }

/* ====================================================== 5. THE CALCULATOR
   The one floating object on the site (§3.2). Inputs sit in sunken wells;
   the result is drawn by the same plate the static pages use, so the
   calculator is not a different product from the pages. */
.tf-calc {
  margin: var(--s4) 0 0;
  border: 1px solid var(--line-2); border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--shadow-lift);
  padding: 22px;
}
:root[data-theme="dark"] .tf-calc { box-shadow: none; background: var(--surface); border-color: var(--line-2); }
.tf-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px; }
.tf-field > span {
  display: block; font-family: var(--mono); font-size: .68rem; letter-spacing: .11em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 8px;
}
.tf-in {
  display: flex; gap: 6px; align-items: center;
  background: var(--paper-2); border: 1px solid var(--line-2);
  border-radius: var(--radius-sm); padding: 6px 8px;
}
.tf-in select, .tf-in input {
  flex: 1; min-width: 0; height: 38px;
  border: 0; background: transparent; color: var(--ink);
  font-family: var(--mono); font-size: 1rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.tf-in select:focus, .tf-in input:focus { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.tf-in i { font-style: normal; color: var(--faint); font-family: var(--mono); font-size: .9rem; }
.tf-note { font-family: var(--mono); font-size: .74rem; letter-spacing: .04em; color: var(--muted); margin-top: 14px; }
.tf-note.live { color: var(--accent); }

/* ============================================== 6. SPEEDOMETER ERROR TABLE
   Small, dense, unmistakably a reference table rather than a marketing
   graphic. Tabular numerals are non-negotiable here — the whole value is
   that the columns line up so the drift is visible down the page. */
.tf-speedo td, .tf-speedo th { font-variant-numeric: tabular-nums lining-nums; }
.tf-speedo .over  { color: var(--tf-no); font-weight: 600; }
.tf-speedo .under { color: var(--tf-ok); font-weight: 600; }

/* =========================================================== 7. SIZE INDEX
   A dense typeset index, closer to the back of a parts catalogue than to a
   card grid: on a rim hub there can be 167 sizes and cards would make that
   five screens of nothing. */
.tf-index {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  border-top: 1px solid var(--line);
}
.tf-index a {
  padding: 11px 14px 11px 0; border-bottom: 1px solid var(--line);
  text-decoration: none; color: var(--ink); display: block;
}
.tf-index a:hover { color: var(--accent); }
.tf-index a b { font-family: var(--mono); font-weight: 600; font-size: .93rem; letter-spacing: .01em; }
.tf-index a small { display: block; color: var(--muted); font-size: .76rem; margin-top: 2px; font-variant-numeric: tabular-nums; }
.tf-index a.tail b { color: var(--muted); font-weight: 500; }

/* ======================================================== 8. THE SEARCH
   The one control every visitor touches first, so it earns real work. The
   behaviour lives in TF_SEARCH_JS (build.mjs); this is only its dress.
   Grouped headings, a pinned exact hit, a highlighted match and a visible
   keyboard legend — the point is that a reader can see the size they typed
   being recognised, rather than guessing whether the box understood them. */
.tf-search input { padding-right: 44px; }
.tf-search .tf-slash {
  position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  font-family: var(--mono); font-size: .72rem; line-height: 1;
  color: var(--muted); background: var(--paper-2);
  border: 1px solid var(--line-2); border-radius: 4px;
  padding: 4px 7px; pointer-events: none;
}
/* Once focused the hint has done its job and would only be noise. */
.tf-search input:focus ~ .tf-slash { opacity: 0; }

.qr .qr-g {
  margin: 0; padding: 9px 16px 5px;
  font-family: var(--mono); font-size: .64rem; letter-spacing: .13em;
  text-transform: uppercase; color: var(--muted);
  background: var(--paper-2); border-bottom: 1px solid var(--line);
}
.qr a mark {
  background: var(--accent-soft); color: inherit;
  border-radius: 2px; padding: 0 1px; font-weight: 700;
}
/* Keyboard selection must be a BACKGROUND change, not just colour: it is the
   only cue when the pointer never moves, and :hover cannot express it. */
.qr a.on { background: var(--paper-2); color: var(--accent); outline: none; }
.qr a.on::after {
  content: "\21B5"; font-family: var(--mono); font-size: .8rem;
  color: var(--accent); margin-left: 8px; flex: none;
}
/* The exact designation the reader typed, pinned to the top. */
.qr a.qr-hit { border-left: 3px solid var(--accent); }
.qr a.qr-hit span { font-weight: 700; }
.qr .qr-k {
  margin: 0; padding: 8px 16px; border-top: 1px solid var(--line);
  background: var(--paper-2);
  font-family: var(--mono); font-size: .66rem; letter-spacing: .06em;
  color: var(--muted); display: flex; gap: 14px;
}
.qr .qr-k b {
  color: var(--muted); font-weight: 600;
  border: 1px solid var(--line-2); border-radius: 3px; padding: 1px 5px; margin-right: 3px;
}
.qr-none b { color: var(--ink-2); font-family: var(--mono); }

/* ============================================================== 9. SUNDRY */
.tf-pill {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: .7rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
  border: 1px solid var(--line-2); border-radius: 999px; padding: 4px 11px;
}
.tf-pill b { color: var(--ink-2); font-weight: 600; letter-spacing: .04em; }
.tf-two { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
@media (max-width: 720px) {
  .tf-two { grid-template-columns: 1fr; }
  .tf-verdict { padding: 18px 16px 20px; }
  .tf-v-delta { margin-left: 0; width: 100%; }
  .tf-plate-body { padding: 16px 12px 6px; }
}

/* ====================================================== 10. THE PLOTTER
   The header of this file used to say "nothing here animates". That was a
   promise about the OUTPUT, not a rejection of motion: the plate must be a
   finished drawing in the HTML, correct with JavaScript off and correct in
   print. It still is — every circle, dimension and label below is rendered
   server-side, and nothing here adds a script or changes a coordinate.

   What this adds is the ACT of drawing. The hand this site draws in is a
   plotter, so the hero plate draws itself the way a plotter would: centre
   lines first, then the tolerance band, then the original tyre, then the
   proposed one, then the dimensions it was all measured against. It is the
   site's argument performed rather than stated — you watch the second tyre
   land inside or outside the ring.

   Three rules held throughout:
     · It is ENHANCEMENT. Every element's final state is its natural state,
       so if the animation never runs the plate is simply there, complete.
     · It runs ONCE, in the hero only. A size page carrying four plates that
       all redraw on load would be a toy, not a reference.
     · It does not exist under prefers-reduced-motion — note the media query
       is `no-preference`, matching the ring's own `.reveal` convention, so
       motion is opt-in rather than something to be switched back off.
   ====================================================================== */
@media (prefers-reduced-motion: no-preference) {

  /* The dash lives ENTIRELY inside the keyframes, never as a static property.
     That distinction is the difference between a drawing and a blank plate:
     set statically, `stroke-dashoffset: 1400` hides the stroke completely, and
     anything that declines to run the animation — PRINT, most obviously, where
     CSS animations do not play — would render the tyre as nothing at all. With
     the offset scoped to the keyframes, the element's natural state stays a
     solid stroke, so a plate that is never animated is simply a finished
     drawing. That is the same guarantee the file header makes about JS.
     1400 comfortably exceeds the largest circumference here (the outer band
     circle is ~1257px at this viewBox), so one constant serves every circle
     and the dash never repeats mid-stroke. */
  .hero .tf-draw .subject,
  .hero .tf-draw .accent {
    animation: tf-draw 1100ms var(--ease-out) both;
  }
  /* The original is drawn before what is proposed for it — the order carries
     the meaning, so the delays are not decoration. */
  .hero .tf-draw .subject { animation-delay: 240ms; }
  .hero .tf-draw .accent  { animation-delay: 620ms; }

  /* The rim circles already carry an inline stroke-dasharray to render as
     dashed. Animating dashoffset here would fight that pattern and make them
     crawl, so they fade instead. */
  .hero .tf-draw .rim { animation: tf-fade 700ms var(--ease-out) 900ms both; }

  .hero .tf-draw .band { animation: tf-band 900ms var(--ease-out) 120ms both; }
  .hero .tf-draw .cl   { animation: tf-fade 600ms var(--ease-out) both; }
  .hero .tf-draw .ext  { animation: tf-fade 600ms var(--ease-out) 380ms both; }
  /* Dimensions and labels arrive last, once there is something to measure. */
  .hero .tf-draw .dim,
  .hero .tf-draw text  { animation: tf-fade 700ms var(--ease-out) 1250ms both; }

  @keyframes tf-draw {
    from { stroke-dasharray: 1400; stroke-dashoffset: 1400; }
    to   { stroke-dasharray: 1400; stroke-dashoffset: 0; }
  }
  @keyframes tf-fade { from { opacity: 0; } }
  @keyframes tf-band { from { opacity: 0; } to { opacity: .08; } }

  /* ---- the verdict rail ------------------------------------------------
     The band expands from the zero line outward and the gate drops onto it,
     so the reader's eye is taken to the result rather than having to find a
     3px mark that was always sitting there. */
  .tf-verdict .tf-rail-ok {
    transform-origin: 50% 50%;
    animation: tf-grow 620ms var(--ease-out) 160ms both;
  }
  .tf-verdict .tf-rail-gate {
    animation: tf-gate 520ms var(--ease-out) 560ms both;
  }
  @keyframes tf-grow { from { transform: scaleX(0); } }
  /* translateX(-1.5px) is the gate's own centring offset — repeating it here
     is mandatory, or the keyframe would drop it and the mark would sit 1.5px
     to the right of the value it reports. */
  @keyframes tf-gate {
    from { opacity: 0; transform: translateX(-1.5px) scaleY(0); }
    to   { opacity: 1; transform: translateX(-1.5px) scaleY(1); }
  }

  /* ---- small hover life ------------------------------------------------ */
  .tf-index a { transition: color var(--t-fast) var(--ease-out), padding-left var(--t-fast) var(--ease-out); }
  .tf-index a:hover { padding-left: 6px; }
  .qr a { transition: background var(--t-fast) var(--ease-out); }
  .tf-search .tf-slash { transition: opacity var(--t-fast) var(--ease-out); }
}
