/* ==========================================================================
   The QnQ Toolkit — shared styling for the free field tools
   --------------------------------------------------------------------------
   Sits on top of /assets/css/qnq.css and borrows all of its tokens, so the
   tools look like the rest of the public site. Everything here is scoped to
   the .tk page shell so it can never leak into another page.

   The rules this file is built to, and they are not decoration:

   · SUNLIGHT. These pages get read on a concrete deck in the sun with a glove
     on. Nothing that carries meaning is under 14px, the answer itself is
     56-64px, and the highest-contrast ink on the page is always the number.
   · ONE MATERIAL, AND NO COLOUR. Neutral near-black ground, gray surfaces,
     dim gray labels, and WHITE carrying the hierarchy. Amber is rationed to
     exactly one thing on a screen — the chosen segment of the primary
     control — and green/red appear only as verdicts, where they mean
     something. Nothing glows.
   · THE DEVICE'S OWN FACE. Everything renders in the system stack (SF Pro on
     an iPhone), so no webfont is downloaded by a tool page at all.
   · MOTION THAT COSTS NOTHING. Transform and opacity only. A dragged thumb
     never waits for a layout.
   · NAMES THAT CANNOT COLLIDE. The toolkit reuses exactly four of the site's
     classes on purpose — .hdr, .mnav, .ftr and .wrap — and everything it
     invents is prefixed or otherwise its own. It has to be: qnq.css defines
     294 classes, and .hero was one of them. The front page's hero section
     carries 138px of padding-top on a phone, and the readout inherited every
     pixel of it before this was caught.
   ========================================================================== */

:root{
  --go:#39D07E;          /* enough capacity */
  --go-dim:rgba(57,208,126,.13);
  --tight:#FFB020;       /* legal but close */
  --tight-dim:rgba(255,176,32,.13);
  --stop:#FF5F52;        /* not enough */
  --stop-dim:rgba(255,95,82,.13);

  /* one radius system — nothing in the toolkit uses a number outside this */
  --r1:12px;   /* inputs, chips, small controls */
  --r2:16px;   /* cards, panels */
  --r3:22px;   /* the instrument cluster, sheets */
  --rp:999px;

  /* the material: translucent deck, lit along the top edge */
  --glass:rgba(16,28,44,.62);
  --glass-2:rgba(21,37,57,.72);
  --glass-line:rgba(141,164,190,.20);
  --glass-lit:inset 0 1px 0 rgba(233,241,249,.07);
  --glass-glow:inset 0 26px 46px -34px rgba(120,175,255,.20);
  --lift:0 18px 44px -26px rgba(0,0,0,.9);

  /* ------------------------------------------------------------------------
     2026-08-27 — NEUTRAL AND SYSTEM-FACED.
     Sam: "more neutral colors… like a premium iPhone tool", "iPhone font too".
     qnq.css hands the toolkit a navy+amber brand palette and three webfonts.
     Every one of those tokens is re-pointed here, and ONLY here: toolkit.css
     is loaded by the twelve tool pages and by nothing else on the site, so
     the rest of qnqsolutions.ca is untouched by any of it.

     Amber is not deleted. It is rationed: --pick is the one amber allowed on
     a screen, and it paints exactly one thing — the chosen segment of the
     primary control. White carries the hierarchy everywhere else.
     ------------------------------------------------------------------------ */
  --pick:#FEBE01;

  /* surfaces: neutral near-black, no navy in it */
  --void:#08080A;
  --deck:#0D0E10;
  --deck-2:#111214;
  --panel:#141517;
  --panel-2:#1C1D20;
  --panel-3:#26272B;

  /* ink: white on top, four grays under it */
  --paper:#FFFFFF;
  --paper-dim:#D5D6D9;
  --steel:#9B9DA2;
  --steel-dim:#7A7C81;
  --steel-faint:#5A5C61;

  /* lines */
  --line:rgba(255,255,255,.12);
  --line-soft:rgba(255,255,255,.07);
  --line-strong:rgba(255,255,255,.20);

  /* the accent slot itself is now white — every var(--amber) in this file
     resolves to it, which is how the amber left the page in one move */
  --amber:#F2F3F5;
  --amber-soft:#FFFFFF;
  --amber-deep:#B9BBBF;
  --navy:#2A2C31;
  --navy-lift:#3A3C42;
  --navy-deep:#1A1B1E;

  /* the material, with the blue light and the glow taken out of it */
  --glass:rgba(26,27,30,.62);
  --glass-2:rgba(34,35,39,.72);
  --glass-line:rgba(255,255,255,.13);
  --glass-lit:inset 0 1px 0 rgba(255,255,255,.06);
  --glass-glow:0 0 0 0 rgba(0,0,0,0);

  /* the iPhone font — SF Pro on iOS, the native face everywhere else. No
     webfont is downloaded by a tool page any more; the <link> is gone too. */
  --display:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,sans-serif;
  --body:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,sans-serif;
  --mono:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,sans-serif;
}

/* The site's own header, mobile menu and footer keep the brand palette. They
   are qnqsolutions.ca chrome that happens to sit on the launcher page, not
   toolkit UI, and they are hidden altogether on a phone. */
