/* ============================================================
   keyquest.tech · KQ-01 — the device page (/)
   Base geometry from design/source/KQ-01 Wireframes.dc.html:
   shell 360×640 at 50%/46%, radius 18, chamfer inset 7px r12,
   screen 378px r11 in a 4px bezel r15, D-pad 160 (mobile 220).
   Desktop (min-width:701px) overrides to the 12a full-face body
   (520×678, 540px screen) with the 13a key-row deck — see the
   "12a FULL-FACE BODY" block. Mobile keeps the base values.

   SIZING SYSTEM — the device grows, the design does not change.
   --k (set on .kq-stage) is the one scale factor: 1 at the
   1536×791 reference window, growing with the viewport, capped
   at 1.75. Every length inside the shell is calc(<wireframe px>
   × var(--k)); every font-size is an em against .kq-body's
   font-size:calc(1rem × var(--k)), so raising the browser's
   default text size enlarges the on-device type too. The type
   scale is deliberately flat — 13/14/15 at k=1 — hierarchy is
   carried by weight, letter-spacing and the orange fill, not by
   size. Hairlines stay 1px at every k (locked rule). Mobile
   (max-width:700px) keeps --k:1: its full-bleed layout is
   untouched by the scale machinery.
   ============================================================ */

html,body{height:100%}
/* auto, not hidden: at 200% zoom / short landscape windows the device is
   taller than the viewport — the page must scroll to reach it (WCAG 1.4.10) */
body.kq-page{overflow:auto}

/* the scale factor, registered: an unsupported/invalid formula falls back
   to 1 (520×678 device) instead of unsetting every calc() that uses it,
   and JS can read the computed number (snake grid, scroll step) */
@property --k{
  syntax:"<number>";
  inherits:true;
  initial-value:1;
}

/* -- the stage: paper studio sweep, at least one viewport tall --- */
.kq-stage{
  --k:1;                       /* mobile and non-tan() browsers never scale */
  position:relative;           /* corner furniture and noscript pin to the stage box */
  min-height:100vh;            /* fallback for pre-dvh Safari/WebView */
  min-height:100dvh;
  display:grid;
  place-items:center;
  padding-block:24px;
  background-color:var(--paper);
  background-image:var(--paper-sweep);
}

/* ============================================================
   THE SHELL
   .kq-body positions · .kq-body-inner is the metal (tilt layer)
   .kq-drop-shadow carries the soft drop for tilt parallax (D8 §4)
   ============================================================ */
.kq-body{
  position:relative;              /* mobile: in-flow, full-bleed; desktop repositions it below */
  width:calc(360px * var(--k));
  height:calc(640px * var(--k));
  perspective:1000px;             /* D8 body layer */
  /* the type root: every on-device font-size is an em against this, so the
     whole face rides --k AND the visitor's browser text-size setting */
  font-size:calc(1rem * var(--k));
}

.kq-drop-shadow{
  position:absolute;
  inset:0;
  border-radius:calc(18px * var(--k));
  box-shadow:var(--shadow-device-drop);
  pointer-events:none;
}

.kq-body-inner{
  position:absolute;
  inset:0;
  background:var(--body-face);
  border-radius:calc(18px * var(--k));
  box-shadow:var(--shadow-device-step);
  padding:calc(14px * var(--k)) calc(16px * var(--k)) 0;
  transform-style:preserve-3d;
  will-change:transform;
}

.kq-chamfer{
  position:absolute;
  inset:calc(7px * var(--k));
  border:1px solid var(--hair-chamfer);
  border-radius:calc(12px * var(--k));
  pointer-events:none;
}

/* warm start (returning to an on device): no idle flash before JS renders */
.kq-warm .scr-idle{display:none}

/* the device shows focus through its selection fill and press states —
   the site-wide orange focus ring would double it */
#kq-screen :focus-visible,
.kq-controls :focus-visible{outline:none}

/* -- recessed screen bezel ------------------------------------- */
.kq-bezel{
  margin-top:calc(25px * var(--k));   /* absorbs the removed LED row so the face keeps its balance */
  background:var(--body-step);
  border:1px solid var(--hair-recess);
  border-radius:calc(15px * var(--k));
  padding:calc(4px * var(--k));
}
.kq-screen{
  height:calc(378px * var(--k));
  background-color:var(--screen);
  border-radius:calc(11px * var(--k));
  position:relative;
  overflow:hidden;
  font-variant-numeric:tabular-nums;
}

