/* ==========================================================================
   THE LONG WAY HOME / interface
   The type and the palette are the TANI & CO tokens. Graphite ink, plaster
   paper, verdigris as the single live accent, mono for anything that labels,
   Archivo for anything that speaks, Newsreader for the one intimate line.
   ========================================================================== */

:root{
  --graphite:#15181A;
  --plaster:#E5E3DB;
  --board:#C6B291;
  --board-lt:#DCCCAE;
  --verdigris:#0F6B62;
  --verdigris-lt:#2A8C82;
  --moke:#EFC01F;

  --display:"Archivo","Helvetica Neue",Arial,sans-serif;
  --body:"Newsreader",Georgia,"Times New Roman",serif;
  --mono:"IBM Plex Mono",ui-monospace,Menlo,monospace;

  --scrim:rgba(21,24,26,.42);
  --edge:rgba(229,227,219,.22);
  --gut:clamp(16px,3.4vw,34px);
  --safe-t:env(safe-area-inset-top,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
}

*,*::before,*::after{box-sizing:border-box}
html,body{height:100%;margin:0;overflow:hidden;background:#B6C6D2}
body{
  font-family:var(--display);color:var(--plaster);
  -webkit-font-smoothing:antialiased;overscroll-behavior:none;
  touch-action:none;-webkit-tap-highlight-color:transparent;
}
canvas#scene{position:fixed;inset:0;width:100%;height:100%;display:block;touch-action:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--moke);outline-offset:3px}
[hidden]{display:none !important}

.mono{
  font-family:var(--mono);font-size:10.5px;font-weight:500;
  letter-spacing:.17em;text-transform:uppercase;
}

/* ---------- paper and light ---------- */
.grain{
  position:fixed;inset:0;pointer-events:none;z-index:2;opacity:.14;
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}
.vignette{
  position:fixed;inset:0;pointer-events:none;z-index:2;
  background:
    radial-gradient(128% 108% at 50% 44%,transparent 52%,rgba(60,52,34,.20) 100%),
    linear-gradient(to bottom,rgba(21,24,26,.14),transparent 22%,transparent 78%,rgba(52,44,28,.16));
}
@media (prefers-reduced-motion:reduce){.grain{opacity:.08}}

/* ---------- loading and title ---------- */
.load{
  position:fixed;inset:0;z-index:40;display:flex;align-items:center;justify-content:center;
  padding:var(--gut);text-align:center;
  background:
    radial-gradient(120% 90% at 24% 14%,rgba(198,178,145,.26),transparent 58%),
    radial-gradient(90% 70% at 82% 88%,rgba(15,107,98,.22),transparent 62%),
    #15181A;
  transition:opacity .9s ease,visibility .9s;
}
.load.is-gone{opacity:0;visibility:hidden}
.load__inner{max-width:min(560px,100%)}
.load__eyebrow{color:var(--board);margin:0 0 26px}
.load__title{
  font-size:clamp(40px,9vw,84px);font-weight:600;line-height:.96;letter-spacing:-.035em;margin:0;
}
.load__sub{
  font-family:var(--body);font-style:italic;font-size:clamp(16px,2.2vw,19px);
  color:rgba(229,227,219,.72);margin:18px 0 40px;
}
.load__bar{height:1px;background:rgba(229,227,219,.18);position:relative;overflow:hidden}
.load__bar span{
  position:absolute;inset:0 100% 0 0;background:var(--board);
  transition:right .4s cubic-bezier(.2,.8,.2,1);
}
.load__stat{color:rgba(229,227,219,.5);margin:16px 0 0;min-height:1.4em}
.load__note{color:rgba(229,227,219,.34);margin:30px 0 0}
.load__begin{margin-top:30px}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.16em;text-transform:uppercase;
  padding:15px 26px;background:var(--plaster);color:var(--graphite);
  border:1px solid var(--plaster);transition:background .3s,color .3s,border-color .3s;
}
.btn:hover{background:var(--verdigris-lt);border-color:var(--verdigris-lt);color:var(--graphite)}
.btn--ghost{background:transparent;color:var(--plaster);border-color:var(--edge)}
.btn--ghost:hover{background:var(--plaster);color:var(--graphite);border-color:var(--plaster)}

/* ---------- top bar ---------- */
.topbar{
  position:fixed;z-index:12;top:0;left:0;right:0;
  padding:calc(var(--safe-t) + 14px) var(--gut) 14px;
  display:flex;align-items:center;gap:16px;
  opacity:0;transition:opacity .8s ease;pointer-events:none;
  background:linear-gradient(to bottom,rgba(21,24,26,.34),transparent);
}
.topbar.is-on{opacity:1;pointer-events:auto}
.topbar__mark{
  font-family:var(--display);font-weight:600;font-size:13px;
  letter-spacing:.12em;text-transform:uppercase;
  text-shadow:0 1px 12px rgba(21,24,26,.55);
}
.topbar__tools{margin-left:auto;display:flex;align-items:center;gap:4px}

/* what time it is and what kind of afternoon, always there */
.status{
  display:flex;align-items:center;gap:10px;margin-left:20px;
  font-family:var(--mono);font-size:11px;font-weight:500;
  text-transform:uppercase;letter-spacing:.15em;
  color:rgba(229,227,219,.72);
}
.status__clock{color:var(--plaster);font-variant-numeric:tabular-nums}
.status__sep{width:14px;height:1px;background:rgba(229,227,219,.30)}
.status__weather{color:var(--board-lt)}
@media (max-width:620px){
  .status{gap:7px;margin-left:12px;font-size:9px;letter-spacing:.1em}
  .status__weather{display:none}
}

/* how far through a stop you are */
.action__prog{
  width:132px;height:2px;margin-top:9px;border-radius:2px;
  background:rgba(229,227,219,.22);overflow:hidden;
}
.action__prog span{
  display:block;height:100%;width:0%;background:var(--moke);
  transition:width .12s linear;
}
.tool{
  font-family:var(--mono);font-size:10px;font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  padding:8px 12px;color:rgba(229,227,219,.82);border:1px solid transparent;
  text-shadow:0 1px 10px rgba(21,24,26,.6);transition:border-color .3s,color .3s;
}
.tool:hover{color:#fff;border-color:var(--edge)}
.tool--accent{color:var(--moke)}
@media (max-width:560px){
  .tool{padding:8px 9px;font-size:9px;letter-spacing:.1em}
  .topbar__mark{font-size:11px}
}

/* ---------- the task ---------- */
.task{
  position:fixed;z-index:10;left:var(--gut);top:calc(var(--safe-t) + 64px);
  opacity:0;transform:translateY(-8px);transition:opacity .8s ease,transform .8s ease;
  pointer-events:none;max-width:min(46vw,260px);
}
/* A soft wash behind the column, with no edge anywhere on it. Over pale
   stubble at noon the type was reading as grey on grey no matter how hard
   the shadow worked, and a scrim does in one pass what stacking shadows
   never quite manages. It reaches well past the text on every side so there
   is no box, only a darkening. */
.task::before,.basket::before{
  content:"";position:absolute;z-index:-1;
  left:-38px;right:-52px;top:-34px;bottom:-34px;
  background:radial-gradient(112% 88% at 22% 50%,
    rgba(21,24,26,.46) 0%,rgba(21,24,26,.24) 46%,rgba(21,24,26,0) 78%);
}
.basket::before{background:radial-gradient(112% 92% at 22% 55%,
    rgba(21,24,26,.44) 0%,rgba(21,24,26,.22) 48%,rgba(21,24,26,0) 78%)}
.task.is-on{opacity:1;transform:none}
.task__head{color:var(--plaster);margin:0 0 14px;line-height:1.7;text-shadow:0 1px 2px rgba(21,24,26,.92),0 2px 16px rgba(21,24,26,.8)}
.task__list{list-style:none;margin:0;padding:0;border-top:1px solid var(--edge)}
.task__list li{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;
  padding:8px 0;border-bottom:1px solid rgba(229,227,219,.16);color:rgba(229,227,219,.86);
  display:flex;align-items:center;gap:9px;
  text-shadow:0 1px 2px rgba(21,24,26,.92),0 2px 14px rgba(21,24,26,.8);transition:color .5s;
}
.task__list li::before{
  content:"";width:5px;height:5px;flex:none;border:1px solid rgba(229,227,219,.72);
  transition:background .5s,border-color .5s,transform .5s;
}
.task__list li.is-got{color:rgba(229,227,219,.5)}
.task__list li.is-got::before{background:var(--moke);border-color:var(--moke);transform:rotate(45deg)}
.task__count{color:var(--board);margin:14px 0 0;text-shadow:0 1px 2px rgba(21,24,26,.92),0 2px 14px rgba(21,24,26,.8)}
@media (max-width:560px){
  .task{max-width:150px;top:calc(var(--safe-t) + 56px)}
  .task__head{font-size:9px;letter-spacing:.13em;margin-bottom:10px}
  .task__list li{font-size:9px;padding:6px 0;letter-spacing:.11em}
}

/* ---------- the second list ---------- */
.side{margin-top:22px;border-top:1px solid var(--edge);padding-top:14px}
.side__head{color:var(--board);margin:0 0 10px;text-shadow:0 1px 2px rgba(21,24,26,.92),0 2px 14px rgba(21,24,26,.8)}
.side__list{border-top:0}
.side__list li{
  font-size:10px;letter-spacing:.12em;color:rgba(229,227,219,.72);
  border-bottom:0;padding:5px 0;text-transform:none;
}
.side__list li.is-got{color:var(--moke)}
.side__list li.is-got::before{background:var(--moke);border-color:var(--moke);transform:rotate(45deg)}

/* ---------- what is in the back of the Moke ----------
   A number says how much and never says what, so every line carries its own
   glyph and its own count. On a desktop it sits bottom left, opposite the
   plan, which puts the errand down one side of the screen and the world down
   the other. On a phone the pads own the bottom and the plan owns the top
   right, so it tucks in under the plan and drops its labels.            */
.basket{
  position:fixed;z-index:10;left:var(--gut);bottom:calc(var(--safe-b) + 22px);
  max-width:min(46vw,268px);pointer-events:none;
  opacity:0;transform:translateY(6px);transition:opacity .6s ease,transform .6s ease;
}
.basket.is-on{opacity:1;transform:none}
.basket__head{
  color:var(--board);margin:0 0 10px;
  display:flex;align-items:center;gap:9px;
  text-shadow:0 1px 2px rgba(21,24,26,.92),0 2px 14px rgba(21,24,26,.8);
}
.basket__chain{
  color:var(--moke);letter-spacing:.14em;font-size:11px;
  text-shadow:0 1px 12px rgba(21,24,26,.85);
}
.basket__chain.is-hot{animation:chainpulse .34s ease}
@keyframes chainpulse{from{transform:scale(1.34);opacity:.45}to{transform:scale(1);opacity:1}}
.basket__list{
  list-style:none;margin:0;padding:0;
  display:flex;flex-wrap:wrap;gap:5px 12px;
}
.chip{
  display:flex;align-items:center;gap:6px;
  font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;
  color:rgba(229,227,219,.8);text-shadow:0 1px 2px rgba(21,24,26,.92),0 2px 14px rgba(21,24,26,.8);
  animation:chipin .4s ease;
}
.chip b{
  font-weight:500;color:var(--plaster);font-variant-numeric:tabular-nums;
  font-size:12px;letter-spacing:.02em;min-width:1.1em;text-align:right;
}
.chip .glyph{
  width:15px;height:15px;flex:none;
  filter:drop-shadow(0 1px 2px rgba(21,24,26,.95)) drop-shadow(0 2px 8px rgba(21,24,26,.7));
}
.chip--new b{color:var(--moke)}
@keyframes chipin{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
@media (max-width:620px),(hover:none){
  .basket{
    left:auto;right:var(--gut);bottom:auto;
    top:calc(var(--safe-t) + 186px);max-width:132px;
    text-align:right;
  }
  .basket__head{justify-content:flex-end;font-size:8.5px;letter-spacing:.12em;margin-bottom:7px}
  .basket__list{justify-content:flex-end;gap:4px 8px}
  .chip__label{display:none}
  .chip{gap:4px}
  .chip .glyph{width:13px;height:13px}
  .chip b{font-size:11px}
}
/* Below about seven hundred pixels of height the basket can grow up into the
   errand list, because the two share the left hand column. Dropping the
   labels turns a twelve row list into three, which is the whole fix. */
@media (max-height:780px){
  .basket__list{gap:3px 9px}
  .chip__label{display:none}
}

/* ---------- a real place ----------
   It was bottom centre, which put it over the Moke, over the band and over
   the one part of the screen the whole game is asking you to look at. It now
   sits on the right above the plan, so the right hand side of the screen is
   where the world tells you about itself and the left is where the errand
   lives. On a phone it goes full width above the pads, because a narrow
   column of body text on a 390 pixel screen is unreadable.             */
.place{
  position:fixed;z-index:12;right:var(--gut);bottom:calc(var(--safe-b) + 248px);
  width:min(348px,34vw);padding:15px 18px 13px;border-radius:14px;
  background:rgba(21,24,26,.82);border:1px solid rgba(198,178,145,.30);
  box-shadow:0 18px 50px rgba(21,24,26,.34);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  opacity:0;translate:0 8px;transition:opacity .4s ease,translate .4s ease;
}
.place.is-on{opacity:1;translate:0 0}
.place__eyebrow{margin:0 0 8px;color:var(--board)}
.place__title{
  margin:0;font-size:clamp(18px,2vw,23px);font-weight:600;letter-spacing:-.02em;line-height:1.1;
}
.place__line{
  font-family:var(--body);font-size:14.5px;line-height:1.45;
  margin:8px 0 12px;color:rgba(229,227,219,.78);
}
.place__open{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding-top:10px;border-top:1px solid var(--edge);
  font-family:var(--mono);font-size:10px;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;color:var(--verdigris-lt);
  pointer-events:auto;transition:color .25s;
}
.place__open:hover{color:var(--moke)}
.place__key{color:rgba(229,227,219,.42)}
.place.is-read .place__eyebrow{color:rgba(198,178,145,.5) !important}
.place.is-read .place__open{color:rgba(229,227,219,.5)}

/* On a phone the chase camera puts the Moke at roughly seventy per cent of
   the way down the screen and the pads own the bottom hundred and fifty
   pixels, which between them leave no gap at the bottom at all: a card there
   sits squarely on the car. The only free band is the top, over the sky and
   the far hillside, so that is where it goes.

   It cannot share that band with the list, the plan and the basket, so while
   a card is up those step aside. It is over in a few seconds, it is the thing
   being shown, and everything comes straight back. */
@media (max-width:620px),(hover:none){
  .place{
    left:var(--gut);right:var(--gut);width:auto;
    top:calc(var(--safe-t) + 56px);bottom:auto;padding:13px 15px 11px;
    translate:0 -8px;
  }
  .place.is-on{translate:0 0}
  .place__key{display:none}
  .place__line{font-size:14px;margin-bottom:10px}

  body.is-reading .task,
  body.is-reading .plan,
  body.is-reading .basket{opacity:0;pointer-events:none}
  .task,.plan,.basket{transition:opacity .35s ease,transform .8s ease}
}
@media (max-height:820px){
  .place__line{display:none}
  .place{padding-bottom:10px}
}
/* A phone on its side has about three hundred usable pixels of height, and
   the card, the plan and the pads have already claimed most of them. The
   basket goes along the top instead, beside the plan, glyphs only. */
@media (max-height:460px){
  .place{top:calc(var(--safe-t) + 44px)}
  .basket{
    top:calc(var(--safe-t) + 40px);right:calc(var(--gut) + 104px);
    max-width:46vw;
  }
  .basket__head{display:none}
  .basket__list{gap:3px 8px}
}

/* ---------- direction hint ---------- */
.pointer{
  position:fixed;z-index:9;left:50%;top:50%;translate:-50% -50%;
  display:flex;flex-direction:column;align-items:center;gap:6px;
  pointer-events:none;opacity:.62;transition:opacity .5s;
}
.pointer svg{width:20px;height:20px;fill:var(--plaster);filter:drop-shadow(0 1px 6px rgba(21,24,26,.7))}
.pointer__label{color:rgba(229,227,219,.8);font-size:9px;text-shadow:0 1px 8px rgba(21,24,26,.8)}

/* ---------- toast ---------- */
.toast{
  position:fixed;z-index:11;left:50%;bottom:calc(var(--safe-b) + 20vh);translate:-50% 0;
  text-align:center;pointer-events:none;
  opacity:0;transition:opacity .7s ease,translate .7s ease;
}
.toast.is-on{opacity:1;translate:-50% -10px}
.toast__name{margin:0;color:var(--moke);text-shadow:0 1px 14px rgba(21,24,26,.8)}
.toast__line{
  font-family:var(--body);font-style:italic;font-size:clamp(15px,1.6vw,18px);
  margin:8px 0 0;color:rgba(229,227,219,.9);text-shadow:0 1px 16px rgba(21,24,26,.85);
}

/* ---------- band message ---------- */
.band{
  position:fixed;z-index:11;left:0;right:0;bottom:calc(var(--safe-b) + 12vh);
  display:flex;justify-content:center;padding:0 var(--gut);pointer-events:none;
  opacity:0;transition:opacity .9s ease;
}
.band.is-on{opacity:1}
.band p{
  margin:0;font-size:clamp(18px,2.6vw,29px);font-weight:500;letter-spacing:-.02em;
  text-align:center;max-width:22ch;line-height:1.2;
  text-shadow:0 2px 22px rgba(21,24,26,.7);
}

/* ---------- action prompt ---------- */
.action{
  position:fixed;z-index:12;left:50%;bottom:calc(var(--safe-b) + 30px);translate:-50% 0;
  display:flex;flex-direction:column;align-items:center;gap:8px;
  opacity:0;transition:opacity .35s ease;
}
.action.is-on{opacity:1}
.actionbtn{
  font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.16em;text-transform:uppercase;
  padding:15px 30px;background:rgba(229,227,219,.94);color:var(--graphite);
  border:1px solid var(--plaster);transition:background .25s;
}
.actionbtn:hover{background:#fff}
.action__key{color:rgba(229,227,219,.6);text-shadow:0 1px 8px rgba(21,24,26,.8)}
@media (hover:none){.action__key{display:none}}
@media (hover:none){.action{bottom:calc(var(--safe-b) + 128px)}}

/* ---------- sheets ---------- */
/* The sheet was a centred flexbox with no scroll and no height cap. On a
   phone the nine control rows wrap to two lines each and the whole thing
   comes to more than the viewport, and a flex item centred in a container it
   overflows is clipped equally at both ends with no way to reach either. So
   the Close button sat below the bottom edge and could not be scrolled to.
   The sheet could be opened and not shut.

   Three fixes, because one is not enough for the only way out of a modal:
   the container scrolls and the panel is centred with auto margins instead
   of align-items, so overflow is always reachable. There is a close control
   pinned to the corner that never moves. And the backdrop and Escape both
   dismiss it. */
.sheet{
  position:fixed;inset:0;z-index:30;display:flex;justify-content:center;
  padding:calc(var(--gut) + var(--safe-t) + 44px) var(--gut) calc(var(--gut) + var(--safe-b));
  overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  background:rgba(21,24,26,.72);backdrop-filter:blur(6px);
}
.sheet__inner{
  max-width:440px;width:100%;margin:auto;background:var(--plaster);color:var(--graphite);
  padding:clamp(24px,4vw,38px);border-left:2px solid var(--verdigris);
}
.sheet__x{
  position:fixed;z-index:31;top:calc(var(--safe-t) + 14px);right:var(--gut);
  width:40px;height:40px;line-height:1;font-size:23px;
  display:flex;align-items:center;justify-content:center;
  color:var(--plaster);background:rgba(21,24,26,.5);
  border:1px solid rgba(229,227,219,.32);border-radius:50%;
  backdrop-filter:blur(4px);transition:background .25s,color .25s;
}
.sheet__x:hover{background:var(--plaster);color:var(--graphite)}
.sheet__eyebrow{color:rgba(21,24,26,.55);margin:0 0 20px}
.sheet__list{margin:0;padding:0;border-top:1px solid rgba(21,24,26,.14)}
.sheet__list div{
  display:flex;gap:16px;align-items:baseline;
  padding:11px 0;border-bottom:1px solid rgba(21,24,26,.14);
}
.sheet__list dt{
  font-family:var(--mono);font-size:10.5px;font-weight:500;letter-spacing:.13em;text-transform:uppercase;
  color:var(--verdigris);flex:none;min-width:104px;
}
.sheet__list dd{margin:0;font-family:var(--body);font-size:16px;line-height:1.45}
.sheet__note{
  font-family:var(--body);font-size:15.5px;line-height:1.5;color:rgba(21,24,26,.62);
  margin:22px 0 26px;
}
/* and it has to be short enough that it mostly does not need to scroll */
@media (max-width:620px),(hover:none){
  .sheet__inner{padding:20px 18px 22px}
  .sheet__eyebrow{margin-bottom:13px}
  .sheet__list div{padding:8px 0;gap:11px}
  .sheet__list dt{min-width:80px;font-size:9px;letter-spacing:.09em}
  .sheet__list dd{font-size:13.5px;line-height:1.34}
  .sheet__note{font-size:13.5px;margin:15px 0 17px}
}

/* ---------- ending ---------- */
.end{
  position:fixed;z-index:14;left:0;right:0;bottom:calc(var(--safe-b) + 8vh);
  display:flex;flex-direction:column;align-items:center;gap:18px;
  justify-content:center;padding:0 var(--gut);text-align:center;
  opacity:0;transition:opacity 1.6s ease;
}
.end.is-on{opacity:1}
.end__line{
  margin:0;font-family:var(--body);font-style:italic;
  font-size:clamp(20px,2.8vw,30px);line-height:1.25;max-width:24ch;
  text-shadow:0 2px 22px rgba(21,24,26,.7);
}
.end__note{
  margin:0;color:rgba(229,227,219,.56);max-width:44ch;line-height:2;
  text-shadow:0 1px 14px rgba(21,24,26,.8);
}
.end__actions{display:flex;gap:12px;flex-wrap:wrap;justify-content:center}

/* ---------- failure ---------- */
.fail{
  position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;
  padding:var(--gut);background:#15181A;text-align:left;
}
.fail__inner{max-width:520px}
.fail__inner .mono{color:var(--board);margin:0 0 18px}
.fail__inner h2{font-size:clamp(26px,4vw,40px);font-weight:600;letter-spacing:-.03em;margin:0 0 18px;line-height:1.05}
.fail__inner p{font-family:var(--body);font-size:17px;line-height:1.55;color:rgba(229,227,219,.72);margin:0 0 18px}
.fail__actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:28px}

/* ---------- touch pads ---------- */
.load__why{
  font-family:var(--body);font-weight:300;
  font-size:clamp(17px,1.85vw,23px);line-height:1.44;letter-spacing:-.004em;
  text-transform:none;
  margin:24px auto 30px;max-width:21em;
  color:rgba(229,227,219,.86);
}

.mix{margin:0;padding:0;border-top:1px solid rgba(21,24,26,.14)}
.mix__row{
  display:grid;grid-template-columns:minmax(0,1fr) 46px;gap:8px 14px;align-items:center;
  padding:15px 0;border-bottom:1px solid rgba(21,24,26,.10);
}
.mix__name{
  font-family:var(--mono);font-size:11px;font-weight:500;text-transform:uppercase;
  letter-spacing:.13em;color:var(--graphite);
}
.mix__val{font-family:var(--mono);font-size:11px;color:rgba(21,24,26,.5);text-align:right}
.mix__row input[type=range]{
  grid-column:1 / -1;-webkit-appearance:none;appearance:none;
  width:100%;height:2px;background:rgba(21,24,26,.22);border-radius:2px;outline:none;margin:2px 0 0;
}
.mix__row input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:17px;height:17px;border-radius:50%;
  background:var(--graphite);cursor:pointer;border:0;
}
.mix__row input[type=range]::-moz-range-thumb{
  width:17px;height:17px;border-radius:50%;background:var(--graphite);cursor:pointer;border:0;
}
.mix__row.is-off .mix__name,.mix__row.is-off .mix__val{color:rgba(21,24,26,.3)}
.mix__actions{display:flex;gap:10px;margin-top:22px;flex-wrap:wrap}

.end__line{
  margin:0 0 22px;font-family:var(--body);font-size:clamp(19px,2.1vw,27px);
  line-height:1.4;color:var(--plaster);text-align:center;max-width:20em;
  opacity:0;transform:translateY(6px);
  transition:opacity 1.4s ease .35s,transform 1.4s ease .35s;
}
.end.is-on .load__why{
  font-family:var(--body);font-weight:300;
  font-size:clamp(17px,1.85vw,23px);line-height:1.44;letter-spacing:-.004em;
  text-transform:none;
  margin:24px auto 30px;max-width:21em;
  color:rgba(229,227,219,.86);
}

.mix{margin:0;padding:0;border-top:1px solid rgba(21,24,26,.14)}
.mix__row{
  display:grid;grid-template-columns:minmax(0,1fr) 46px;gap:8px 14px;align-items:center;
  padding:15px 0;border-bottom:1px solid rgba(21,24,26,.10);
}
.mix__name{
  font-family:var(--mono);font-size:11px;font-weight:500;text-transform:uppercase;
  letter-spacing:.13em;color:var(--graphite);
}
.mix__val{font-family:var(--mono);font-size:11px;color:rgba(21,24,26,.5);text-align:right}
.mix__row input[type=range]{
  grid-column:1 / -1;-webkit-appearance:none;appearance:none;
  width:100%;height:2px;background:rgba(21,24,26,.22);border-radius:2px;outline:none;margin:2px 0 0;
}
.mix__row input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:17px;height:17px;border-radius:50%;
  background:var(--graphite);cursor:pointer;border:0;
}
.mix__row input[type=range]::-moz-range-thumb{
  width:17px;height:17px;border-radius:50%;background:var(--graphite);cursor:pointer;border:0;
}
.mix__row.is-off .mix__name,.mix__row.is-off .mix__val{color:rgba(21,24,26,.3)}
.mix__actions{display:flex;gap:10px;margin-top:22px;flex-wrap:wrap}

.end__line{opacity:1;transform:translateY(0)}

.pads{
  position:fixed;inset:auto 0 0 0;z-index:13;height:150px;
  padding:0 18px calc(var(--safe-b) + 18px);
  display:none;align-items:flex-end;justify-content:space-between;
  pointer-events:none;
}
.pads.is-on{display:flex}
.pad{pointer-events:auto;user-select:none;-webkit-user-select:none}
.pad--steer{display:flex;flex-direction:column;align-items:center;gap:8px;padding:22px 10px 4px}
.pad__track{
  width:132px;height:52px;border:1px solid rgba(229,227,219,.34);
  border-radius:26px;display:flex;align-items:center;justify-content:center;
  background:rgba(21,24,26,.24);backdrop-filter:blur(3px);
}
.pad__knob{
  width:44px;height:44px;border-radius:50%;background:rgba(229,227,219,.86);
  transition:transform .06s linear;
}
.pad--steer.is-live .pad__track{border-color:rgba(239,192,31,.8)}
.pad__label{
  font-family:var(--mono);font-size:9px;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(229,227,219,.55);
}
.pad--gas{display:flex;flex-direction:column;align-items:center;gap:9px}
.pad__gas,.pad__rev,.pad__boost{
  font-family:var(--mono);letter-spacing:.14em;text-transform:uppercase;
  border:1px solid rgba(229,227,219,.34);background:rgba(21,24,26,.24);
  backdrop-filter:blur(3px);color:rgba(229,227,219,.9);
}
.pad__gas{width:92px;height:92px;border-radius:50%;font-size:12px}
.pad__rev{width:64px;height:34px;border-radius:17px;font-size:9px}
/* second gear reads in the Moke's own yellow, since it is the one warm signal */
.pad__boost{
  width:78px;height:34px;border-radius:17px;font-size:9px;
  border-color:rgba(239,192,31,.52);color:rgba(239,192,31,.92);
}
.pad__gas.is-live,.pad__rev.is-live{background:rgba(239,192,31,.82);color:#15181A;border-color:var(--moke)}
.pad__boost.is-live{background:var(--moke);color:#15181A;border-color:var(--moke)}

/* steering under the other thumb, set from CONTROLS.steerSide */
.pads.is-swapped{flex-direction:row-reverse}

/* ---- the plan --------------------------------------------------------- */
.plan{
  position:fixed;z-index:10;right:var(--gut);bottom:calc(var(--safe-b) + 22px);
  width:184px;pointer-events:none;
  opacity:0;transform:translateY(8px);
  transition:opacity .7s ease,transform .7s ease;
}
.plan.is-on{opacity:1;transform:translateY(0)}
.plan__canvas{
  display:block;width:184px;height:184px;
  border:1px solid rgba(198,178,145,.34);border-radius:2px;
  background:rgba(21,24,26,.30);
  backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
}
.plan__label{
  margin:7px 0 0;font-size:9px;letter-spacing:.18em;
  color:rgba(229,227,219,.44);text-align:right;
}

/* on a phone the driving pads own the bottom, so the plan sits top right and
   shrinks to something you can glance at */
@media (max-width:620px),(hover:none){
  .plan{width:112px;right:var(--gut);bottom:auto;top:calc(var(--safe-t) + 64px)}
  .plan__canvas{width:112px;height:112px}
  .plan__label{display:none}
}
@media (max-height:460px){
  .plan{width:92px}
  .plan__canvas{width:92px;height:92px}
}

/* landscape phones get shorter pads so the road stays visible */
@media (max-height:460px){
  .load__why{
  font-family:var(--body);font-weight:300;
  font-size:clamp(17px,1.85vw,23px);line-height:1.44;letter-spacing:-.004em;
  text-transform:none;
  margin:24px auto 30px;max-width:21em;
  color:rgba(229,227,219,.86);
}

.mix{margin:0;padding:0;border-top:1px solid rgba(21,24,26,.14)}
.mix__row{
  display:grid;grid-template-columns:minmax(0,1fr) 46px;gap:8px 14px;align-items:center;
  padding:15px 0;border-bottom:1px solid rgba(21,24,26,.10);
}
.mix__name{
  font-family:var(--mono);font-size:11px;font-weight:500;text-transform:uppercase;
  letter-spacing:.13em;color:var(--graphite);
}
.mix__val{font-family:var(--mono);font-size:11px;color:rgba(21,24,26,.5);text-align:right}
.mix__row input[type=range]{
  grid-column:1 / -1;-webkit-appearance:none;appearance:none;
  width:100%;height:2px;background:rgba(21,24,26,.22);border-radius:2px;outline:none;margin:2px 0 0;
}
.mix__row input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:17px;height:17px;border-radius:50%;
  background:var(--graphite);cursor:pointer;border:0;
}
.mix__row input[type=range]::-moz-range-thumb{
  width:17px;height:17px;border-radius:50%;background:var(--graphite);cursor:pointer;border:0;
}
.mix__row.is-off .mix__name,.mix__row.is-off .mix__val{color:rgba(21,24,26,.3)}
.mix__actions{display:flex;gap:10px;margin-top:22px;flex-wrap:wrap}

.end__line{
  margin:0 0 22px;font-family:var(--body);font-size:clamp(19px,2.1vw,27px);
  line-height:1.4;color:var(--plaster);text-align:center;max-width:20em;
  opacity:0;transform:translateY(6px);
  transition:opacity 1.4s ease .35s,transform 1.4s ease .35s;
}
.end.is-on .load__why{
  font-family:var(--body);font-weight:300;
  font-size:clamp(17px,1.85vw,23px);line-height:1.44;letter-spacing:-.004em;
  text-transform:none;
  margin:24px auto 30px;max-width:21em;
  color:rgba(229,227,219,.86);
}

.mix{margin:0;padding:0;border-top:1px solid rgba(21,24,26,.14)}
.mix__row{
  display:grid;grid-template-columns:minmax(0,1fr) 46px;gap:8px 14px;align-items:center;
  padding:15px 0;border-bottom:1px solid rgba(21,24,26,.10);
}
.mix__name{
  font-family:var(--mono);font-size:11px;font-weight:500;text-transform:uppercase;
  letter-spacing:.13em;color:var(--graphite);
}
.mix__val{font-family:var(--mono);font-size:11px;color:rgba(21,24,26,.5);text-align:right}
.mix__row input[type=range]{
  grid-column:1 / -1;-webkit-appearance:none;appearance:none;
  width:100%;height:2px;background:rgba(21,24,26,.22);border-radius:2px;outline:none;margin:2px 0 0;
}
.mix__row input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:17px;height:17px;border-radius:50%;
  background:var(--graphite);cursor:pointer;border:0;
}
.mix__row input[type=range]::-moz-range-thumb{
  width:17px;height:17px;border-radius:50%;background:var(--graphite);cursor:pointer;border:0;
}
.mix__row.is-off .mix__name,.mix__row.is-off .mix__val{color:rgba(21,24,26,.3)}
.mix__actions{display:flex;gap:10px;margin-top:22px;flex-wrap:wrap}

.end__line{opacity:1;transform:translateY(0)}

.pads{height:118px;padding-bottom:calc(var(--safe-b) + 10px)}
  .pad__gas{width:74px;height:74px}
  .pad__boost,.pad__rev{height:28px}
  .pad__track{width:112px;height:44px}
  .pad__knob{width:38px;height:38px}
}


/* ==========================================================================
   The phone layout, resolved as bands rather than as separate decisions.

   Every panel here had been positioned on its own and they had begun to
   collide: the load floated loose under the map, the list ran halfway down
   the screen, and the toast and the band both landed on the Moke exactly the
   way the plaque card did.

   A phone screen has four bands and they do not overlap.

     topbar             the top of the screen
     the message strip  whatever the world is saying: a plaque, a band, a toast
     the panels         the list on the left, the map and the load on the right
     the Moke           nothing may be placed here, ever
     the pads           driving

   The chase camera puts the car at about seventy per cent of the way down, so
   the panels have to finish above that. The strip is a reserved height rather
   than something that pushes, so nothing is hidden to make room and no panel
   ever jumps. `--strip` is the whole of the vertical budget and every
   breakpoint below is one number: how much of the screen the message needs.
   ========================================================================== */
@media (max-width:620px),(hover:none){
  :root{ --strip:162px }

  /* ---- the message strip ---- */
  .place{
    left:var(--gut);right:var(--gut);width:auto;
    top:calc(var(--safe-t) + 54px);bottom:auto;padding:13px 15px 11px;
    translate:0 -8px;
  }
  .place.is-on{translate:0 0}
  .band{top:calc(var(--safe-t) + 62px);bottom:auto;align-items:flex-start}
  .band p{font-size:clamp(17px,5.2vw,22px);max-width:20ch}
  .toast{
    top:calc(var(--safe-t) + 66px);bottom:auto;translate:-50% -6px;
    max-width:min(88vw,420px);
  }
  .toast.is-on{translate:-50% 0}
  .toast__line{font-size:14.5px}
  /* the card answers where you are standing, so it takes the strip. A band
     and a toast are ambient and they repeat, so they wait. */
  body.is-reading .band,
  body.is-reading .toast{opacity:0}

  /* ---- the panels ---- */
  .task{top:calc(var(--safe-t) + 56px + var(--strip));max-width:132px}
  .task__head{display:none}
  .task__list li{font-size:8.5px;padding:5px 0;letter-spacing:.09em;gap:7px}
  .task__list li::before{width:4px;height:4px}
  .task__count{font-size:8.5px;margin-top:10px;letter-spacing:.1em}
  .side{margin-top:13px;padding-top:10px}
  .side__head{font-size:8.5px;margin-bottom:7px;letter-spacing:.1em}
  .side__list li{font-size:8.5px;padding:4px 0;letter-spacing:.08em}

  .plan{
    top:calc(var(--safe-t) + 56px + var(--strip));bottom:auto;
    right:var(--gut);width:112px;
  }
  .plan__canvas{width:112px;height:112px;border-radius:3px}

  /* The load sits directly under the map, the same width, the same border and
     the same wash, so the two read as one stacked panel rather than a row of
     numbers floating below a picture. */
  .basket{
    left:auto;right:var(--gut);bottom:auto;
    top:calc(var(--safe-t) + 56px + var(--strip) + 118px);
    width:112px;max-width:112px;padding:7px 7px 8px;
    border:1px solid rgba(198,178,145,.34);border-radius:3px;
    background:rgba(21,24,26,.42);
    backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
  }
  .basket::before{display:none}          /* the scrim belongs to the desktop column */
  .basket__head{
    display:flex;justify-content:flex-start;
    font-size:7.5px;letter-spacing:.09em;margin:0 0 6px;
  }
  .basket__list{justify-content:flex-start;gap:3px 3px}
  .chip{gap:2px;width:calc(33.333% - 2px);justify-content:flex-start}
  .chip__label{display:none}
  .chip .glyph{width:11px;height:11px}
  .chip b{font-size:9.5px;min-width:0;text-align:left}

  /* with the map switched off the load closes the gap rather than hanging */
  body.is-planoff .basket{top:calc(var(--safe-t) + 56px + var(--strip))}
}

/* Below about eight hundred pixels the card drops its body line, so the strip
   needs a third less room and the panels move up into it. */
@media (max-height:820px){ :root{ --strip:112px } }
@media (max-height:660px){ :root{ --strip:94px } }
@media (max-height:600px){ :root{ --strip:92px } }

/* On the smallest screens still in use, about three hundred and twenty by five
   hundred and sixty, there is no arrangement in which the list, the second
   list, the map, the load and the Moke all fit. The second list gives way,
   because it is the only panel that is optional by design. */
@media (max-width:620px) and (max-height:600px),(hover:none) and (max-height:600px){
  .side{display:none}
  .plan{width:84px}
  .plan__canvas{width:84px;height:84px}
  .basket{top:calc(var(--safe-t) + 56px + var(--strip) + 90px);width:84px}
}

@media (max-width:620px) and (max-height:700px),(hover:none) and (max-height:700px){
  .plan{width:92px}
  .plan__canvas{width:92px;height:92px}
  .basket{top:calc(var(--safe-t) + 56px + var(--strip) + 98px);width:92px}
  .basket__head{display:none}
  .chip .glyph{width:10px;height:10px}
  .chip b{font-size:9px}
}

/* A phone on its side has no vertical bands worth the name: the car sits two
   thirds of the way down a three hundred pixel screen and the pads take the
   bottom of it. So nothing stacks. The panels flank the car, which is only
   about ninety pixels wide in this aspect, the load moves alongside the map
   instead of under it, and the strip narrows to the middle so it clears them
   both. The second list is the one thing that will not fit, and it comes
   straight back when the phone is turned upright.                        */
@media (hover:none) and (max-height:460px){
  .place{left:150px;right:150px;top:calc(var(--safe-t) + 38px)}
  .band{top:calc(var(--safe-t) + 40px);padding:0 150px}
  .band p{font-size:clamp(15px,3.4vw,19px)}
  .toast{top:calc(var(--safe-t) + 42px);max-width:50vw}

  .task{top:calc(var(--safe-t) + 40px);max-width:112px}
  .task__list li{font-size:8px;padding:4px 0}
  .task__count{font-size:8px;margin-top:8px}
  .side{display:none}

  .plan{top:calc(var(--safe-t) + 40px);width:84px}
  .plan__canvas{width:84px;height:84px}

  /* beside the map would put the load under the message strip, so it stays
     under the map and the strip keeps the whole middle to itself */
  .basket{
    top:calc(var(--safe-t) + 40px + 90px);right:var(--gut);
    width:84px;max-width:84px;padding:6px;
  }
  .basket__head{display:none}
  .chip .glyph{width:10px;height:10px}
  .chip b{font-size:9px}
  body.is-planoff .basket{top:calc(var(--safe-t) + 40px)}
  body.is-reading .band,body.is-reading .toast{opacity:0}
}

/* Under three hundred and eighty pixels of height on a phone lying on its
   side there is no arrangement at all. The map wins over the load, because
   knowing where you are beats knowing what you picked, and the load is one
   rotation away. */
@media (hover:none) and (max-height:380px){
  .basket{display:none}
  .plan{width:72px}
  .plan__canvas{width:72px;height:72px}
}