.hdr,.mnav,.ftr{--amber:#FEBE01;--paper:#E9F1F9;--paper-dim:#C3D3E4;--steel:#8DA4BE}

/* ---------- page shell ---------- */
.tk{padding:calc(var(--header-h) + clamp(20px,4.5vw,44px)) 0 clamp(40px,7vw,72px)}
.tk__in{max-width:42rem;margin:0 auto}
/* The trail. It used to borrow the site's .crumb by accident and looked
   right by luck; this is the same look, chosen on purpose and owned here. */
.tkcrumb{display:flex;align-items:center;flex-wrap:wrap;gap:.55em;
  font-size:.875rem;letter-spacing:0;
  color:var(--steel-faint);margin-bottom:.95rem}
.tkcrumb a{color:var(--steel-dim);transition:color .25s var(--ease)}
.tkcrumb a:hover{color:var(--amber)}
.tk h1{font-size:clamp(1.7rem,5.2vw,2.35rem);line-height:1.08;margin-bottom:.6rem}
.tk .tklede{font-size:1.02rem;line-height:1.62;color:var(--paper-dim);max-width:40rem;
  margin-bottom:1.1rem}

/* ---------- the disclaimer: one dim line, no band, no box ---------- */
.band-warn{
  display:flex;gap:.55rem;align-items:baseline;
  margin:0 0 1.4rem;padding:.75rem 0;
  border:0;background:none;
}
.band-warn svg{width:14px;height:14px;flex:none;stroke:var(--steel-dim);fill:none;
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transform:translateY(2px)}
.band-warn p{font-size:.8125rem;line-height:1.5;color:var(--steel-dim);margin:0;
  font-weight:400}

/* ==========================================================================
   THE INSTRUMENT CLUSTER — the scene and the answer, together, on top
   ========================================================================== */
.cluster{
  position:relative;border:1px solid var(--glass-line);border-radius:var(--r3);
  background:var(--glass);
  -webkit-backdrop-filter:blur(20px) saturate(1.25);backdrop-filter:blur(20px) saturate(1.25);
  box-shadow:var(--glass-lit),var(--glass-glow),var(--lift);
  overflow:hidden;margin-bottom:1.1rem;
  transition:border-color .45s var(--ease),background .45s var(--ease);
}
.cluster::before{  /* the machined hairline that catches the light at the top */
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:linear-gradient(180deg,rgba(233,241,249,.045),rgba(233,241,249,0) 38%);
}

/* the scene sits in the lid */
.scene{position:relative;background:
    radial-gradient(120% 82% at 50% 0%,rgba(255,255,255,.045),rgba(8,8,10,0) 72%);
  border-bottom:1px solid var(--line-soft);
  /* pan-y: a drag that starts vertical scrolls the page like any other part
     of it, and only a sideways drag turns the object. Nobody gets stuck
     inside the picture. */
  touch-action:pan-y}
.scene > svg,.scene > canvas{width:100%;height:auto;display:block;outline:none}
.scene canvas:focus-visible,.scene svg:focus-visible{outline:2px solid var(--amber);
  outline-offset:-2px}

/* the live scene: a canvas, with the numbers on glass over it */
.scene__gl{
  aspect-ratio:320/226;width:100%;display:block;
  touch-action:pan-y;-webkit-user-select:none;user-select:none;cursor:grab;
  opacity:0;transition:opacity .5s var(--ease)}
.scene__gl:active{cursor:grabbing}
.scene__ov{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;
  opacity:0;transition:opacity .5s var(--ease)}
 /* The hint sits at the TOP, because the bottom of the frame is where the
    load and its weight label are. It leaves for good on the first touch. */
.scene__hint{
  position:absolute;left:.55rem;top:.5rem;pointer-events:none;
  padding:.3rem .55rem;border:1px solid var(--glass-line);border-radius:8px;
  background:rgba(8,8,10,.62);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  font-size:.75rem;letter-spacing:0;
  line-height:1.35;max-width:min(62%,17rem);
  color:var(--steel);transition:opacity .45s var(--ease)}
.scene.is-touched .scene__hint{opacity:0}

/* flat is what the markup ships with, and what a phone with no WebGL keeps */
.scene[data-mode="flat"] .scene__gl,
.scene[data-mode="flat"] .scene__ov,
.scene[data-mode="flat"] .scene__hint{display:none}
.scene[data-mode="3d"] .scene__flat{display:none}
.scene[data-mode="3d"] .scene__gl,.scene[data-mode="3d"] .scene__ov{opacity:1}
.scene figcaption{font-size:.8125rem;letter-spacing:0;
  color:var(--steel-faint);text-align:center;padding:0 0 .5rem}

/* the readout, in the same panel as the scene */
.read{padding:1.15rem 1.15rem 1.2rem;position:relative}
.read__k{
  display:flex;align-items:center;gap:.45rem;
  font-size:.875rem;letter-spacing:0;
  color:var(--steel);margin-bottom:.3rem}
.read__k .dot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.rdo{display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap;min-width:0}
.rdo__n{
  font-family:var(--display);font-weight:700;
  font-size:clamp(3.5rem,15.5vw,4rem);        /* 56px on a small phone, 64px up */
  line-height:.98;letter-spacing:-.028em;color:var(--paper);
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1;
  overflow-wrap:anywhere;min-width:0;
}
.rdo__u{
  font-size:1.15rem;color:var(--steel);letter-spacing:0;
  transform:translateY(-.1em)}
.rdo__2{
  font-size:1.02rem;color:var(--steel);margin-top:.35rem;
  font-variant-numeric:tabular-nums;letter-spacing:0}
.rdo__2 span{color:var(--steel)}

/* the answer settles when it changes — it never snaps */
.settle{animation:settle .34s var(--ease-out)}
@keyframes settle{from{opacity:.35;transform:translateY(3px)}to{opacity:1;transform:none}}

/* the supporting facts: a quiet list, no grid, no boxes. Value first in
   white-ish digits, its name under it in dim gray sentence case. */
.mini{display:grid;grid-template-columns:repeat(auto-fit,minmax(8.5rem,1fr));gap:.7rem 1.4rem;
  margin-top:1rem;padding-top:.9rem;border-top:1px solid var(--line-soft)}
.mini > div{min-width:0}
.mini b{display:block;font-size:1.05rem;color:var(--paper-dim);
  font-weight:500;font-variant-numeric:tabular-nums;line-height:1.25;letter-spacing:-.01em}
.mini span{display:block;font-size:.8125rem;letter-spacing:0;
  color:var(--steel-dim);margin-top:.05rem;line-height:1.3}

/* ---------- the verdict is a state the cluster takes, not a box ---------- */
.vline{
  display:none;align-items:flex-start;gap:.6rem;margin-top:1rem;padding-top:.95rem;
  border-top:1px solid var(--line-soft)}
.cluster[data-v] .vline{display:flex}
.vline svg{width:20px;height:20px;flex:none;fill:none;stroke-width:2.3;
  stroke-linecap:round;stroke-linejoin:round;margin-top:.1rem}
.vline b{display:block;font-family:var(--display);
  font-weight:700;font-size:1.05rem;line-height:1.2;
  margin-bottom:.2rem}
.vline p{font-size:.9375rem;line-height:1.55;color:var(--paper-dim);margin:0}

/* Colour here is meaning, not decoration, so it lives on the words and the
   glyph only — the panel behind them no longer changes colour at all. */
.cluster[data-v="ok"] .vline svg{stroke:var(--go)}
.cluster[data-v="ok"] .vline b{color:var(--go)}

.cluster[data-v="tight"] .vline svg{stroke:var(--tight)}
.cluster[data-v="tight"] .vline b{color:var(--tight)}

.cluster[data-v="bad"] .rdo__n{color:var(--stop)}
.cluster[data-v="bad"] .vline svg{stroke:var(--stop)}
.cluster[data-v="bad"] .vline b{color:var(--stop);font-size:1.2rem;letter-spacing:.01em}

/* one hard red pulse when it is not enough — once, never looping */
.cluster.pulse-bad{animation:pulseBad .62s var(--ease-out) 1}
@keyframes pulseBad{
  0%{box-shadow:var(--glass-lit),var(--glass-glow),var(--lift),0 0 0 0 rgba(255,95,82,.55)}
  55%{box-shadow:var(--glass-lit),var(--glass-glow),var(--lift),0 0 0 14px rgba(255,95,82,0)}
  100%{box-shadow:var(--glass-lit),var(--glass-glow),var(--lift),0 0 0 0 rgba(255,95,82,0)}
}

/* The old sticky "pin" that repeated the answer once it scrolled away is gone.
   The instrument stage is sticky now, so the answer never leaves the screen and
   there is nothing left for a second copy of it to do. TK.pin() survives as a
   no-op so the pages that call it keep working. */

/* ==========================================================================
   THE ASSUMPTION GATE — two plain questions before the first answer
   ========================================================================== */
.cluster.is-gated .rdo,.cluster.is-gated .mini,.cluster.is-gated .vline{
  filter:blur(9px);opacity:.5;pointer-events:none;user-select:none}
.gate{
  position:absolute;inset:0;z-index:6;display:flex;flex-direction:column;justify-content:center;
  padding:1.2rem 1.15rem;border-radius:inherit;
  background:linear-gradient(180deg,rgba(8,8,10,.92),rgba(8,8,10,.97));
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
}
.gate[hidden]{display:none}
.gate__k{font-size:.875rem;letter-spacing:0;
  color:var(--steel);margin-bottom:.85rem}
.gq{margin-bottom:.95rem}
.gq p{font-size:1rem;line-height:1.4;color:var(--paper);margin:0 0 .5rem;font-weight:500}
.gq__b{display:grid;grid-template-columns:1fr 1fr;gap:.5rem}
.gq__b button{
  min-height:50px;border:1px solid var(--line-strong);border-radius:var(--r1);
  font-family:var(--display);font-weight:600;font-size:1rem;
  color:var(--paper-dim);background:var(--panel-2);
  transition:border-color .2s,color .2s,background .2s}
.gq__b button:hover{border-color:var(--amber);color:var(--amber)}
.gq__b button[aria-pressed="true"]{background:var(--pick);border-color:var(--pick);
  color:#12160C}
.gq__b button[aria-pressed="true"][data-a="n"]{background:var(--tight);border-color:var(--tight)}
.gate__warn{border-left:3px solid var(--tight);padding-left:.85rem;margin-bottom:1rem}
.gate__warn b{display:block;font-family:var(--display);
  font-weight:700;font-size:1.05rem;color:var(--tight);
  margin-bottom:.3rem}
.gate__warn p{font-size:.9375rem;line-height:1.55;color:var(--paper-dim);margin:0}
.gate__go{
  width:100%;min-height:52px;border-radius:var(--r1);border:1px solid var(--line-strong);
  font-family:var(--display);font-weight:600;font-size:.95rem;
  color:var(--paper);background:var(--panel-2);
  transition:border-color .2s,color .2s}
.gate__go:hover{border-color:var(--amber);color:var(--amber)}
/* the strip that stays behind once somebody said No and looked anyway */
.gflag{display:none;align-items:flex-start;gap:.55rem;margin-top:.9rem;padding-top:.85rem;
  border-top:1px solid rgba(255,176,32,.28)}
.gflag.is-on{display:flex}
.gflag svg{width:16px;height:16px;flex:none;stroke:var(--tight);fill:none;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;margin-top:.15rem}
.gflag p{font-size:.875rem;line-height:1.5;color:var(--tight);margin:0}

/* ==========================================================================
   INPUTS
   ========================================================================== */
.card{
  border:1px solid var(--glass-line);border-radius:var(--r2);background:var(--glass);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  box-shadow:var(--glass-lit);
  padding:1.15rem 1.1rem;margin-bottom:1.1rem;
}
.fld{margin-bottom:1.15rem}
.fld:last-child{margin-bottom:0}
.fld > label,.fld__lab{
  display:block;font-size:.9375rem;letter-spacing:0;
  color:var(--steel);margin-bottom:.45rem;line-height:1.35;font-weight:400;
}
.fld__hint{display:block;font-size:.875rem;color:var(--steel-dim);
  margin-top:.45rem;line-height:1.5;text-transform:none;letter-spacing:0;font-family:var(--body)}
.fld__opt{color:var(--steel-faint);text-transform:none;letter-spacing:.02em;font-size:.75rem}

.inrow{display:flex;gap:.5rem;align-items:stretch}
.inp{
  flex:1 1 auto;min-width:0;width:100%;
  background:var(--void);border:1px solid var(--line-strong);border-radius:var(--r1);
  color:var(--paper);font-size:1.35rem;font-weight:500;
  padding:.62em .7em;min-height:58px;-moz-appearance:textfield;
  font-variant-numeric:tabular-nums;
  transition:border-color .2s var(--ease),box-shadow .2s var(--ease);
}
.inp::-webkit-outer-spin-button,.inp::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.inp::placeholder{color:var(--steel-faint);font-weight:400}
.inp:focus{outline:none;border-color:var(--paper-dim);box-shadow:0 0 0 3px rgba(255,255,255,.10)}
.inp.is-bad{border-color:var(--stop)}
.usel{
  flex:0 0 auto;background:var(--panel);border:1px solid var(--line-strong);
  border-radius:var(--r1);color:var(--paper-dim);font-size:.95rem;
  padding:0 .55rem 0 .75rem;min-height:58px;min-width:5.2rem;cursor:pointer;
  -webkit-appearance:none;appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--steel) 50%),
                   linear-gradient(135deg,var(--steel) 50%,transparent 50%);
  background-position:calc(100% - 17px) 50%,calc(100% - 12px) 50%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:2rem;
}
.usel:focus{outline:none;border-color:var(--amber)}
select.wsel{
  width:100%;background:var(--void);border:1px solid var(--line-strong);border-radius:var(--r1);
  color:var(--paper);font-family:var(--body);font-size:1.02rem;padding:0 1rem;min-height:58px;
  cursor:pointer;-webkit-appearance:none;appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--steel) 50%),
                   linear-gradient(135deg,var(--steel) 50%,transparent 50%);
  background-position:calc(100% - 19px) 50%,calc(100% - 14px) 50%;
  background-size:6px 6px,6px 6px;background-repeat:no-repeat;
}
select.wsel:focus{outline:none;border-color:var(--amber)}

/* ---------- segmented control ---------- */
.tkseg{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:4px;
  background:var(--void);border:1px solid var(--line-strong);border-radius:var(--r1);padding:4px}
.tkseg button{
  min-height:48px;border-radius:9px;font-family:var(--display);
  font-weight:600;font-size:.9375rem;color:var(--steel);
  transition:background .2s var(--ease),color .2s var(--ease);padding:0 .3rem;
  line-height:1.15;
}
.tkseg button[aria-pressed="true"]{background:var(--pick);color:#12160C}
.tkseg button:not([aria-pressed="true"]):hover{background:var(--panel-2);color:var(--paper)}
.tkseg--wrap{grid-auto-flow:row;grid-auto-columns:auto;grid-template-columns:repeat(2,1fr)}
.tkseg--sm button{font-size:.875rem}
/* the unit picker: the same control, shrunk, and deliberately NOT amber —
   amber marks the one primary choice on a screen and this is not it */
.tkseg--u{width:max-content;justify-self:end}
.tkseg--u button{min-height:34px;padding:0 1.05rem;font-size:.875rem;font-weight:500}
.tkseg--u button[aria-pressed="true"]{background:var(--panel-3);color:var(--paper)}
.deck .tkseg.tkseg--u{grid-column:1 / -1;justify-self:end;margin-top:.1rem}
.deck .tkseg.tkseg--u button[aria-pressed="true"]{background:var(--panel-3);color:var(--paper);
  box-shadow:0 1px 3px rgba(0,0,0,.5)}

/* ---------- slider ---------- */
.rngrow{display:flex;gap:.75rem;align-items:center}
.rng{
  flex:1 1 auto;min-width:0;-webkit-appearance:none;appearance:none;background:transparent;
  height:44px;margin:0;cursor:pointer;touch-action:pan-y;
}
.rng::-webkit-slider-runnable-track{height:6px;border-radius:3px;
  background:linear-gradient(90deg,var(--paper) var(--fill,50%),var(--panel-3) var(--fill,50%))}
.rng::-moz-range-track{height:6px;border-radius:3px;background:var(--panel-3)}
.rng::-moz-range-progress{height:6px;border-radius:3px;background:var(--paper)}
.rng::-webkit-slider-thumb{-webkit-appearance:none;width:30px;height:30px;border-radius:50%;
  background:var(--paper);border:3px solid var(--panel-3);margin-top:-12px;
  box-shadow:0 3px 10px rgba(0,0,0,.55)}
.rng::-moz-range-thumb{width:26px;height:26px;border-radius:50%;background:var(--paper);
  border:3px solid var(--panel-3);box-shadow:0 3px 10px rgba(0,0,0,.55)}
.rng:focus{outline:none}
.rng:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 4px rgba(255,255,255,.28)}
.rngval{flex:0 0 auto;font-size:1.3rem;color:var(--paper);
  min-width:4.1rem;text-align:right;font-variant-numeric:tabular-nums}