/* -- controls row: BACK · D-pad · INDEX ------------------------ */
.kq-controls{
  height:calc(200px * var(--k));
  display:grid;
  grid-template-columns:calc(76px * var(--k)) 1fr calc(76px * var(--k));   /* 76px is the max next to the 160px dial plate: 8px clearance each side */
  align-items:center;
  padding:0;   /* keys sit at the row edge — the shell's own 16px inset keeps them off the wall */
}
.kq-key{
  position:relative;
  width:calc(76px * var(--k));height:calc(38px * var(--k));
  background:var(--body-step);
  border:1px solid var(--hair);
  border-radius:calc(7px * var(--k));
  display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:calc(3px * var(--k));
  font-size:0.8125em;font-weight:500;letter-spacing:0.12em;color:var(--grey-1);
  text-decoration:none;   /* BACK (button) and INDEX (link) read identically */
  cursor:pointer;
}
.kq-key .kq-mark{line-height:1}
.kq-key:hover{text-decoration:none;color:var(--grey-1)}
.kq-key--back{justify-self:start}
.kq-key--index{justify-self:end}

/* -- hardware button states: shade on hover, press on click ---- */
.kq-key::after,.kq-centre::after{
  content:"";position:absolute;inset:0;border-radius:inherit;
  background:transparent;pointer-events:none;
}
/* hover shades only where hover exists — on touch, :hover sticks after
   the tap and buttons would look permanently pressed */
@media (hover:hover){
  .kq-key:hover::after{background:rgba(var(--ink-rgb),0.07)}
  .kq-centre:hover::after{background:rgba(var(--ink-rgb),0.08)}
}
.kq-key:active::after{background:rgba(var(--ink-rgb),0.14)}
.kq-key:active{transform:translateY(1px)}
.kq-centre{cursor:pointer;transition:transform .08s ease}
.kq-centre:active::after{background:rgba(var(--ink-rgb),0.16)}
.kq-centre:active{transform:scale(0.94)}

/* navigation cluster: recessed plate + 4 keys + OK centre */
.kq-dial{
  position:relative;
  width:calc(160px * var(--k));height:calc(160px * var(--k));
  margin:0 auto;
  perspective:620px;              /* D8 dial layer */
}
.kq-dial-inner{
  position:absolute;inset:0;
  transform-style:preserve-3d;
  will-change:transform;
}
.kq-dial-plate{
  position:absolute;inset:0;
  background:var(--body-step);
  border:1px solid var(--hair-recess);
  border-radius:calc(30px * var(--k));
}
/* engraved marks are exempt from tilt: counter-rotated by tilt.js */
.kq-mark{display:inline-block;will-change:transform}
/* SVG arrows: block display kills the inline baseline gap */
.kq-nav svg,.scr-pager .pg-arrow svg{display:block;margin:0 auto}
/* pager arrows ride the scale (the markup's 8px attributes are the k=1 size) */
.scr-pager .pg-arrow svg{width:calc(8px * var(--k));height:calc(8px * var(--k))}
.kq-centre{
  position:absolute;left:calc(58px * var(--k));top:calc(58px * var(--k));
  width:calc(44px * var(--k));height:calc(44px * var(--k));
  border-radius:50%;
  background:var(--accent);
  border:1px solid var(--hair);
  display:flex;align-items:center;justify-content:center;
}
/* engraved OK — ink on the accent (4.7:1); tilt counter-rotates it like every mark */
.kq-centre .kq-mark{font-size:0.8125em;font-weight:500;letter-spacing:0.12em;color:var(--ink)}
.kq-dial--mobile{display:none}

/* -- navigation-key variant (replaces the cross) --------------- */
.kq-nav{
  position:absolute;
  background:var(--body-face);
  border:1px solid var(--hair);
  border-radius:calc(7px * var(--k));
  display:flex;align-items:center;justify-content:center;
  font-size:0.8125em;color:var(--grey-1);
  cursor:pointer;
}
.kq-nav::after{
  content:"";position:absolute;inset:0;border-radius:inherit;
  background:transparent;pointer-events:none;
}
/* engraved collar ring around every button (as on the original centre).
   pointer-events stays on: the ring is part of the button's hit area,
   so clicks on it are never dead. */
.kq-nav::before{
  content:"";position:absolute;inset:calc(-4px * var(--k));
  border:1px solid var(--hair);border-radius:calc(11px * var(--k));
}
.kq-centre::before{
  content:"";position:absolute;inset:calc(-6px * var(--k));
  border:1px solid var(--hair);border-radius:50%;
}
@media (hover:hover){
  .kq-nav:hover::after{background:rgba(var(--ink-rgb),0.07)}
}
.kq-nav:active::after{background:rgba(var(--ink-rgb),0.14)}
.kq-nav:active{transform:translateY(1px)}
.kq-nav--up{left:calc(58px * var(--k));top:calc(14px * var(--k));width:calc(44px * var(--k));height:calc(34px * var(--k))}
.kq-nav--down{left:calc(58px * var(--k));top:calc(112px * var(--k));width:calc(44px * var(--k));height:calc(34px * var(--k))}
.kq-nav--left{left:calc(14px * var(--k));top:calc(58px * var(--k));width:calc(34px * var(--k));height:calc(44px * var(--k))}
.kq-nav--right{left:calc(112px * var(--k));top:calc(58px * var(--k));width:calc(34px * var(--k));height:calc(44px * var(--k))}

/* ============================================================
   ON-SCREEN UI (shared bits)
   Type: em against .kq-body — 0.8125em/0.875em/0.9375em render
   13/14/15px at k=1 with a 16px browser default.
   ============================================================ */
.scr{position:absolute;inset:0;display:flex;flex-direction:column;padding:calc(16px * var(--k))}
.scr--flush{padding:0}

.scr-status{
  font-size:0.8125em;font-weight:500;letter-spacing:0.12em;
  color:rgba(var(--screen-text-rgb),0.65);
  padding-bottom:calc(10px * var(--k));
  border-bottom:1px solid rgba(var(--screen-text-rgb),0.14);
  flex:none;
}

/* D1 idle */
.scr-idle{align-items:center;justify-content:center;gap:calc(10px * var(--k));text-align:center;text-wrap:balance}
.scr-idle-caption{
  font-size:0.8125em;font-weight:500;letter-spacing:0.22em;
  color:rgba(var(--screen-text-rgb),0.5);
}
.scr-idle-note{
  font-size:0.8125em;font-weight:400;letter-spacing:0.12em;
  color:rgba(var(--screen-text-rgb),0.5);
}
/* D2 boot */
.scr-boot{align-items:center;justify-content:center;gap:calc(20px * var(--k))}
/* the bar's widths are JS-driven px (0→180): one transform scales the
   whole readout — dash pattern included — instead of rescaling the JS */
.scr-boot-bar{display:flex;transform:scale(var(--k));transform-origin:center}
.scr-boot-on{
  height:9px;
  background:repeating-linear-gradient(90deg, var(--screen-hi) 0, var(--screen-hi) 3px, transparent 3px, transparent 9px);
}
.scr-boot-off{
  height:9px;
  background:repeating-linear-gradient(90deg, rgba(var(--screen-text-rgb),0.22) 0, rgba(var(--screen-text-rgb),0.22) 3px, transparent 3px, transparent 9px);
}
.scr-boot-line{
  font-size:0.8125em;font-weight:500;letter-spacing:0.18em;
  color:rgba(var(--screen-text-rgb),0.4);
}

/* D3 home channels */
.scr-list{margin-top:calc(12px * var(--k))}
.scr-ch{
  width:100%;
  display:flex;justify-content:space-between;align-items:center;
  padding:calc(12px * var(--k)) calc(10px * var(--k));
  border-bottom:1px solid rgba(var(--screen-text-rgb),0.08);
  text-align:left;
}
.scr-ch:last-child{border-bottom:0}
.scr-ch .ch-name{
  font-size:0.8125em;font-weight:400;letter-spacing:0.06em;
  color:var(--screen-text);
}
.scr-ch .ch-sub{
  font-size:0.8125em;font-weight:400;letter-spacing:0.1em;
  color:rgba(var(--screen-text-rgb),0.60);   /* 5.9:1 composited on the screen — 0.45 measured only 3.9:1 */
}
.scr-ch.is-sel{background:var(--screen-hi);border-bottom-color:transparent}
.scr-ch.is-sel .ch-name,
.scr-ch.is-sel .ch-sub{color:var(--screen);font-weight:500}