.chips{display:flex;flex-wrap:wrap;gap:.45rem;margin-top:.7rem}
.chip{
  min-height:40px;padding:0 .9rem;border:1px solid var(--line-strong);border-radius:var(--rp);
  font-size:.875rem;color:var(--steel);
  transition:border-color .2s,color .2s,background .2s;
}
.chip:hover{border-color:var(--amber);color:var(--amber)}
.chip[aria-pressed="true"]{background:rgba(255,255,255,.13);border-color:var(--paper-dim);
  color:var(--paper)}

/* ---------- a plain secondary panel ---------- */
.res{
  border:1px solid var(--glass-line);border-radius:var(--r2);background:var(--glass);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);box-shadow:var(--glass-lit);
  padding:1.1rem 1.1rem 1rem;margin-bottom:1.1rem;
}
.res__k{font-size:.875rem;letter-spacing:0;color:var(--steel);margin-bottom:.65rem}
.res__pair{display:grid;grid-template-columns:1fr 1fr;gap:.5rem 1rem}
.res__pair > div{min-width:0}
.res__pair b{
  display:block;font-weight:600;
  font-size:clamp(1.6rem,7.4vw,2.15rem);line-height:1.05;color:var(--paper);
  font-variant-numeric:tabular-nums;letter-spacing:-.02em;overflow-wrap:anywhere;
}
.res__pair span{display:block;font-size:.8125rem;letter-spacing:0;
  color:var(--steel-dim);margin-top:.25rem}
.res__note,.rdo__note{font-size:.875rem;color:var(--steel-dim);margin-top:.9rem;line-height:1.55}
.res__note a,.rdo__note a{color:var(--amber)}

/* ==========================================================================
   THE ACTION ROW — save, share, history
   ========================================================================== */
.acts{display:grid;grid-template-columns:repeat(3,1fr);gap:.5rem;margin-bottom:.6rem}
.acts button{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.3rem;
  min-height:62px;border:1px solid var(--line-strong);border-radius:var(--r1);
  background:var(--glass);color:var(--paper-dim);
  font-family:var(--display);font-weight:600;font-size:.875rem;
  transition:border-color .2s,color .2s,transform .12s var(--ease);
}
.acts button svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}
.acts button:hover{border-color:var(--amber);color:var(--amber)}
.acts button:active{transform:scale(.97)}
.linkbtn{
  display:flex;align-items:center;justify-content:center;gap:.5em;width:100%;min-height:52px;
  border:1px solid var(--line-strong);border-radius:var(--r1);background:transparent;
  color:var(--steel);font-family:var(--display);
  font-weight:600;font-size:.9375rem;margin-bottom:1.6rem;
  transition:border-color .2s,color .2s}
.linkbtn svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}
.linkbtn:hover{border-color:var(--amber);color:var(--amber)}

.toast{
  position:fixed;left:50%;bottom:24px;z-index:200;
  transform:translate(-50%,14px);
  background:var(--panel-3);color:var(--paper);border:1px solid var(--line-strong);
  border-radius:var(--rp);padding:.7rem 1.2rem;font-size:.9375rem;
  box-shadow:0 14px 34px rgba(0,0,0,.55);opacity:0;pointer-events:none;
  transition:opacity .25s var(--ease),transform .25s var(--ease);max-width:min(92vw,26rem);
  text-align:center;
}
.toast.is-on{opacity:1;transform:translate(-50%,0)}

/* ---------- the history sheet ---------- */
.sheet{position:fixed;inset:0;z-index:180;display:none}
.sheet.is-on{display:block}
.sheet__scrim{position:absolute;inset:0;background:rgba(2,5,10,.72);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  opacity:0;transition:opacity .25s var(--ease)}
.sheet.is-on .sheet__scrim{opacity:1}
.sheet__body{
  position:absolute;left:0;right:0;bottom:0;max-height:82vh;overflow-y:auto;
  -webkit-overflow-scrolling:touch;
  background:var(--deck);border-top:1px solid var(--glass-line);
  border-radius:var(--r3) var(--r3) 0 0;box-shadow:0 -20px 60px rgba(0,0,0,.7);
  padding:.6rem var(--gutter) calc(1.4rem + env(safe-area-inset-bottom));
  transform:translateY(102%);transition:transform .3s var(--ease-out);
}
.sheet.is-on .sheet__body{transform:none}
.sheet__grab{width:44px;height:4px;border-radius:2px;background:var(--line-strong);
  margin:.3rem auto 1rem}
.sheet__hd{display:flex;align-items:center;gap:1rem;margin-bottom:.9rem}
.sheet__hd h2{font-size:1.15rem;line-height:1.2}
.sheet__hd button{margin-left:auto;font-size:.875rem;
  color:var(--steel);padding:.4rem .2rem}
.sheet__hd button:hover{color:var(--stop)}
.hrow{display:block;padding:.85rem 0;border-top:1px solid var(--line-soft)}
.hrow:first-of-type{border-top:0}
.hrow em{display:block;font-size:.8125rem;letter-spacing:0;
  color:var(--steel);font-style:normal;margin-bottom:.28rem}
.hrow b{display:block;font-size:1.15rem;color:var(--paper);
  font-weight:500;font-variant-numeric:tabular-nums;line-height:1.25;margin-bottom:.2rem}
.hrow span{display:block;font-size:.875rem;line-height:1.45;color:var(--steel-dim)}
.hrow time{display:block;font-size:.8125rem;color:var(--steel-faint);
  margin-top:.25rem}
.hempty{font-size:.9375rem;line-height:1.6;color:var(--steel-dim);padding:.4rem 0 1rem}

/* ==========================================================================
   REFERENCE PROSE AND TABLES
   ========================================================================== */
.tkh2{font-size:clamp(1.2rem,3.4vw,1.45rem);margin:2.3rem 0 .8rem;line-height:1.2}
.tkp{font-size:.9375rem;line-height:1.7;color:var(--steel);margin-bottom:1rem}
.tkp b{color:var(--paper-dim)}
.tkp a{color:var(--amber)}
.tkul{margin:0 0 1.2rem;padding-left:1.1rem;list-style:disc}
.tkul li{font-size:.9375rem;line-height:1.7;color:var(--steel);margin-bottom:.4rem}
.tkul li b{color:var(--paper-dim)}
.tkul li a{color:var(--amber)}
.tscroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin-bottom:1.4rem}
.tbl{width:100%;border-collapse:collapse;font-size:.9375rem;min-width:19rem}
.tbl caption{text-align:left;font-size:.8125rem;letter-spacing:0;
  color:var(--steel);padding-bottom:.65rem}
.tbl th{text-align:left;font-weight:500;font-size:.8125rem;
  letter-spacing:0;color:var(--steel-dim);
  border-bottom:1px solid var(--line);padding:0 .55rem .5rem 0;white-space:nowrap}
.tbl td{padding:.6rem .55rem .6rem 0;border-bottom:1px solid var(--line-soft);
  color:var(--paper-dim);font-variant-numeric:tabular-nums;white-space:nowrap}
.tbl tr[data-live="on"] td{color:var(--paper);background:rgba(255,255,255,.06)}
.tbl tr[data-pick="on"] td{color:var(--go);background:rgba(57,208,126,.08);font-weight:500}
.tbl tr[data-pick="no"] td{color:var(--steel-faint)}
.tbl th:last-child,.tbl td:last-child{padding-right:0}
.tbl td.w{white-space:normal;min-width:11rem;color:var(--steel)}

.src{font-size:.875rem;line-height:1.65;color:var(--steel-dim);margin-bottom:1.4rem}
.src b{color:var(--steel)}
.src a{color:var(--amber)}

/* ---------- the one quiet line at the end of every tool ---------- */
.tkend{
  display:flex;flex-wrap:wrap;gap:.6rem 1.2rem;align-items:baseline;
  margin-top:2.4rem;padding-top:1.2rem;border-top:1px solid var(--line);
  font-size:.875rem;color:var(--steel-dim)}
.tkend a{color:var(--steel)}
.tkend a:hover{color:var(--amber)}
.tkend .tkend__back{margin-left:auto;display:inline-flex;align-items:center;gap:.45em;
  font-family:var(--display);font-weight:600;color:var(--paper)}
.tkend .tkend__back svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2.3;
  stroke-linecap:round;stroke-linejoin:round;transform:rotate(180deg)}
.tkend .tkend__back:hover{color:var(--amber)}

/* ==========================================================================
   THE LAUNCHER
   ========================================================================== */
.launch{display:grid;grid-template-columns:repeat(2,1fr);gap:.72rem;margin:1.7rem 0 0}

/* Each tile is a machined face: a dark anodised plate with a lit top edge, a
   deep undershadow, and a cool shop light behind the instrument — steel-white,
   with only a whisper of amber in the core so the grid never reads yellow. */