/* D4 work list */
.scr-hint{
  font-size:0.8125em;color:rgba(var(--screen-text-rgb),0.6);
  margin-top:calc(10px * var(--k));flex:none;
}
.scr-hint--home{margin-top:auto;text-align:center;line-height:1.7}
.scr-work{margin-top:calc(8px * var(--k))}
.scr-row{
  width:100%;
  display:grid;grid-template-columns:calc(26px * var(--k)) 1fr auto;align-items:center;
  padding:calc(8.5px * var(--k)) calc(10px * var(--k));   /* text starts/ends where the home rows' text does */
  border-bottom:1px solid rgba(var(--screen-text-rgb),0.09);
  text-align:left;
}
.scr-row:last-child{border-bottom:0}
.scr-row .row-num{font-size:0.8125em;font-weight:500;color:var(--screen-hi)}
.scr-row .row-name{font-size:0.8125em;font-weight:400;color:var(--screen-text)}
.scr-row .row-year{font-size:0.8125em;color:rgba(var(--screen-text-rgb),0.45)}
.scr-row.is-sel{background:var(--screen-hi);border-bottom-color:transparent}
.scr-row.is-sel .row-num,
.scr-row.is-sel .row-name,
.scr-row.is-sel .row-year{color:var(--screen);font-weight:500}

.scr-scrollbar{
  position:absolute;right:calc(6px * var(--k));top:calc(92px * var(--k));
  height:calc(180px * var(--k));width:2px;
  background:rgba(var(--screen-text-rgb),0.1);
}
.scr-scrollbar > div{
  position:absolute;left:0;width:2px;
  background:rgba(var(--screen-text-rgb),0.4);
}

/* D5 preview (full-bleed) */
.scr-crumb{
  font-size:0.8125em;font-weight:500;letter-spacing:0.12em;
  color:rgba(var(--screen-text-rgb),0.65);
  padding:calc(12px * var(--k)) calc(14px * var(--k)) calc(10px * var(--k));
  border-bottom:1px solid rgba(var(--screen-text-rgb),0.12);
  flex:none;
}
.scr-photo{
  flex:1;position:relative;overflow:hidden;
  background-color:var(--body-step);
  min-height:0;
  cursor:pointer;
}
.scr-photo img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;
}
/* the photo is a button — hover/press shade like the hardware keys */
.scr-photo::after{
  content:"";position:absolute;inset:0;
  background:transparent;pointer-events:none;
}
@media (hover:hover){
  .scr-photo:hover::after{background:rgba(var(--ink-rgb),0.07)}
}
.scr-photo:active::after{background:rgba(var(--ink-rgb),0.14)}
.scr-caption{
  padding:calc(10px * var(--k)) calc(14px * var(--k)) calc(8px * var(--k));
  font-size:0.8125em;
  color:rgba(var(--screen-text-rgb),0.75);flex:none;
}
.scr-caption b{font-weight:700;color:var(--screen-text)}
.scr-chips{display:flex;flex-wrap:wrap;gap:calc(6px * var(--k));padding:0 calc(14px * var(--k)) calc(10px * var(--k));flex:none}
.scr-chip{
  border:1px solid rgba(var(--screen-text-rgb),0.28);
  border-radius:calc(3px * var(--k));padding:calc(3px * var(--k)) calc(7px * var(--k));
  white-space:nowrap;flex:none;   /* a chip never squashes or wraps inside */
  font-size:0.8125em;font-weight:500;letter-spacing:0.1em;
  color:rgba(var(--screen-text-rgb),0.8);
}
.scr-open{
  padding:0 calc(14px * var(--k)) calc(8px * var(--k));font-size:0.8125em;
  color:rgba(var(--screen-text-rgb),0.55);flex:none;
}
.scr-pager{
  /* centre, not baseline: the arrow buttons hold only an SVG (no text
     baseline), so baseline alignment floats them above the count */
  display:flex;justify-content:center;align-items:center;gap:calc(12px * var(--k));
  padding:0 calc(14px * var(--k)) calc(12px * var(--k));font-size:0.8125em;flex:none;
}
.scr-pager .pg-arrow{
  position:relative;   /* anchors the invisible hit pad below */
  color:rgba(var(--screen-text-rgb),0.65);background:none;border:0;
  font-size:calc(14em / 13);   /* 14 against the pager's 13 — the locked 14px step */
  padding:calc(6px * var(--k)) calc(14px * var(--k));
  border-radius:calc(4px * var(--k));cursor:pointer;
}
/* invisible hit pad — the drawn arrow is 36×20 at k=1; pad to ≥44×44.
   The pager's 12k bottom padding absorbs the 12px downward reach, so
   the pad stays inside the screen. Mobile's 44px arrows: no-op. */
.scr-pager .pg-arrow::after{
  content:"";position:absolute;
  left:50%;top:50%;
  width:max(100%, 44px);height:max(100%, 44px);
  transform:translate(-50%,-50%);
}
@media (hover:hover){
  .scr-pager .pg-arrow:hover{color:rgba(var(--screen-text-rgb),0.95);background:rgba(var(--screen-text-rgb),0.08)}
}
.scr-pager .pg-count{color:rgba(var(--screen-text-rgb),0.85)}