.launch a{
  position:relative;isolation:isolate;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;gap:0;
  min-height:140px;padding:1.05rem .8rem 1.1rem;
  border:1px solid rgba(150,178,210,.10);border-radius:22px;
  background:linear-gradient(180deg,#1E1F22 0%,#17181B 34%,#111214 72%,#0B0C0E 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.10),
    inset 0 -1px 0 rgba(0,0,0,.6),
    0 1px 0 rgba(0,0,0,.55),
    0 16px 30px -20px rgba(0,0,0,.95);
  transition:transform .22s var(--ease),border-color .22s var(--ease),
    box-shadow .22s var(--ease),background .22s var(--ease);
  -webkit-tap-highlight-color:transparent;
}
/* the ambience sitting behind the icon: a cool steel-white pool, with a small
   amber core underneath it that you feel rather than see */
.launch a::before{
  content:"";position:absolute;inset:0;border-radius:inherit;z-index:-1;pointer-events:none;
  background:
    radial-gradient(46% 33% at 50% 33%,
      rgba(206,225,248,.15),rgba(178,203,233,.045) 50%,transparent 74%),
    radial-gradient(26% 19% at 50% 34%,
      rgba(255,255,255,.05),rgba(255,255,255,0) 72%);
  opacity:.85;transition:opacity .22s var(--ease);
}
/* the specular sweep along the very top of the face */
.launch a::after{
  content:"";position:absolute;left:14%;right:14%;top:0;height:1px;border-radius:2px;
  pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(228,240,255,.58),transparent);
  opacity:.6;transition:opacity .22s var(--ease);
}
.launch i{
  position:relative;display:grid;place-items:center;flex:none;
  width:60px;height:60px;background:none;border:0;border-radius:50%}
.launch i::before{
  content:"";position:absolute;inset:-2px;border-radius:50%;pointer-events:none;
  background:
    radial-gradient(circle at 50% 44%,
      rgba(212,230,250,.16),rgba(190,214,240,.04) 52%,transparent 70%),
    radial-gradient(circle at 50% 46%,
      rgba(255,255,255,.05),rgba(255,255,255,0) 58%)}
.launch i svg{position:relative;width:52px;height:52px;overflow:visible;
  fill:none;stroke:none;stroke-width:0;
  filter:drop-shadow(0 3px 4px rgba(0,0,0,.55)) drop-shadow(0 0 13px rgba(176,203,236,.17))}
.launch b{font-family:var(--display);font-weight:600;
  font-size:.95rem;letter-spacing:.004em;color:var(--paper);line-height:1.22;
  margin-top:.72rem;text-shadow:0 1px 2px rgba(0,0,0,.55)}

@media (hover:hover){
  .launch a:hover{
    transform:translateY(-2px);border-color:rgba(255,255,255,.28);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,.15),
      inset 0 -1px 0 rgba(0,0,0,.6),
      0 0 0 1px rgba(255,255,255,.07),
      0 2px 0 rgba(0,0,0,.5),
      0 24px 38px -22px rgba(0,0,0,.95);
  }
  .launch a:hover::before{opacity:1}
  .launch a:hover::after{opacity:.9}
}
/* pressed: the plate sinks into its recess */
.launch a:active,.launch a.is-pressed{
  transform:translateY(1px) scale(.985);
  border-color:rgba(255,255,255,.16);
  background:linear-gradient(180deg,#111214 0%,#131417 46%,#161719 100%);
  box-shadow:
    inset 0 3px 6px rgba(0,0,0,.72),
    inset 0 1px 0 rgba(0,0,0,.5),
    inset 0 -1px 0 rgba(255,255,255,.05),
    0 1px 3px -2px rgba(0,0,0,.9);
  transition-duration:.07s;
}
.launch a:active::after,.launch a.is-pressed::after{opacity:0}
.launch a:active::before,.launch a.is-pressed::before{opacity:.6}
.launch a:active i svg,.launch a.is-pressed i svg{
  filter:drop-shadow(0 1px 2px rgba(0,0,0,.6))}

@media (min-width:560px){.launch{grid-template-columns:repeat(3,1fr)}}
@media (min-width:820px){.launch{grid-template-columns:repeat(4,1fr);gap:.85rem}}

.badges{display:flex;flex-wrap:wrap;gap:.4rem 1.1rem;margin-top:1.5rem;
  font-size:.875rem;letter-spacing:0;color:var(--steel-dim)}
.badges span{display:inline-flex;align-items:center;gap:.4em}
.badges svg{width:13px;height:13px;stroke:var(--steel);fill:none;stroke-width:2.6;
  stroke-linecap:round;stroke-linejoin:round}


/* ---------- converters: type in any box ---------- */
.cardk{font-size:.875rem;letter-spacing:0;color:var(--steel);margin-bottom:.9rem}
.cvt{display:grid;grid-template-columns:repeat(auto-fit,minmax(8.5rem,1fr));gap:.75rem}
.cvt .fld{margin:0}
.cvt .fld > label{margin-bottom:.4rem}
.cvt .inp{font-size:1.15rem;min-height:52px}
@media (max-width:420px){
  .cvt{grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem}
  .cvt .inp{font-size:1.05rem;padding-inline:.55em}
}

/* ---------- hand signals ---------- */
.sig{display:grid;grid-template-columns:repeat(auto-fill,minmax(15rem,1fr));gap:.8rem;margin-top:1.5rem}
.sigc{border:1px solid var(--glass-line);border-radius:var(--r2);background:var(--glass);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);box-shadow:var(--glass-lit);
  padding:1rem .9rem 1.05rem;text-align:center}
.sigc svg{width:100%;max-width:150px;height:auto;margin:0 auto .55rem}
.sigc b{display:block;font-family:var(--display);font-weight:600;
  font-size:1.05rem;color:var(--paper);margin-bottom:.3rem;line-height:1.2}
.sigc p{font-size:.875rem;line-height:1.5;color:var(--steel);margin:0}
.s-body{stroke:var(--paper-dim);stroke-width:3.4;fill:none;stroke-linecap:round;stroke-linejoin:round}
.s-head{stroke:var(--paper-dim);stroke-width:3.4;fill:none}
.s-arm{stroke:var(--paper);stroke-width:4.4;fill:none;stroke-linecap:round;stroke-linejoin:round}
.s-mot{stroke:var(--steel);stroke-width:2.4;fill:none;stroke-linecap:round;stroke-linejoin:round}
.s-fill{fill:var(--paper)}

/* ---------- the flat 2D diagram, the fallback that is always there ---------- */
.d-load{fill:var(--panel-2);stroke:var(--steel-dim);stroke-width:1.4}
.d-leg{stroke:var(--paper);fill:none;stroke-linecap:round}
.d-line{stroke:var(--steel-faint);stroke-width:1.2;fill:none}
.d-dash{stroke:var(--steel-faint);stroke-width:1.1;fill:none;stroke-dasharray:4 4}
.d-arc{stroke:var(--steel);stroke-width:1.4;fill:none}
.d-hook{stroke:var(--paper-dim);stroke-width:1.7;fill:none;stroke-linecap:round}
.d-t{font-size:13px;font-weight:600;fill:var(--steel);letter-spacing:.02em}
.d-t--a{fill:var(--paper)}
.d-t--p{fill:var(--paper)}
.fig{border:1px solid var(--glass-line);border-radius:var(--r2);background:var(--glass);
  padding:.9rem .6rem .5rem;margin-bottom:1.3rem;overflow:hidden}
.fig svg{width:100%;height:auto;display:block}
.fig figcaption{font-size:.8125rem;letter-spacing:0;
  color:var(--steel-faint);text-align:center;padding:.35rem 0 .3rem}

/* ---------- the numbers on glass over the live scene ----------
   Drawn in CSS pixels over the canvas, not in a scaled viewBox — so on a
   phone this type comes DOWN in size, never up, and stays crisp. */
.s3-t{font-size:13px;font-weight:600;fill:var(--paper);
  letter-spacing:.01em;paint-order:stroke;stroke:rgba(8,8,10,.9);stroke-width:4;
  stroke-linejoin:round}
.s3-t--a{fill:var(--paper)}
.s3-t--s{fill:var(--steel);font-size:12px}
.s3-t--hot{fill:var(--stop)}
.s3-plate{fill:rgba(8,8,10,.55);stroke:rgba(255,255,255,.18);stroke-width:1}
.s3-tick{fill:none;stroke:rgba(255,255,255,.35);stroke-width:1}
.s3-grab{fill:rgba(255,255,255,.05);stroke:var(--paper-dim);stroke-width:1.5}
.s3-rail{fill:none;stroke:rgba(255,255,255,.3);stroke-width:1.2;stroke-dasharray:3 5}
@media (max-width:420px){
  .s3-t{font-size:11.5px;stroke-width:3.5}
  .s3-t--s{font-size:11px}
}

/* the app bar is defined in full in THE INSTRUMENT section at the end of this
   file — it is now the tool's only chrome on a phone, not a standalone extra */
@media (display-mode:standalone){
  .hdr,.mnav,.ftr{display:none!important}
}

/* ==========================================================================
   THE LIFT SHEET — dark on screen, black on white on paper
   ========================================================================== */
.sheetdoc{max-width:44rem;margin:0 auto}
.sd__hd{display:flex;align-items:flex-start;gap:1rem;padding-bottom:1rem;
  border-bottom:2px solid var(--amber);margin-bottom:1.3rem}
.sd__hd img{width:130px;height:auto;flex:none}
.sd__hd div{margin-left:auto;text-align:right}
.sd__hd h1{font-size:1.5rem;line-height:1.1;margin:0}
.sd__hd span{display:block;font-size:.8125rem;color:var(--steel);
  margin-top:.25rem}
.sd__grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.9rem 1.4rem;margin-bottom:1.3rem}
.sd__f{border-bottom:1px solid var(--line);padding-bottom:.5rem;min-width:0}
.sd__f em{display:block;font-size:.8125rem;letter-spacing:0;
  color:var(--steel-dim);font-style:normal;margin-bottom:.28rem}
.sd__f b{display:block;font-size:1.2rem;color:var(--paper);
  font-weight:500;font-variant-numeric:tabular-nums;line-height:1.3;overflow-wrap:anywhere}
.sd__f--wide{grid-column:1 / -1}
.sd__v{border:1px solid var(--line-strong);border-left-width:4px;border-radius:var(--r1);
  padding:.85rem 1rem;margin-bottom:1.3rem}
.sd__v b{display:block;font-family:var(--display);
  font-weight:700;font-size:1.1rem;margin-bottom:.25rem}
.sd__v p{margin:0;font-size:.9375rem;line-height:1.55;color:var(--paper-dim)}
.sd__v[data-v="ok"]{border-color:var(--go)}.sd__v[data-v="ok"] b{color:var(--go)}
.sd__v[data-v="tight"]{border-color:var(--tight)}.sd__v[data-v="tight"] b{color:var(--tight)}
.sd__v[data-v="bad"]{border-color:var(--stop)}.sd__v[data-v="bad"] b{color:var(--stop)}
.sd__sig{display:grid;grid-template-columns:repeat(2,1fr);gap:1.4rem;margin-top:1.8rem}
.sd__sig label{display:block;font-size:.8125rem;letter-spacing:0;
  color:var(--steel-dim);margin-bottom:.4rem}