/* About / CV / Contact / Experiments (text channels) */
.scr-bio{
  margin-top:calc(12px * var(--k));overflow-y:auto;min-height:0;
  padding-right:calc(8px * var(--k));
  scrollbar-width:thin;
  scrollbar-color:rgba(var(--screen-text-rgb),0.3) rgba(var(--screen-text-rgb),0.08);
  /* scroll the text by hand on touch screens */
  touch-action:pan-y;
  -webkit-overflow-scrolling:touch;
  overscroll-behavior:contain;
}
.scr-bio p{
  font-size:0.8125em;line-height:1.6;
  color:rgba(var(--screen-text-rgb),0.75);
  margin:0 0 calc(12px * var(--k));
}

.scr-link{
  width:100%;
  display:flex;justify-content:space-between;align-items:center;
  padding:calc(12px * var(--k)) calc(10px * var(--k));
  border-bottom:1px solid rgba(var(--screen-text-rgb),0.08);
  text-align:left;text-decoration:none;
}
.scr-link:hover{text-decoration:none}
.scr-link .lk-label{
  font-size:0.8125em;font-weight:500;letter-spacing:0.12em;
  color:var(--screen-hi);
}
.scr-link .lk-value{font-size:0.8125em;color:rgba(var(--screen-text-rgb),0.75)}
.scr-link.is-sel{background:var(--screen-hi)}
.scr-link.is-sel .lk-label,
.scr-link.is-sel .lk-value{color:var(--screen);font-weight:500}

.scr-note{
  margin-top:calc(12px * var(--k));font-size:0.8125em;letter-spacing:0.1em;
  color:rgba(var(--screen-text-rgb),0.45);
}

/* contact: summary + rows in one scrollable pane (small screens) */
.scr-scroll{
  flex:1;min-height:0;overflow-y:auto;
  touch-action:pan-y;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  scrollbar-width:thin;
  scrollbar-color:rgba(var(--screen-text-rgb),0.3) rgba(var(--screen-text-rgb),0.08);
}
.scr-bio--brief{flex:none;overflow:visible;margin-top:calc(12px * var(--k));padding-right:0}
/* RECOGNITION block at the end of About */
.scr-recog{
  margin-top:calc(14px * var(--k));padding-top:calc(10px * var(--k));
  border-top:1px solid rgba(var(--screen-text-rgb),0.12);
}
.scr-recog-head{
  font-size:0.8125em;font-weight:500;letter-spacing:0.12em;
  color:rgba(var(--screen-text-rgb),0.65);
  margin-bottom:calc(6px * var(--k));
}
.scr-recog-row{
  font-size:0.8125em;line-height:1.6;
  color:rgba(var(--screen-text-rgb),0.85);
}

/* D9 snake */
.scr-field{
  flex:1;margin-top:calc(12px * var(--k));min-height:0;
  border:1px solid rgba(var(--screen-text-rgb),0.14);
  position:relative;overflow:hidden;
}
.scr-field canvas{position:absolute;left:0;top:0}
.scr-dead{
  position:absolute;inset:0;background:var(--screen);
  display:flex;align-items:center;justify-content:center;
}
.scr-dead-inner{width:calc(204px * var(--k))}
.scr-dead-title{
  font-size:0.9375em;font-weight:700;letter-spacing:0.2em;
  color:var(--screen-text);text-align:center;
}
.scr-dead-score{
  margin-top:calc(6px * var(--k));font-size:0.8125em;font-weight:500;letter-spacing:0.14em;
  color:rgba(var(--screen-text-rgb),0.6);text-align:center;
}
.scr-dead-actions{margin-top:calc(14px * var(--k));display:flex;flex-direction:column;gap:calc(8px * var(--k))}
/* both actions share the quiet face; selection carries the orange fill,
   moved by arrows and hover exactly like the home rows */
.scr-dead-actions button{
  position:relative;   /* anchors the invisible hit pad below */
  background:none;
  border:1px solid rgba(var(--screen-text-rgb),0.28);
  color:rgba(var(--screen-text-rgb),0.8);
  font-size:0.8125em;font-weight:500;letter-spacing:0.12em;
  text-align:center;padding:calc(9px * var(--k)) 0;width:100%;
  cursor:pointer;
}
/* invisible hit pad — the drawn action is ~41px tall at k=1; pad to
   44px. The 8k gap between the two actions keeps the pads ~5px apart. */