.sd__sig input{width:100%;background:transparent;border:0;border-bottom:1px solid var(--line-strong);
  color:var(--paper);font-family:var(--body);font-size:1.05rem;padding:.35rem 0;min-height:44px}
.sd__sig input:focus{outline:none;border-bottom-color:var(--amber)}
.sd__note{font-size:.875rem;line-height:1.6;color:var(--steel-dim);margin-top:1.6rem;
  padding-top:1rem;border-top:1px solid var(--line)}

@media print{
  @page{size:letter;margin:14mm}
  html,body{background:#fff!important;color:#000!important}
  .hdr,.mnav,.ftr,.tkbar,.pin,.tkcrumb,.noprint,.toast,.sheet,.abar,
  .tkinfo__scrim,.tkinfo__grab,.tkinfo__hd,.signav,.sigdots,.sigcount{display:none!important}
  .tk{padding:0!important}
  .wrap{padding:0!important;max-width:none!important}
  .sheetdoc,.tk__in{max-width:none!important}
  h1,h2,h3,b,strong{color:#000!important}
  p,li,td,th,span,em,div{color:#111!important}
  .sd__hd{border-bottom:2px solid #000}
  .sd__f{border-bottom:1px solid #999}
  .sd__f em,.sd__sig label,.hrow em{color:#555!important}
  .sd__v{border-color:#000!important;border-left-width:4px}
  .sd__sig input{border-bottom:1px solid #000;color:#000!important}
  .sd__note,.src{color:#444!important}
  .card,.res,.cluster,.tbl,.sigc{background:#fff!important;box-shadow:none!important;
    -webkit-backdrop-filter:none!important;backdrop-filter:none!important;
    border-color:#bbb!important}
  .tbl th{border-bottom:1px solid #000;color:#000!important}
  .tbl td{border-bottom:1px solid #ddd}
  .tbl caption{color:#000!important}
  .tscroll{overflow:visible!important}
  .tkh2{page-break-after:avoid;break-after:avoid}
  .tbl{page-break-inside:auto}
  tr{page-break-inside:avoid}
  a{color:#000!important;text-decoration:none}
  .band-warn{border-color:#000!important;background:none!important}
  .band-warn p{color:#000!important}
}

/* ---------- small screens ---------- */
@media (max-width:420px){
  .res__pair{gap:.9rem}
  .res__pair b{font-size:clamp(1.5rem,8.2vw,1.95rem)}
  .usel{min-width:4.6rem;font-size:.9375rem;padding-right:1.75rem;
    background-position:calc(100% - 14px) 50%,calc(100% - 10px) 50%}
  .inp{font-size:1.2rem}
  .sig{grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem}
  .sigc{padding:.75rem .5rem .8rem}
  .sigc b{font-size:.9375rem}
  .sigc p{font-size:.8125rem}
  .read{padding:1rem .95rem 1.05rem}
  .sd__grid,.sd__sig{grid-template-columns:1fr}
}
@media (max-width:340px){
  .sig{grid-template-columns:1fr}
  .launch{grid-template-columns:1fr}
}

@media (prefers-reduced-motion:reduce){
  .launch a{transition:none}
  .launch a:hover{transform:none}
  .launch a:active,.launch a.is-pressed{transform:none}
  .toast{transition:opacity .01s}
  .settle{animation:none}
  .cluster.sweep-ok::after{display:none}
  .cluster.pulse-bad{animation:none}
  .sheet__body{transition:none}
  .pin{transition:opacity .01s}
}

/* ==========================================================================
   THE INSTRUMENT
   --------------------------------------------------------------------------
   Sam, 27 Aug: "I want it to look like a real tool… the way Apple would build
   it into an iPhone. Very clean and easy to use."

   So on a phone a tool page is not a web page with a calculator on it. It is
   one instrument, composed the way Measure, Level and Compass are:

     · ONE BAR. A 52px nav bar — back chevron, the tool's name, ⓘ. No site
       header, no breadcrumb trail, no second navigation of any kind.
     · THE READING OWNS THE TOP. The stage (the live 3D scene and the giant
       number under it) is sticky, so it is on screen the whole time you are
       touching the controls. That is why the old floating "pin" is gone.
     · THE CONTROLS ARE THE ONLY THING THAT SCROLLS, and they sit in the thumb
       zone: segmented pickers, one slider, one big numeric field.
     · THE ACTION BAR IS FIXED at the bottom — Save, Share, History, Sheet —
       four glyphs, the way a system app puts its verbs.
     · EVERYTHING ELSE IS BEHIND ⓘ. The angle-factor table, the sources, what
       the tool does not know, the closing line. Reachable in one tap, never
       in the way. The amber disclaimer stays out here as one hairline, and it
       is the button that opens that sheet.

   Above 820px the site header comes back and the page relaxes into an
   ordinary document with the instrument at the top of it: a desktop visitor
   arrived from a search result and should be able to reach the rest of QnQ.
   ========================================================================== */
:root{
  --navh:52px;         /* the bar, before the safe area is added to it */
  --abarh:60px;        /* the fixed action bar at the bottom */
  --stage-scene:clamp(148px,25dvh,264px);
}

/* ---------- the nav bar ---------- */
.tkbar{
  display:flex;align-items:center;gap:.2rem;
  position:sticky;top:0;z-index:60;
  min-height:var(--navh);
  padding-top:env(safe-area-inset-top);
  padding-left:max(6px,env(safe-area-inset-left));
  padding-right:max(6px,env(safe-area-inset-right));
  background:rgba(8,8,10,.92);
  -webkit-backdrop-filter:saturate(1.7) blur(18px);backdrop-filter:saturate(1.7) blur(18px);
  border-bottom:1px solid var(--line);
}
.tkbar__back,.tkbar__i{
  flex:none;width:44px;height:44px;display:flex;align-items:center;justify-content:center;
  border:0;background:none;border-radius:12px;color:var(--amber);cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  transition:transform .16s var(--ease),background-color .16s var(--ease);
}
.tkbar__back svg,.tkbar__i svg{width:25px;height:25px;fill:none;stroke:currentColor;
  stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.tkbar__i svg{width:23px;height:23px;stroke-width:1.9}
.tkbar__back:active,.tkbar__i:active,
.tkbar__back.is-pressed,.tkbar__i.is-pressed{transform:scale(.88);background:rgba(255,255,255,.10)}
.tkbar h1,.tkbar strong{
  flex:1 1 auto;min-width:0;margin:0;text-align:center;
  font-family:var(--display);font-weight:700;
  font-size:1rem;line-height:1.2;letter-spacing:-.004em;color:var(--paper);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tkbar--doc h1,.tkbar--doc strong{text-align:left;padding-left:.15rem}
/* with no ⓘ on the right the title would sit off-centre, so a doc bar reads
   left, the way a Files or Notes document header does */
.tkread .band-warn{cursor:default}

/* a tool with no picture puts the number in the middle of its own stage */
.tkstage[data-stage="num"] .read{padding-top:1.15rem;padding-bottom:1.15rem}

/* ---------- the stage: what the tool is actually reading ---------- */
.tkstage{
  position:sticky;top:calc(var(--navh) + env(safe-area-inset-top));z-index:20;
  background:var(--void);
}
.tkstage .cluster{
  margin:0;border-radius:0;border-left:0;border-right:0;border-top:0;
  box-shadow:none;background:transparent;
  /* THE BACKDROP FILTER STAYS, AND IT IS NOT DECORATION. Measured at 4x CPU
     throttle, dragging the 3D scene: with it, 16.7 ms a frame; without it,
     50 ms. It is what puts the cluster on its own compositing layer, so a new
     canvas frame no longer re-rasters the whole sticky instrument behind it.
     Over the flat near-black stage it blurs nothing anybody can see — it is
     here for the compositor, and removing it costs three times the frame. */
  -webkit-backdrop-filter:blur(20px) saturate(1.25);
  backdrop-filter:blur(20px) saturate(1.25);
}
.tkstage .cluster::before{display:none}

/* the scene becomes a fixed-height window, not a fixed-aspect picture, so the
   readout under it can be a known size on every phone. Both the canvas and the
   flat SVG fill it; three.js re-fits itself off the element's own box. */
.tkstage .scene{height:var(--stage-scene);border-bottom:0}
/* the picture fades into the reading below it. This is an overlay and not a
   mask on the scene, deliberately: a mask has to be applied when the layer is
   rastered, which put the live canvas back on the slow path — 50 ms a frame
   against 17. Painted over a flat stage the two are indistinguishable. */
.tkstage .scene::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:26%;z-index:1;
  pointer-events:none;
  background:linear-gradient(180deg,rgba(8,8,10,0),rgba(8,8,10,.72));
}
.tkstage .scene > svg,.tkstage .scene > canvas{
  position:absolute;inset:0;width:100%;height:100%;aspect-ratio:auto}
.tkstage .scene__hint{left:auto;right:.6rem;top:.55rem}

/* the readout, floating under the picture with no card of its own */
.tkstage .read{padding:.85rem var(--gutter) 1rem}
.tkstage .read__k{margin-bottom:.25rem;font-size:.8125rem;letter-spacing:0}
.tkstage .rdo__n{font-size:clamp(3.25rem,15.5vw,4.25rem)}
.tkstage .rdo__2{font-size:1.05rem;margin-top:.35rem}
.tkstage .mini{
  grid-template-columns:repeat(3,minmax(0,1fr));gap:0 .7rem;
  margin-top:.7rem;padding-top:.65rem}
.tkstage .mini b{font-size:.95rem}
.tkstage .mini span{font-size:.75rem;letter-spacing:0;margin-top:.05rem}
.tkstage .vline{margin-top:.75rem;padding-top:.7rem}
.tkstage .vline b{font-size:.95rem}
.tkstage .vline p{font-size:.8125rem;line-height:1.45}
.tkstage .gflag{margin-top:.7rem;padding-top:.6rem}
.tkstage .gflag p{font-size:.8125rem}
.tkstage .gate{padding:1rem var(--gutter)}

/* ---------- the amber hairline: the one disclaimer that stays out here ---- */
.band-warn{
  width:100%;text-align:left;cursor:pointer;-webkit-tap-highlight-color:transparent;
  border-left:0;border-right:0;-webkit-appearance:none;appearance:none;
  padding:.6rem var(--gutter) .65rem;margin:0;
  transition:background-color .18s var(--ease);
}
.band-warn:active{background:rgba(255,255,255,.06)}
/* on the launcher and the two document pages the column already has a gutter,
   so the line must not be indented a second time */
.tk__in .band-warn,.tkread .band-warn{padding-inline:0}
.band-warn p{font-size:.8125rem;line-height:1.45}

/* ---------- the controls ---------- */
.deck{padding:1rem 0 0}
.deck .card{
  border-left:0;border-right:0;border-radius:0;margin-bottom:0;
  background:transparent;box-shadow:none;
  -webkit-backdrop-filter:none;backdrop-filter:none;
  padding:1.05rem var(--gutter) 1.1rem;
}
.deck .card + .card{border-top:1px solid var(--line-soft)}
.deck .card:first-child{border-top:0}
.deck .card:last-of-type{border-bottom:0}

/* ---------- the fixed action bar ---------- */
.abar{
  position:fixed;left:0;right:0;bottom:0;z-index:55;
  padding-bottom:env(safe-area-inset-bottom);
  background:rgba(8,8,10,.92);
  -webkit-backdrop-filter:saturate(1.7) blur(18px);backdrop-filter:saturate(1.7) blur(18px);
  border-top:1px solid var(--line);
}
.abar .acts{
  display:flex;gap:0;margin:0;
}
.abar .acts button,.abar .linkbtn{
  flex:1 1 0;min-width:0;min-height:var(--abarh);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.22rem;
  border:0;border-radius:0;background:none;margin:0;
  color:var(--steel);font-family:var(--mono);font-size:.625rem;letter-spacing:.06em;
  text-transform:uppercase;white-space:nowrap;
  -webkit-tap-highlight-color:transparent;
  transition:color .16s var(--ease),transform .16s var(--ease);
}
.abar .acts button svg,.abar .linkbtn svg{width:22px;height:22px;stroke-width:1.8}
.abar .acts button:active,.abar .linkbtn:active,
.abar .acts button.is-pressed,.abar .linkbtn.is-pressed{color:var(--amber);transform:scale(.9)}
.abar__row{display:flex;align-items:stretch}
.abar__row .acts{flex:1 1 auto}

/* ---------- the ⓘ sheet: everything the instrument does not need ---------- */
.tkinfo{position:fixed;inset:0;z-index:170;display:none}
.tkinfo.is-on{display:block}
.tkinfo__scrim{position:absolute;inset:0;background:rgba(2,5,10,.72);
  opacity:0;transition:opacity .28s var(--ease)}
.tkinfo.is-on .tkinfo__scrim{opacity:1}
.tkinfo__body{
  position:absolute;left:0;right:0;bottom:0;top:calc(env(safe-area-inset-top) + 34px);
  display:flex;flex-direction:column;
  border-radius:var(--r3) var(--r3) 0 0;
  background:rgba(10,18,28,.97);
  -webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);
  border-top:1px solid var(--glass-line);
  box-shadow:0 -22px 60px -30px rgba(0,0,0,.95);
  transform:translateY(100%);transition:transform .34s var(--ease-out);
}
.tkinfo.is-on .tkinfo__body{transform:none}
.tkinfo__grab{width:44px;height:4px;border-radius:2px;background:var(--line-strong);
  margin:.55rem auto .1rem;flex:none}
.tkinfo__hd{display:flex;align-items:center;gap:1rem;flex:none;
  padding:.35rem var(--gutter) .7rem;border-bottom:1px solid var(--line-soft)}
.tkinfo__hd h2{font-size:1.05rem;line-height:1.2;margin:0}
.tkinfo__hd button{margin-left:auto;background:none;border:0;color:var(--amber);
  font-family:var(--display);font-weight:600;
  font-size:.9375rem;min-height:44px;padding:0 .2rem;cursor:pointer}
.tkinfo__scroll{
  flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
  overscroll-behavior:contain;
  padding:1.1rem var(--gutter) calc(2rem + env(safe-area-inset-bottom));
}
.tkinfo__scroll > *:first-child{margin-top:0}
.tkinfo__scroll .tkh2:first-child{margin-top:0}
.tkinfo__scroll .tklede{margin-bottom:1.3rem}

/* ==========================================================================
   PHONE — the instrument takes the screen
   ========================================================================== */
@media (max-width:819.98px){
  /* .tkapp is on the twelve tool pages and NOT on the launcher, which keeps
     the site's own header — it is the way back into qnqsolutions.ca */
  body.tkapp .hdr,body.tkapp .mnav{display:none!important}
  body.tkapp .tk{padding:0 0 calc(var(--abarh) + env(safe-area-inset-bottom))}
  body.tkapp .tk--noabar{padding-bottom:clamp(28px,6vw,48px)}
  body.tkapp .tkcrumb{display:none}
  body.tkapp .tk .wrap{padding-inline:0}
  body.tkapp .tk__in{max-width:none}
}

/* ==========================================================================
   DESKTOP — the site comes back and the instrument sits at the top of a page
   ========================================================================== */
@media (min-width:820px){
  .tkbar{
    position:static;background:none;border-bottom:0;-webkit-backdrop-filter:none;
    backdrop-filter:none;padding:calc(var(--header-h) + clamp(20px,4vw,40px)) var(--gutter) 0;
    max-width:var(--wrap);margin-inline:auto;gap:.5rem;
  }
  .tkbar__back{width:38px;height:38px;margin-left:-8px}
  .tkbar h1,.tkbar strong{text-align:left;font-size:clamp(1.7rem,3.4vw,2.35rem);
    font-weight:700;line-height:1.08;white-space:normal;
    overflow:visible;text-overflow:clip}
  .tkbar__i{display:none}
  body.tkapp .tk{padding-top:.9rem}
  .tkstage{position:sticky;top:calc(var(--header-h) + 12px);
    max-width:var(--wrap);margin-inline:auto;padding-inline:var(--gutter);background:none}
  .tkstage .cluster{
    max-width:42rem;margin:0 auto;border:1px solid var(--glass-line);border-radius:var(--r3);
    background:var(--glass);box-shadow:var(--glass-lit),var(--glass-glow),var(--lift);
    -webkit-backdrop-filter:blur(20px) saturate(1.25);backdrop-filter:blur(20px) saturate(1.25);
  }
  .tkstage .cluster::before{display:block}
  .tkstage .scene{height:auto;-webkit-mask-image:none;mask-image:none;
    border-bottom:1px solid var(--line-soft)}
  .tkstage .scene > svg,.tkstage .scene > canvas{position:relative;height:auto}
  .tkstage .scene__gl{aspect-ratio:320/226}
  .tkstage .read{padding:1.15rem 1.15rem 1.2rem}
  .tkstage .mini{grid-template-columns:repeat(auto-fit,minmax(8.5rem,1fr));
    gap:.6rem 1rem;margin-top:1.05rem;padding-top:1rem}
  .tkstage .mini b{font-size:1.12rem}
  .tkstage .mini span{font-size:.8125rem;letter-spacing:0}
  .band-warn{max-width:42rem;margin:1.1rem auto 0;padding-inline:0;cursor:default}
  .deck{max-width:42rem;margin:0 auto;padding:1.4rem var(--gutter) 0}
  .deck .card{border:1px solid var(--glass-line);border-radius:var(--r2);
    background:var(--glass);box-shadow:var(--glass-lit);
    -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
    padding:1.15rem 1.1rem;margin-bottom:1.1rem}
  .deck .card + .card{border-top:1px solid var(--glass-line)}
  .abar{position:static;background:none;border-top:0;-webkit-backdrop-filter:none;
    backdrop-filter:none;max-width:42rem;margin:0 auto 1.6rem;padding:0 var(--gutter)}
  .abar .acts{display:grid;grid-template-columns:repeat(3,1fr);gap:.5rem;margin-bottom:.6rem}
  .abar__row{display:block}
  .abar .acts button{
    min-height:62px;border:1px solid var(--line-strong);border-radius:var(--r1);
    background:var(--glass);color:var(--paper-dim);font-family:var(--display);
    font-weight:600;font-size:.875rem;letter-spacing:0;
    text-transform:none}
  .abar .acts button svg,.abar .linkbtn svg{width:19px;height:19px;stroke-width:1.9}
  .abar .linkbtn{flex:none;flex-direction:row;gap:.5em;min-height:52px;
    border:1px solid var(--line-strong);border-radius:var(--r1);color:var(--steel);
    font-family:var(--display);font-weight:600;
    font-size:.9375rem;letter-spacing:0;text-transform:none;margin-bottom:1.6rem}
  .tkinfo{position:static;display:block;z-index:auto}
  .tkinfo__scrim,.tkinfo__grab,.tkinfo__hd{display:none}
  .tkinfo__body{position:static;transform:none;background:none;border-top:0;box-shadow:none;
    border-radius:0;-webkit-backdrop-filter:none;backdrop-filter:none;display:block}
  .tkinfo__scroll{overflow:visible;padding:0 var(--gutter) clamp(40px,7vw,72px);
    max-width:calc(42rem + var(--gutter) * 2);margin-inline:auto}
}

/* ==========================================================================
   HAND SIGNALS — one signal per screen, swiped
   ========================================================================== */
.sigdeck{position:relative}
.sigtrack{
  display:flex;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;
  -webkit-overflow-scrolling:touch;scrollbar-width:none;
  overscroll-behavior-x:contain;gap:0;
}
.sigtrack::-webkit-scrollbar{display:none}
.sigtrack .sigc{
  flex:0 0 100%;width:100%;scroll-snap-align:center;scroll-snap-stop:always;
  border:0;border-radius:0;background:none;box-shadow:none;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:.4rem var(--gutter) 1rem;text-align:center;
}
.sigtrack .sigc svg{
  width:100%;max-width:min(78vw,320px);height:auto;
  max-height:calc(100dvh - 300px);margin:0 auto .9rem}
.sigtrack .sigc b{font-family:var(--display);font-weight:700;
  font-size:clamp(1.35rem,6.4vw,1.8rem);color:var(--paper);line-height:1.12;
  margin-bottom:.4rem;display:block}
.sigtrack .sigc p{font-size:.9375rem;line-height:1.55;color:var(--steel);margin:0;
  max-width:26rem}
.sigcount{
  display:flex;align-items:center;justify-content:center;gap:.9rem;
  padding:.4rem 0 .2rem;font-size:.8125rem;letter-spacing:0;
  color:var(--steel-faint)}
.sigcount b{color:var(--paper);font-weight:500;font-variant-numeric:tabular-nums}
.sigdots{display:flex;gap:5px;justify-content:center;flex-wrap:wrap;
  padding:.15rem var(--gutter) .1rem}
.sigdots i{width:6px;height:6px;border-radius:50%;background:var(--steel-faint);
  transition:background-color .2s var(--ease),transform .2s var(--ease)}
.sigdots i.is-on{background:var(--amber);transform:scale(1.35)}
.signav{
  position:absolute;top:50%;transform:translateY(-50%);z-index:3;
  width:44px;height:44px;display:none;align-items:center;justify-content:center;
  border:1px solid var(--line-strong);border-radius:50%;background:rgba(8,8,10,.7);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  color:var(--paper-dim);cursor:pointer}
.signav svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2.4;
  stroke-linecap:round;stroke-linejoin:round}
.signav--p{left:.5rem}
.signav--n{right:.5rem}
.signav[disabled]{opacity:.28;pointer-events:none}
@media (hover:hover) and (pointer:fine){.signav{display:flex}}

/* ==========================================================================
   THE READERS — reference tables and the lift sheet are documents, not
   instruments. They get a clean reading column and nothing else.
   ========================================================================== */
.tkread{padding-top:1.35rem}
.tkread .tkh2:first-of-type{margin-top:1.6rem}
@media (max-width:819.98px){
  .tkread{padding-inline:var(--gutter)}
  /* it used to be a full-bleed band; it is a line of text now, so it lines up
     with the words above it instead of bleeding past them */
  .tkread .band-warn{margin-inline:0;padding-inline:0}
  .tkread .tklede{font-size:1rem}
}
@media (min-width:820px){
  .tkread{max-width:calc(42rem + var(--gutter) * 2);margin-inline:auto;
    padding-inline:var(--gutter)}
}

@media (prefers-reduced-motion:reduce){
  .tkinfo__body{transition:none}
  .tkbar__back,.tkbar__i,.abar .acts button,.abar .linkbtn{transition:none}
  .sigtrack{scroll-behavior:auto}
}

/* ==========================================================================
   THE UNIT CONVERTER — four instruments, not sixteen little boxes
   --------------------------------------------------------------------------
   There is no single hero number here because all four readings are equally
   the answer. So every unit gets a full-width row: the name on the left, the
   value in big tabular digits on the right, and the whole row is the field.
   Type in any of them and the other three move — the same behaviour it always
   had, given the size it deserves.
   ========================================================================== */
.cvtdeck{padding-bottom:clamp(28px,6vw,56px)}
.cvt{display:block;padding:.95rem 0 .1rem;border-top:1px solid var(--line-soft)}
.cvt:first-child{border-top:0}
.cvt__k{font-size:.875rem;letter-spacing:0;
  color:var(--steel);margin:0 0 .35rem;padding:0 var(--gutter);font-weight:400}
.cvtr{
  display:flex;align-items:center;gap:1rem;min-height:58px;
  padding:0 var(--gutter);border-top:1px solid var(--line-soft);cursor:text;
  transition:background-color .18s var(--ease);
}
.cvt__k + .cvtr{border-top:0}
.cvtr > span{flex:0 0 auto;font-size:.9375rem;letter-spacing:0;color:var(--steel)}
.cvtr__v{
  flex:1 1 auto;width:100%;min-width:0;background:none;border:0;text-align:right;
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.35rem,6.4vw,1.9rem);line-height:1.15;letter-spacing:-.015em;
  color:var(--paper);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1;
  padding:.45rem 0;min-height:46px;
}
.cvtr__v::-webkit-outer-spin-button,.cvtr__v::-webkit-inner-spin-button{
  -webkit-appearance:none;margin:0}
.cvtr__v:focus{outline:none;color:var(--paper)}
.cvtr:focus-within{background:rgba(255,255,255,.045)}
.cvt__n{font-size:.8125rem;line-height:1.55;color:var(--steel-dim);
  margin:.6rem 0 .95rem;padding:0 var(--gutter)}
.cvt__n a{color:var(--amber)}
.cvt--link{padding-bottom:.3rem}
@media (min-width:820px){
  .cvtdeck{max-width:calc(42rem + var(--gutter) * 2);margin-inline:auto}
  .cvtr{border-radius:var(--r1)}
}

/* ==========================================================================
   HAND SIGNALS — the deck fills the screen
   ========================================================================== */
@media (max-width:819.98px){
  .tk--sig{display:flex;flex-direction:column;
    min-height:calc(100dvh - var(--navh) - env(safe-area-inset-top))}
  .tk--sig .sigdeck{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
  .tk--sig .sigtrack{flex:1 1 auto;min-height:0}
  .tk--sig .band-warn{margin-top:auto}
}
@media (min-width:820px){
  .sigdeck{max-width:var(--wrap);margin:1rem auto 0;padding-inline:var(--gutter)}
  .sigtrack .sigc{padding-block:1.4rem 2rem}
  .sigtrack .sigc svg{max-width:300px;max-height:none}
}

/* ==========================================================================
   ROUND 2 — THE CONTROL DECK AS ROWS
   --------------------------------------------------------------------------
   A stack of outlined boxes with shouting uppercase labels over them is a web
   form. What a system app does instead is a grouped list: the thing being set
   named in plain sentence case on the left, its value in big tabular digits on
   the right, a hairline between rows, edge to edge. Nothing here changes a
   field, an id or a value — the same markup is simply laid out as rows.
   ========================================================================== */
.deck .card{padding:0;border-top:0}
.deck .card + .card{border-top:1px solid var(--line-soft)}
.deck .cardk{padding:1.05rem var(--gutter) .1rem;margin:0}

.deck .fld{
  /* both tracks have a floor: an "auto" label column could grow to its own
     max-content and squeeze the value column to nothing, which took the input
     out of the page entirely. The label wraps instead. */
  display:grid;grid-template-columns:minmax(0,1fr) minmax(8.5rem,1fr);
  align-items:center;column-gap:1rem;row-gap:.35rem;
  margin:0;padding:.55rem var(--gutter) .6rem;
  border-top:1px solid var(--line-soft);
  transition:background-color .18s var(--ease);
}
.deck .card > .fld:first-child,.deck .cardk + .fld,
.deck [data-shape] > .fld:first-child{border-top:0}
.deck .fld:focus-within{background:rgba(255,255,255,.04)}

.deck .fld > label{
  grid-column:1;min-width:0;margin:0;
  font-family:var(--body);font-size:.9375rem;line-height:1.3;letter-spacing:0;
  text-transform:none;color:var(--paper-dim);font-weight:400;
}
.deck .fld__opt{font-size:.8125rem;color:var(--steel-faint)}
.deck .fld__lab{
  grid-column:1 / -1;margin:0 0 .1rem;
  font-family:var(--body);font-size:.9375rem;line-height:1.3;letter-spacing:0;
  text-transform:none;color:var(--paper-dim);font-weight:400;
}
.deck .fld > .inp,.deck .fld > .inrow{grid-column:2}
.deck .fld > .tkseg,.deck .fld > .chips,.deck .fld > .fld__hint,
.deck .fld > select.wsel{grid-column:1 / -1}
.deck .fld__hint{
  font-size:.8125rem;line-height:1.5;color:var(--steel-dim);margin:.15rem 0 .1rem}

/* the value itself: no box, right-aligned, the biggest ink in the row */
.deck .inp{
  background:none;border:0;border-radius:0;padding:.1rem 0;min-height:44px;width:100%;
  text-align:right;font-family:var(--display);
  font-weight:700;font-size:1.5rem;line-height:1.15;letter-spacing:-.012em;
  color:var(--paper);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1;
}
.deck .inp:focus{outline:none;border:0;box-shadow:none;color:var(--paper)}
.deck .inp.is-bad{color:var(--stop)}
.deck .inrow{gap:.55rem;align-items:center;justify-content:flex-end}
.deck .inrow .inp{flex:1 1 auto;min-width:0}

/* the unit picker shrinks to a chip — the value is the thing being read */
.deck .usel{
  flex:0 0 auto;min-height:44px;min-width:0;border-radius:var(--rp);
  background-color:var(--panel-2);border:1px solid var(--line);
  font-size:.8125rem;color:var(--paper-dim);
  padding:0 1.55rem 0 .7rem;
  background-position:calc(100% - 15px) 50%,calc(100% - 10px) 50%;
  background-size:5px 5px,5px 5px;
}
/* a long menu (material, units of measure) gets the whole row under its name */
.deck select.wsel{
  min-height:46px;border-radius:var(--r1);background-color:var(--panel);
  border-color:var(--line);font-size:.9375rem;padding:0 2.4rem 0 .85rem;
  color:var(--paper-dim);margin-top:.1rem}

/* segmented: an iOS track with the chosen chip sitting proud of it */
.deck .tkseg{
  gap:3px;padding:3px;border-radius:11px;background:var(--panel-2);
  border:1px solid var(--line-soft);margin-top:.1rem}
.deck .tkseg button{
  min-height:38px;border-radius:8px;font-size:.875rem;
  font-weight:600;color:var(--steel);
  transition:background-color .18s var(--ease),color .18s var(--ease)}
.deck .tkseg button[aria-pressed="true"]{
  background:var(--pick);color:#12160C;font-weight:700;
  box-shadow:0 1px 3px rgba(0,0,0,.5)}

/* slider: the reading sits beside the name, the track runs the full width */
.deck .fld > .rngrow{display:contents}
.deck .rngval{grid-column:2;grid-row:1;justify-self:end;
  font-family:var(--display);font-weight:700;
  font-size:1.5rem;color:var(--paper);letter-spacing:-.012em;text-align:right}
.deck .rng{grid-column:1 / -1;margin:.35rem 0 .1rem}
.deck .chips{margin-top:.5rem;gap:.4rem}
.deck .chip{min-height:36px;padding:0 .85rem;border-radius:var(--rp);font-size:.8125rem}

/* the planner's "from the tension tool" banner is a notice, not a field */
.deck .card#fromTension{background:rgba(255,255,255,.05)}

@media (min-width:820px){
  .deck .card{padding:1.15rem 1.1rem}
  .deck .cardk{padding:0 0 .6rem}
  .deck .fld{display:block;padding:0;border-top:0;margin-bottom:1.15rem}
  .deck .fld:last-child{margin-bottom:0}
  .deck .fld > label,.deck .fld__lab{
    font-size:.9375rem;letter-spacing:0;
    color:var(--steel);margin-bottom:.5rem;display:block}
  .deck .inp{background:var(--void);border:1px solid var(--line-strong);
    border-radius:var(--r1);padding:0 .9rem;min-height:58px;text-align:left;
    font-size:1.35rem}
  .deck .inp:focus{border-color:var(--paper-dim);box-shadow:0 0 0 3px rgba(255,255,255,.10);
    color:var(--paper)}
  .deck .fld:focus-within{background:none}
  .deck .usel{min-height:58px;min-width:5.2rem;border-radius:var(--r1);
    background-color:var(--panel);border-color:var(--line-strong);font-size:.95rem;
    padding:0 2rem 0 .75rem}
  .deck select.wsel{min-height:58px;background-color:var(--void);
    border-color:var(--line-strong);font-size:1.02rem;padding:0 1rem}
  .deck .fld > .rngrow{display:flex}
  .deck .rngval{font-size:1.3rem}
}

/* ==========================================================================
   ROUND 3 — the tuning pass
   ========================================================================== */
@media (max-width:819.98px){
  :root{--stage-scene:clamp(140px,23dvh,232px)}

  /* the supporting figures read as one instrument face: every cell the same
     height, so four long ones never turn into a ragged block of text */
  .tkstage .mini{grid-template-columns:repeat(3,minmax(0,1fr));gap:.55rem .7rem;
    align-items:start;margin-top:.65rem;padding-top:.6rem}
  .tkstage .mini > div{display:flex;flex-direction:column;min-width:0}
  .tkstage .mini b{font-size:.9375rem;line-height:1.25;min-height:2.5em;
    overflow-wrap:anywhere;display:block}
  .tkstage .mini span{font-size:.75rem;line-height:1.25;letter-spacing:0;
    margin-top:.05rem;min-height:2.4em}
  .tkstage .mini:has(> div:nth-child(4)){grid-template-columns:repeat(2,minmax(0,1fr))}

  /* the caption belongs to the picture, so it sits on it rather than above it —
     the SVG is absolutely placed now and would otherwise push it to the top */
  .tkstage .scene figcaption{position:absolute;left:0;right:0;bottom:.1rem;z-index:2;
    padding:0 var(--gutter);font-size:.75rem;letter-spacing:0;line-height:1.3}

  /* the drag hint gets out of the way of the hook and stops shouting */
  .tkstage .scene__hint{
    left:.6rem;right:auto;top:auto;bottom:.5rem;border:0;background:none;
    -webkit-backdrop-filter:none;backdrop-filter:none;padding:0;
    color:var(--steel-faint);font-size:.75rem;letter-spacing:0}

  .tkstage .read{padding-top:.75rem;padding-bottom:.85rem}
  .tkstage .rdo__2{font-size:1rem}
  .deck{padding-top:.35rem}
  .deck .fld__hint{font-size:.78125rem;line-height:1.45}
  .cvtdeck{padding-top:.2rem}

  /* iOS large-title behaviour on the two document pages: the bar names the
     page only once its own title has scrolled away */
  .tkbar--doc strong{opacity:0;transform:translateY(7px);
    transition:opacity .22s var(--ease),transform .22s var(--ease)}
  .tkbar--doc.is-titled strong{opacity:1;transform:none}

  /* hand signals: the drawing is the whole point, so give it the room */
  .sigtrack .sigc{padding-top:0;justify-content:center}
  .sigtrack .sigc svg{max-width:min(92vw,400px);max-height:none;flex:1 1 auto;
    min-height:0;margin-bottom:.7rem}
  .sigtrack .sigc b{font-size:clamp(1.5rem,7.4vw,2.1rem)}
  .sigcount{padding:.3rem 0 0}
  .sigdots{padding-bottom:.4rem}
}
@media (prefers-reduced-motion:reduce){
  .tkbar--doc strong{transition:none}
}

/* ---------- round 3b: the tuning of the tuning ---------- */
@media (max-width:819.98px){
  .tkstage .mini b{min-height:1.3em}
  .tkstage .mini span{min-height:2.4em}
  /* two wide columns fit their labels on one line, so nothing is reserved */
  .tkstage .mini:has(> div:nth-child(4)) b,
  .tkstage .mini:has(> div:nth-child(4)) span{min-height:0}
  .tkstage .mini:has(> div:nth-child(4)){gap:.45rem .9rem}

  /* the hint goes back to the top, where the frame is empty */
  .tkstage .scene__hint{top:.4rem;bottom:auto;left:.7rem}

  /* a figure with a legend keeps the legend its own strip of the frame */
  .tkstage .scene:has(figcaption) > svg,
  .tkstage .scene:has(figcaption) > canvas{bottom:1.75rem;height:auto}
  .tkstage .scene figcaption{bottom:.25rem}
}

/* ---------- round 3c: nothing comes to rest behind the instrument ---------- */
@media (max-width:819.98px){
  body.tkapp{scroll-padding-top:calc(var(--navh) + var(--stage-h,52vh) + 10px)}
  .deck .fld,.deck .card,.deck .tkseg button,.deck .chip,.deck .inp,
  .deck select,.deck .rng,.cvtr,.deck [data-shape]{
    scroll-margin-top:calc(var(--navh) + var(--stage-h,52vh) + 10px);
    scroll-margin-bottom:calc(var(--abarh) + env(safe-area-inset-bottom) + 16px)}
  /* and the deck always has room to clear the fixed action bar at the end */
  body.tkapp .tk{padding-bottom:calc(var(--abarh) + env(safe-area-inset-bottom) + 20px)}
}

/* ==========================================================================
   ROUND 4 — the desktop column, and the last small things
   ========================================================================== */
:root{--col:calc(42rem + var(--gutter) * 2)}

@media (max-width:819.98px){
  /* a page with no action bar must not reserve room for one — this has to
     come after the rule that gives every other page that room */
  body.tkapp .tk--noabar{padding-bottom:clamp(28px,6vw,48px)}
  /* the placeholder is a hint, not a reading, so it never crowds the field */
  .deck .inp::placeholder{font-family:var(--body);font-size:1rem;font-weight:400}
}

@media (min-width:820px){
  /* everything lines up on one document column: the title, the instrument,
     the disclaimer, the controls and the reference matter */
  .tkbar,.tkstage,.deck,.abar,.cvtdeck,.tkinfo__scroll,.sigdeck{
    max-width:var(--col);margin-inline:auto;padding-inline:var(--gutter)}
  .tkbar{padding-top:calc(var(--header-h) + clamp(20px,4vw,40px));padding-bottom:0}
  .tkstage .cluster{max-width:none}
  .deck{padding-top:1.4rem;padding-bottom:0}
  .abar{padding-bottom:0;margin-bottom:1.6rem}
  .band-warn{max-width:var(--col);margin-inline:auto;padding-inline:var(--gutter)}
  .tkinfo__scroll{padding-bottom:clamp(40px,7vw,72px)}

  /* the scene is capped so the sticky instrument never swallows the screen:
     a 42rem-wide picture at its natural aspect is 474px tall on its own. */
  .tkstage .scene{height:clamp(200px,30vh,320px);border-bottom:1px solid var(--line-soft)}
  .tkstage .scene > svg,.tkstage .scene > canvas{position:absolute;inset:0;height:100%}
  .tkstage .scene__gl{aspect-ratio:auto}
  .tkstage .scene figcaption{position:absolute;left:0;right:0;bottom:.2rem;padding:0 1rem}
  .tkstage .scene:has(figcaption) > svg{bottom:1.6rem;height:auto}
}

/* ---------- round 4b ---------- */
@media (min-width:820px){
  /* the rule lines of the disclaimer match the text column, not the gutter */
  .band-warn{max-width:42rem;margin:1.1rem auto 0;padding-inline:0}
  /* a document page already carries its own big title; the bar just gets you
     back out of it */
  .tkbar--doc strong{display:none}
  .tkbar--doc{padding-bottom:.2rem}
  .tkinfo{padding-top:1.6rem}
}

/* ==========================================================================
   THE COST OF THE GLASS
   --------------------------------------------------------------------------
   backdrop-filter on the bar and the action bar is what makes them read as
   system chrome. It is also a full backdrop read-back every frame, and while
   a thumb is dragging the 3D scene the whole viewport is repainting: measured
   at 4x CPU throttle it took the drag from a 17 ms frame to a 117 ms one.

   So the blur is suspended for exactly as long as something is being dragged,
   and comes back the moment the thumb lifts. At rest — which is when anybody
   is actually looking at it — the glass is there.
   ========================================================================== */
:root.is-scrubbing .tkbar,:root.is-scrubbing .abar{
  -webkit-backdrop-filter:none;backdrop-filter:none;
  background:rgba(8,8,10,.97);
}

/* ---------- the bars go flat on a page with a live picture ----------
   Two backdrop-filter roots sitting over a canvas that repaints under a thumb
   cost about as much as the canvas does. On the pages that have a scene the
   bars use a solid wash instead; on every other page the glass stays, because
   there is nothing animating behind it to pay for. */
@media (max-width:819.98px){
  body.tkapp:has(.scene) .tkbar,body.tkapp:has(.scene) .abar{
    -webkit-backdrop-filter:none;backdrop-filter:none;background:rgba(8,8,10,.96)}
}

/* ---------- the lift sheet's three "pick a tool" tiles ----------
   They use the plain line symbols, not the launcher's illustrated icons, and
   the icon pass set stroke:none on every .launch svg — which left three empty
   glows on the empty-state page. These get their line back. */
.launch--line i svg{stroke:var(--paper-dim);stroke-width:1.7;fill:none;
  stroke-linecap:round;stroke-linejoin:round;width:34px;height:34px;
  filter:drop-shadow(0 2px 5px rgba(0,0,0,.6))}
.launch--line a:hover i svg,.launch--line a:active i svg{stroke:var(--amber)}

@media print{
  /* on paper a tool is a document again: the instrument, then everything the
     ⓘ sheet was holding, then the signals one after another down the page */
  .tkstage{position:static!important;background:none!important}
  .tkstage .scene{height:auto!important}
  .tkstage .scene > svg,.tkstage .scene > canvas{position:static!important;height:auto!important}
  .tkstage .scene::after{display:none!important}
  .tkinfo{position:static!important;display:block!important}
  .tkinfo__body{position:static!important;transform:none!important;display:block!important;
    background:none!important;box-shadow:none!important;border:0!important}
  .tkinfo__scroll{overflow:visible!important;padding:0!important;max-width:none!important}
  .sigtrack{display:block!important;overflow:visible!important}
  .sigtrack .sigc{width:auto!important;page-break-inside:avoid;break-inside:avoid;
    padding:.6rem 0!important}
  .sigtrack .sigc svg{max-width:150px!important;max-height:none!important}
  .deck .card,.cvtdeck{page-break-inside:auto}
}