.scr-dead-actions button::before{
  content:"";position:absolute;
  left:0;right:0;top:50%;
  height:max(100%, 44px);
  transform:translateY(-50%);
}
.scr-dead-actions button.is-sel{
  background:var(--screen-hi);border-color:transparent;
  color:var(--screen);font-weight:700;
}
.scr-dead-note{
  margin-top:calc(10px * var(--k));font-size:0.8125em;font-weight:500;letter-spacing:0.1em;
  color:rgba(var(--screen-text-rgb),0.45);text-align:center;
}

/* ============================================================
   CORNER FURNITURE (paper, D1–D5/D9; desktop only)
   Paper-side type follows the same 13px floor, in rem: it rides
   the browser text-size setting but not --k (it is not the device).
   ============================================================ */
.kq-changelog{position:absolute;left:26px;bottom:22px}
.kq-fur-head{
  font-size:0.8125rem;font-weight:700;letter-spacing:0.14em;
  color:var(--grey-2);margin-bottom:6px;
}
.kq-changelog-list{
  font-size:0.8125rem;letter-spacing:0.1em;color:var(--grey-2);line-height:1.9;
}
.kq-legend{
  position:absolute;right:26px;top:50%;
  transform:translateY(-50%);text-align:right;
}
.kq-legend .kq-fur-head{margin-bottom:8px}
.kq-legend-rows{
  font-size:0.8125rem;letter-spacing:0.12em;color:var(--grey-2);line-height:2;
}
.kq-copyright{
  position:absolute;left:30%;right:30%;bottom:22px;text-align:center;
  font-size:0.8125rem;letter-spacing:0.14em;color:var(--grey-2);
}
@media (max-width:980px){
  .kq-changelog,.kq-legend{display:none}
}

/* -- the projector: pages open in an overlay frame, the URL never
      changes and the device stays alive underneath ---------------- */
/* while the projector is up the page behind must not scroll: no second
   scrollbar beside the overlay, no shifting the stage underneath.
   (:has fallback = old behavior: overlay + inert extra scrollbar) */
body.kq-page:has(.kq-projector){overflow:hidden}
.kq-projector{
  position:fixed;inset:0;z-index:20;
  opacity:0;transition:opacity .18s ease;
  overflow:auto;                       /* iOS expands iframes to content height — wrapper scrolls */
  -webkit-overflow-scrolling:touch;
  overscroll-behavior:contain;         /* the page behind can scroll now — don't chain past the overlay */
  background:var(--card);
}
.kq-projector.is-open{opacity:1}
.kq-projector iframe{
  width:100%;height:100%;border:0;display:block;
  background:var(--card);
}

/* -- no-JS escape hatch --------------------------------------- */
.kq-noscript{
  position:absolute;
  left:50%;top:22px;transform:translateX(-50%);
  z-index:9;
  background:var(--card);
  border:1px solid var(--hair);
  padding:10px 16px;
  font-size:0.8125rem;font-weight:500;letter-spacing:0.12em;color:var(--grey-1);
  white-space:nowrap;
}

/* ============================================================
   12a FULL-FACE BODY + 13a KEY-ROW DECK (desktop only)
   Mobile branch untouched: everything here is scoped to
   min-width:701px.
   ============================================================ */
@media (min-width:701px){
  /* -- the fluid scale ------------------------------------------
     k = min(88% of the free height ÷ 678, viewport width ÷ 1150),
     floored at 1, capped at 1.75. 0.88 keeps slack around the
     shell — 46% only reads as optical centring with air around
     the object. On a 1536×791 window k is exactly 1: same device,
     same placement, nothing changes. tan(atan2(a,b)) is how CSS
     divides two lengths into the plain number a÷b; browsers
     without it keep the registered fallback --k:1. */
  @supports (width: calc(1px * tan(atan2(1px, 1px)))){
    .kq-stage{
      --k:clamp(1,
            min(tan(atan2(calc((100dvh - 48px) * 0.88), 678px)),
                tan(atan2(100vw, 1150px))),
            1.75);
    }
  }
  .kq-stage{
    --dev-h:calc(678px * var(--k));
    /* the stage grows with the device: short or zoomed windows scroll
       to reach it, nothing is ever clipped or unreachable */
    min-height:max(100vh, calc(var(--dev-h) + 48px));
    min-height:max(100dvh, calc(var(--dev-h) + 48px));
  }

  /* the wireframes' stance: device CENTRE at 46% of the stage — a
     deliberate optical centre, above true centre — wherever there is
     room. When there isn't, max() pins the top edge to a 24px pad and
     the page scrolls. translate carries the horizontal centring only:
     top positions the edge directly, so no translateY to double-apply. */
  .kq-body{
    position:absolute;
    left:50%;
    translate:-50% 0;
    top:max(24px, calc(46% - var(--dev-h) / 2));
    width:calc(520px * var(--k));
    height:var(--dev-h);
  }

  .kq-body-inner{padding:calc(16px * var(--k))}

  /* full-face: no LED-row gap. The bezel is the device's one scroll
     container: a screen taller than it (ABOUT, or a raised browser
     text size) scrolls under the lip instead of clipping. Thin ink
     thumb, no browser default chrome. */
  .kq-bezel{
    margin-top:0;
    height:calc(548px * var(--k) + 2px);   /* 4k pad + 540k screen + 4k pad + 2×1px border */
    overflow-y:auto;
    scrollbar-width:thin;
    scrollbar-color:rgba(var(--ink-rgb),0.55) transparent;
    touch-action:pan-y;
    -webkit-overflow-scrolling:touch;
    overscroll-behavior:contain;
  }
  .kq-bezel::-webkit-scrollbar{width:6px}
  .kq-bezel::-webkit-scrollbar-track{background:transparent}
  .kq-bezel::-webkit-scrollbar-thumb{background:rgba(var(--ink-rgb),0.55);border-radius:3px}
  .kq-screen{height:auto}
  /* screens flow (not absolute) so a long one can outgrow the bezel;
     min-height keeps short ones filling the full 540k face */
  .scr{position:static;min-height:calc(540px * var(--k))}

  /* 9px top padding: the visual floor is the chamfer line (7px inset), the
     row's floor is the shell padding (16px) — this centres the deck between
     the bezel bottom and the chamfer, not the padding edge */
  .kq-controls{
    height:calc(96px * var(--k));
    grid-template-columns:calc(92px * var(--k)) 1fr calc(92px * var(--k));
    padding:calc(9px * var(--k)) calc(4px * var(--k)) 0;
  }

  /* BACK / INDEX — 13a keys */
  .kq-key{width:calc(84px * var(--k));height:calc(40px * var(--k));border-radius:calc(9px * var(--k));letter-spacing:0.1em}
  /* invisible hit pad — the key draws 40k tall, under the 44px touch
     minimum (iPads browse this branch). Extends the hit area only, never
     the artwork. Desktop-scoped: mobile's keys are 44px and static, and
     an absolute pad there would resolve against the whole body. */
  .kq-key::before{
    content:"";position:absolute;
    left:0;right:0;top:50%;
    height:max(100%, 44px);
    transform:translateY(-50%);
  }

  /* 13a — arrow keys + OK in one recessed pill plate */
  .kq-dial--desktop{width:fit-content;height:auto;margin:0 auto}
  .kq-dial--desktop .kq-dial-inner{
    position:relative;inset:auto;
    display:flex;align-items:center;
    gap:calc(10px * var(--k));padding:calc(10px * var(--k)) calc(18px * var(--k));
  }
  .kq-dial--desktop .kq-dial-plate{border-radius:calc(30px * var(--k))}
  /* relative, not static: the plate is position:absolute, and positioned
     boxes paint above static siblings — static keys would hide their
     faces under the plate (only the promoted glyph spans showed) */
  .kq-dial--desktop .kq-nav{position:relative;left:auto;top:auto;width:calc(36px * var(--k));height:calc(36px * var(--k));border-radius:calc(10px * var(--k))}
  .kq-dial--desktop .kq-nav svg{width:calc(12px * var(--k));height:calc(12px * var(--k))}
  /* no collar rings on the key row — the ::before is repurposed as an
     invisible hit pad: each 36k key answers to ≥44×44 without growing
     the artwork. At k=1 neighbouring pads keep 2px air (1px to the OK
     collar); the 10k gaps only widen from there. */
  .kq-dial--desktop .kq-nav::before{
    border:0;border-radius:0;
    inset:50% auto auto 50%;
    width:max(100%, 44px);height:max(100%, 44px);
    transform:translate(-50%,-50%);
  }
  .kq-dial--desktop .kq-centre{position:relative;left:auto;top:auto;width:calc(52px * var(--k));height:calc(52px * var(--k))}
  .kq-dial--desktop .kq-centre::before{inset:calc(-5px * var(--k))}      /* collar stays on OK only */

  /* 13d — preview footer: pager arrows quieter than the counter */
  .scr-pager .pg-arrow{color:rgba(var(--screen-text-rgb),0.5)}
}

/* ============================================================
   FIT & MOBILE (M1 — the phone IS the device)
   ============================================================ */
@media (max-width:700px){
  .kq-stage{padding-block:0}   /* the phone IS the device — full bleed, no paper bands */
  .kq-body{
    width:100%;
    height:100vh;              /* fallback for pre-dvh Safari/WebView */
    height:100dvh;
    transform:none;perspective:none;
  }
  .kq-drop-shadow{display:none}
  .kq-body-inner{
    border-radius:0;box-shadow:none;
    display:flex;flex-direction:column;
    /* no tilt on touch — a 3D rendering context here breaks native
       scrolling of the on-screen text in some mobile browsers */
    transform-style:flat;will-change:auto;
  }
  .kq-dial-inner{transform-style:flat;will-change:auto}
  .kq-mark{will-change:auto}
  .kq-chamfer{border-radius:14px;z-index:5}

  .kq-bezel{border-radius:17px;flex:none}
  .kq-screen{height:52vh;height:52dvh;border-radius:13px}   /* vh fallback for pre-dvh Safari/WebView */

  .scr-status{font-size:10px}
  /* idle: each line holds one line down to 360px. the note is the wider
     string, so its tracking sets the floor — 0.10em = 281px of 286px */
  .scr-idle-caption{letter-spacing:0.14em}
  .scr-idle-note{letter-spacing:0.10em}
  .scr-list{margin-top:8px}
  .scr-ch{min-height:44px;padding:0 12px}
  .scr-ch .ch-name{font-size:14px}
  .scr-ch .ch-sub{font-size:9.5px}
  .scr-row{min-height:44px;padding:0 12px}   /* highlight inset matches the home rows */
  .scr-scrollbar{top:96px;height:264px}      /* track spans the 6 × 44px rows */
  .scr-row .row-name{font-size:14px}
  .scr-link{min-height:44px}
  /* preview: pager arrows are primary controls on touch — 44px targets */
  .scr-pager{padding:0 14px 6px;align-items:center}
  .scr-pager .pg-arrow{min-width:44px;min-height:44px;font-size:13px}
  .scr-open{padding:8px 14px}
  .scr-bio p{font-size:12px}

  /* controls: dial row above a pill row (BACK left · INDEX right) — no overlap,
     pills inset from the device edge */
  .kq-controls{
    flex:1;height:auto;padding:6px 10px 22px;
    display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr auto;
    row-gap:10px;
  }
  .kq-dial-slot{
    grid-column:1/3;grid-row:1;min-height:0;
    display:flex;align-items:center;justify-content:center;
  }
  .kq-key--back,.kq-key--index{
    grid-row:2;position:static;display:flex;flex-direction:column;gap:3px;
    width:auto;height:44px;padding:0 20px;border-radius:12px;
    /* type mirrors desktop — sizes and colors come from the base .kq-key rules */
  }
  .kq-key--back{grid-column:1;justify-self:start}
  .kq-key--index{grid-column:2;justify-self:end}
  .kq-dial--desktop{display:none}
  .kq-dial--mobile{
    display:block;position:relative;left:auto;top:auto;transform:none;
    width:220px;height:220px;margin:0;perspective:none;flex:none;
  }
  .kq-dial--mobile .kq-dial-plate{border-radius:40px}
  .kq-dial--mobile .kq-centre{left:80px;top:80px;width:60px;height:60px}
  .kq-dial--mobile .kq-centre .kq-mark{font-size:10px;letter-spacing:0.14em}
  .kq-dial--mobile .kq-nav{font-size:9px;border-radius:9px}
  .kq-dial--mobile .kq-nav::before{inset:-5px;border-radius:14px}
  .kq-dial--mobile .kq-nav--up{left:80px;top:18px;width:60px;height:48px}
  .kq-dial--mobile .kq-nav--down{left:80px;top:154px;width:60px;height:48px}
  .kq-dial--mobile .kq-nav--left{left:18px;top:80px;width:48px;height:60px}
  .kq-dial--mobile .kq-nav--right{left:154px;top:80px;width:48px;height:60px}

  /* short phones: keep the dial clear of the screen and pills */
  @media (max-height:730px){
    .kq-dial--mobile{transform:scale(.82)}
  }

  .kq-changelog,.kq-legend,.kq-copyright{display:none}
  .kq-noscript{white-space:normal;width:calc(100% - 48px);text-align:center}
}
