/* ═══════════════════════════════════════════════════════════════════════════
   Home — the screen a Wabi opens on.

   THE HOUSE RULES THIS SHEET KEEPS
   ─────────────────────────────────
   1. EVERY LENGTH IS A DESIGN POINT: calc(var(--pt)*n), where --pt is one
      point of the 402pt width the layout was drawn at. The framed desktop
      view and a real phone then get the SAME layout rather than two designs.
      The one exception is a tap target, which is 44 REAL pixels — the one
      measurement that must not scale is the one about a thumb.
   2. ONE DECLARED LIGHT, from just left of straight above (11 o'clock). Every
      raised thing has a lit hairline on its TOP inner edge, a shaded one along
      its BOTTOM, and a cast shadow BELOW it.
   3. GEOMETRY IS FIGMA'S, MEASURED off node 21431:22948 of 🌻 Wabi 2.0:
        gutter 20 · widget 140 square, radius 24 (--sm), 1.5px white border,
        gap 13 · row 361 wide, radius 24, fill rgba(147,147,147,.08), pad 16,
        gap 8, icon 56 (radius 20 for an app, round for an orb), name 16/18
        #090909, sub 14/16 #636363, time 14 at .7 · dock 282x54 pill + 54
        square, gap 14, radius 60, rgba(244,244,244,.3) with the glass-1 inner
        shadows · top-rail 126 tall, a gradient from #f2f2f2 to nothing.
   4. THREE INKS and no more: --ink for what you came to read, --ink-58 for
      what supports it, --ink-34 for the small print.
   ═══════════════════════════════════════════════════════════════════════════ */

@font-face{font-family:'Selecta';src:url(../fonts/Selecta-Regular.otf) format('opentype');font-weight:400;font-display:swap}
@font-face{font-family:'Selecta';src:url(../fonts/Selecta-Medium.otf) format('opentype');font-weight:500;font-display:swap}

:root{
  --ink:#090909;
  --ink-58:#636363;
  --ink-34:rgba(9,9,9,.34);
  --paper:#fafafa;
  --tile:#fafafa;
  --row:rgba(147,147,147,.08);
  --sm:24;                       /* the Figma radius token, in points */
  --ease:cubic-bezier(.22,1,.36,1);
  --spring:cubic-bezier(.34,1.42,.64,1);
  --sheet:cubic-bezier(.32,.72,0,1);
  /* elevation/3, straight off the Figma effect style */
  --e3:0 0 0 1px rgba(0,0,0,.02), 0 calc(var(--pt)*2) calc(var(--pt)*16) rgba(0,0,0,.04), 0 calc(var(--pt)*8) calc(var(--pt)*24) rgba(0,0,0,.10);
  --e2:0 0 0 1px rgba(0,0,0,.02), 0 calc(var(--pt)*2) calc(var(--pt)*6) rgba(0,0,0,.04), 0 calc(var(--pt)*4) calc(var(--pt)*8) rgba(0,0,0,.10);
  /* the exported artwork. ⚠ a url() in a real stylesheet resolves against the
     STYLESHEET, which is what we want; the trap is a url() inside a stylesheet
     built in JS, which resolves against the document. */
  --sheen:url(../img/orb.webp);
  --mag:url(../img/ui/search.svg);
  --plus:url(../img/ui/plus.svg);
}

*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{height:100%}
body{
  background:#101010;
  font-family:'Selecta',ui-sans-serif,system-ui,-apple-system,sans-serif;
  color:var(--ink);
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  overscroll-behavior:none;
}
button,textarea,input{font:inherit;color:inherit;border:0;background:none}
button{cursor:pointer}
[hidden]{display:none!important}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* ── the desk ─────────────────────────────────────────────────────────────
   Desktop only. `body.bare` is the same app with the hardware and the rail
   taken off, and a real phone is ALWAYS bare — the frame is a class, and
   js/app.js gates the class on matchMedia('(pointer:fine)') rather than a
   media query, because a media query cannot promise a class is absent. */
#desk{
  position:fixed;inset:0;display:flex;align-items:center;justify-content:center;
  gap:56px;
  background:radial-gradient(120% 90% at 50% 0%,#1b1b1b 0%,#0b0b0b 74%);
}
#device{
  position:relative;flex:none;width:402px;height:874px;
  container-type:size;container-name:app;
  border-radius:56px;overflow:hidden;isolation:isolate;
  background:var(--paper);
  box-shadow:
    0 0 0 12px #16161a, 0 0 0 13px #3a3a40, 0 0 0 15px #0d0d10,
    0 60px 120px -40px rgba(0,0,0,.9), 0 10px 40px -12px rgba(0,0,0,.6);
}
body.bare #desk{background:var(--paper);gap:0}
body.bare #device{width:100%;height:100%;border-radius:0;box-shadow:none}
body.bare #rail{display:none}
.island,.homebar{position:absolute;left:50%;transform:translateX(-50%);z-index:60;pointer-events:none}
.island{top:11px;width:125px;height:36px;border-radius:20px;background:#0a0a0a}
.homebar{bottom:8px;width:139px;height:5px;border-radius:3px;background:rgba(9,9,9,.32)}
body.bare .island,body.bare .homebar{display:none}

/* ── the reviewer's rail ───────────────────────────────────────────────── */
#rail{
  flex:none;width:268px;color:rgba(255,255,255,.9);
  display:flex;flex-direction:column;gap:18px;
}
.rail-hd b{display:block;font-weight:500;font-size:17px;letter-spacing:-.02em}
.rail-hd span{display:block;margin-top:4px;font-size:13px;color:rgba(255,255,255,.42)}
#people-rail{display:flex;flex-direction:column;gap:6px}
.pcard{
  display:flex;align-items:center;gap:11px;width:100%;text-align:left;
  padding:9px 11px;border-radius:15px;
  background:rgba(255,255,255,.05);
  transition:background .2s var(--ease);
}
.pcard:hover{background:rgba(255,255,255,.10)}
.pcard[aria-pressed=true]{background:rgba(255,255,255,.16);box-shadow:inset 0 0 0 1px rgba(255,255,255,.16)}
.pcard .orb{width:30px;height:30px;flex:none}
.pcard b{display:block;font-weight:500;font-size:14px;letter-spacing:-.015em}
.pcard span{display:block;font-size:12px;color:rgba(255,255,255,.44);letter-spacing:-.01em}
.pcard kbd{
  margin-left:auto;font:inherit;font-size:11px;color:rgba(255,255,255,.3);
  padding:2px 6px;border-radius:5px;background:rgba(255,255,255,.06);
}
.rail-ft{margin-top:2px;display:flex;flex-direction:column;gap:9px;align-items:flex-start}
#tolib,#vtoggle{
  font-size:13px;color:rgba(255,255,255,.66);text-decoration:none;
  padding:8px 13px;border-radius:999px;background:rgba(255,255,255,.07);
}
#tolib:hover,#vtoggle:hover{color:#fff;background:rgba(255,255,255,.13)}
.rail-note{font-size:11.5px;line-height:1.45;color:rgba(255,255,255,.3);max-width:236px}
body.bare #vtoggle{
  display:block;position:fixed;right:18px;top:18px;z-index:90;
  background:rgba(9,9,9,.07);color:var(--ink-58);
}

/* ── the app ──────────────────────────────────────────────────────────────
   --pt is 1/402 of the device's own width. --top and --bot are the phone's
   safe areas: real insets on a phone, the drawn island and home bar in the
   frame, so the layout is under the same constraint either way. */
#stage{
  position:absolute;inset:0;overflow:hidden;isolation:isolate;
  --pt:calc(100cqw / 402);
  --top:calc(var(--pt)*59);
  --bot:calc(var(--pt)*34);
  --gut:calc(var(--pt)*20);
  /* ⚠ 54 DESIGN POINTS IS 43 REAL PIXELS ON A 320pt PHONE. The one measurement
     that must not scale is the one about a thumb. */
  --dock:max(48px, calc(var(--pt)*54));
}
body.bare #stage{
  --top:max(calc(var(--pt)*20), env(safe-area-inset-top));
  --bot:max(calc(var(--pt)*16), env(safe-area-inset-bottom));
}
#wash{position:absolute;inset:0;z-index:0;pointer-events:none;background:#fafafa}

/* ── the top rail ─────────────────────────────────────────────────────────
   126pt tall, a gradient from the neutral ground to nothing, so the widgets
   dissolve INTO it as they scroll under rather than being sliced by an edge. */
#top{
  position:absolute;left:0;right:0;top:0;z-index:40;
  height:calc(var(--top) + var(--pt)*67);
  padding-top:var(--top);
  background:linear-gradient(#f2f2f2 0%, #f2f2f2 58%, rgba(250,250,250,0) 100%);
  -webkit-backdrop-filter:blur(calc(var(--pt)*8));backdrop-filter:blur(calc(var(--pt)*8));
  pointer-events:none;
}
#top>*{pointer-events:auto}
#top .status{
  position:absolute;left:0;right:0;top:calc(var(--pt)*21);height:calc(var(--pt)*22);
  display:flex;align-items:center;justify-content:space-between;
  padding:0 calc(var(--pt)*16);
}
body.bare #top .status{display:none}
#top .clock{font-weight:500;font-size:calc(var(--pt)*17);letter-spacing:-.01em}
#top .levels{display:flex;align-items:center;gap:calc(var(--pt)*7)}
#top .levels img{display:block;height:calc(var(--pt)*12)}
#top .tool{
  position:absolute;left:var(--gut);right:var(--gut);bottom:calc(var(--pt)*9);
  height:calc(var(--pt)*44);display:flex;align-items:center;justify-content:space-between;
}
#top .logo{display:block;width:calc(var(--pt)*112);color:var(--ink)}
#top .logo svg{display:block;width:100%;height:auto}
#top .me{
  width:max(44px, calc(var(--pt)*44));height:max(44px, calc(var(--pt)*44));
  display:grid;place-items:center;border-radius:999px;
  transition:transform .3s var(--spring);
}
#top .me:active{transform:scale(.93)}
#top .me .orb{width:calc(var(--pt)*44);height:calc(var(--pt)*44)}

/* the orb: a coloured ground with the mark's own specular screened over it —
   the Figma component exactly, including the 120.21% / -9.96% / -9% that push
   the plate's white margin outside the circle. */
.orb{
  position:relative;display:block;border-radius:50%;overflow:hidden;flex:none;
  background:radial-gradient(120% 120% at 30% 18%, var(--o1,#8ab) 0%, var(--o2,#248) 78%);
  box-shadow:0 0 0 1.5px #fff, 0 0 0 2.5px rgba(0,0,0,.02),
             0 calc(var(--pt)*3) calc(var(--pt)*7) rgba(0,0,0,.16);
}
.orb::after{
  content:'';position:absolute;left:-9.96%;top:-9%;width:120.21%;height:120.21%;
  background:var(--sheen) center/contain no-repeat;
  mix-blend-mode:screen;pointer-events:none;
}

/* ── the scroller ─────────────────────────────────────────────────────── */
#scroll{
  position:absolute;inset:0;z-index:10;
  overflow-y:auto;overflow-x:hidden;
  -webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  scrollbar-width:none;
}
#scroll::-webkit-scrollbar{display:none}
#page{
  padding-top:calc(var(--top) + var(--pt)*67);
  /* the dock floats over the list, so the list has to end above it */
  padding-bottom:calc(var(--bot) + var(--dock) + var(--pt)*40);
}

/* ── the widgets ──────────────────────────────────────────────────────────
   ⚠ A MOUSE CANNOT SWIPE `overflow-x`. It scrolls under a finger and a wheel
     and not at all under a mouse drag, so on the one machine this gets reviewed
     on the row would be dead. js/app.js drags scrollLeft by hand, with NO
     pointer capture — capturing on a scroller retargets the following `click`
     and every widget here is a button. */
.widgets{
  display:flex;gap:calc(var(--pt)*13);
  padding:calc(var(--pt)*4) var(--gut) calc(var(--pt)*18);
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none;
  scroll-snap-type:x proximity;scroll-padding-left:var(--gut);
  -webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;
}
.widgets::-webkit-scrollbar{display:none}
.cell{
  flex:none;position:relative;display:block;padding:0;
  width:calc(var(--pt)*140);height:calc(var(--pt)*140);
  scroll-snap-align:start;
  transition:transform .42s var(--spring);
  will-change:transform;
}
.cell:active{transform:scale(.965)}
.cell .field{
  position:absolute;inset:0;display:block;overflow:hidden;
  border-radius:calc(var(--pt)*var(--sm));
  background:var(--tile);isolation:isolate;
  /* 1.5px white border + elevation/3, both the artwork's own */
  box-shadow:0 0 0 1.5px #fff, var(--e3);
}
.widgets.drag{cursor:grabbing}
.widgets.drag .cell{pointer-events:none}

/* ── the list ─────────────────────────────────────────────────────────── */
.list{display:flex;flex-direction:column;gap:calc(var(--pt)*8);padding:0 var(--gut)}
.rowc{
  position:relative;display:flex;align-items:center;justify-content:space-between;
  gap:calc(var(--pt)*12);width:100%;text-align:left;
  padding:calc(var(--pt)*16);
  border-radius:calc(var(--pt)*var(--sm));
  background:var(--row);
  transition:transform .3s var(--spring), background .2s var(--ease);
}
.rowc:first-child{box-shadow:inset 0 0 0 1.5px #fff}
.rowc:active{transform:scale(.985);background:rgba(147,147,147,.14)}
.rowc .ic{flex:none;width:calc(var(--pt)*56);height:calc(var(--pt)*56);position:relative}
/* an app's icon is the widget itself, laid out at ITS own size and scaled —
   a photograph of the app running, not a redraw of it */
.rowc .ic .field{
  position:absolute;left:0;top:0;transform-origin:0 0;overflow:hidden;
  border-radius:calc(var(--pt)*20);background:var(--tile);
  box-shadow:0 0 0 1.5px #fff, var(--e2);
}
.rowc .txt{flex:1;min-width:0}
.rowc .txt b{
  display:block;font-weight:400;font-size:calc(var(--pt)*16);line-height:calc(var(--pt)*18);
  color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.rowc .txt span{
  display:block;margin-top:calc(var(--pt)*2);
  font-size:calc(var(--pt)*14);line-height:calc(var(--pt)*16);
  color:var(--ink-58);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.rowc.new .txt span{font-weight:500;color:var(--ink)}
.rowc .when{
  flex:none;display:flex;align-items:center;gap:calc(var(--pt)*8);
  font-size:calc(var(--pt)*14);line-height:calc(var(--pt)*16);color:var(--ink-58);opacity:.7;
}
.rowc .when i{width:calc(var(--pt)*6);height:calc(var(--pt)*6);border-radius:50%;background:#2f6bff}
.credit{
  padding:calc(var(--pt)*22) var(--gut) 0;
  font-size:calc(var(--pt)*11.5);line-height:1.5;color:var(--ink-34);text-align:center;
}

/* ── the dock ─────────────────────────────────────────────────────────────
   Two pieces of glass floating over the list: the search, and the one way to
   make something new. Geometry is the artwork's: 282x54 and 54 square, 14
   apart, radius 60, and the glass-1 inner shadows. */
#dock{
  position:absolute;left:50%;bottom:calc(var(--bot) + var(--pt)*12);z-index:45;
  transform:translateX(-50%);
  display:flex;align-items:center;gap:calc(var(--pt)*14);
}
#dock .pill,#dock .plus{
  height:var(--dock);border-radius:calc(var(--pt)*60);
  background:rgba(244,244,244,.3);
  -webkit-backdrop-filter:blur(calc(var(--pt)*18)) saturate(1.6);
  backdrop-filter:blur(calc(var(--pt)*18)) saturate(1.6);
  box-shadow:
    inset -1px -1px 2px 0 rgba(255,255,255,.32),
    inset 1px 1px 1px 0 rgba(255,255,255,.12),
    0 calc(var(--pt)*6) calc(var(--pt)*18) rgba(0,0,0,.10);
}
#dock .pill{
  width:calc(var(--pt)*282);display:flex;align-items:center;gap:calc(var(--pt)*11);
  padding:0 calc(var(--pt)*23);
}
#dock .mag{
  width:calc(var(--pt)*18);height:calc(var(--pt)*18);flex:none;
  background:var(--mag) center/contain no-repeat;opacity:.4;
}
#dock input{
  flex:1;min-width:0;height:100%;
  font-size:calc(var(--pt)*16);line-height:calc(var(--pt)*16);color:var(--ink);
}
#dock input::placeholder{color:rgba(0,0,0,.3)}
#dock input::-webkit-search-cancel-button{display:none}
#dock .plus{
  width:var(--dock);flex:none;display:grid;place-items:center;
  transition:transform .3s var(--spring);
}
#dock .plus:active{transform:scale(.93)}
#dock .pl{
  width:calc(var(--pt)*28);height:calc(var(--pt)*28);display:block;
  background:var(--plus) center/contain no-repeat;
}
body.searching #dock .plus{display:none}
body.searching #dock .pill{width:calc(var(--pt)*350)}

/* ── the app, opened ──────────────────────────────────────────────────────
   Tapping a widget OPENS it. The tile flies up and becomes the thing itself at
   the width of the phone — the same object, the same sim, not a screenshot —
   and the one verb under it is how you get your own. */
#open{
  position:absolute;inset:0;z-index:55;display:flex;flex-direction:column;
  background:#fafafa;
  padding:calc(var(--top) + var(--pt)*10) var(--gut) calc(var(--bot) + var(--pt)*18);
}
#open.in{animation:openin .42s var(--ease) both}
@keyframes openin{from{opacity:0}to{opacity:1}}
#open .oh{display:flex;align-items:center;gap:calc(var(--pt)*12);height:max(44px, calc(var(--pt)*44))}
#open .back{
  width:max(44px, calc(var(--pt)*44));height:max(44px, calc(var(--pt)*44));
  margin-left:calc(var(--pt)*-10);
  display:grid;place-items:center;border-radius:999px;position:relative;
}
#open .back::before{
  content:'';width:calc(var(--pt)*11);height:calc(var(--pt)*11);
  border-left:calc(var(--pt)*2) solid var(--ink);
  border-bottom:calc(var(--pt)*2) solid var(--ink);
  transform:rotate(45deg);border-radius:1px;
}
#open .who{font-size:calc(var(--pt)*15);color:var(--ink-58)}
#open .big{
  margin-top:calc(var(--pt)*10);
  width:100%;aspect-ratio:1;position:relative;
}
#open .big .field{
  position:absolute;inset:0;display:block;overflow:hidden;isolation:isolate;
  border-radius:calc(var(--pt)*34);background:var(--tile);
  box-shadow:0 0 0 1.5px #fff, var(--e3);
}
#open .ot{margin-top:calc(var(--pt)*26)}
#open .ot b{display:block;font-weight:500;font-size:calc(var(--pt)*28);letter-spacing:-.034em}
#open .ot p{
  margin-top:calc(var(--pt)*8);
  font-size:calc(var(--pt)*16);line-height:1.42;letter-spacing:-.012em;color:var(--ink-58);
  text-wrap:pretty;
}
#open .oa{margin-top:auto;display:flex}
#open .oa .btn{flex:1}

/* ── whose phone is this ──────────────────────────────────────────────── */
#people{position:absolute;inset:0;z-index:72}
#people::before{
  content:'';position:absolute;inset:0;background:rgba(18,18,17,.42);
  -webkit-backdrop-filter:blur(calc(var(--pt)*4));backdrop-filter:blur(calc(var(--pt)*4));
  animation:fadein .34s var(--ease) both;
}
#people .sh{
  position:absolute;left:0;right:0;bottom:0;
  padding:calc(var(--pt)*10) calc(var(--pt)*18) calc(var(--bot) + var(--pt)*18);
  border-radius:calc(var(--pt)*30) calc(var(--pt)*30) 0 0;
  background:#fbfbfa;
  box-shadow:0 calc(var(--pt)*-10) calc(var(--pt)*40) rgba(0,0,0,.30);
  animation:up .46s var(--sheet) both;
}
#people .k{
  font-weight:500;font-size:calc(var(--pt)*15);letter-spacing:-.016em;color:var(--ink-58);
  padding:0 calc(var(--pt)*4) calc(var(--pt)*12);
}
.who-list{display:flex;flex-direction:column;gap:calc(var(--pt)*4)}
.who-row{
  display:flex;align-items:center;gap:calc(var(--pt)*12);width:100%;text-align:left;
  padding:calc(var(--pt)*10) calc(var(--pt)*12);border-radius:calc(var(--pt)*18);
  min-height:max(44px, calc(var(--pt)*60));
}
.who-row[aria-pressed=true]{background:rgba(147,147,147,.12)}
.who-row .orb{width:calc(var(--pt)*40);height:calc(var(--pt)*40)}
.who-row b{display:block;font-weight:500;font-size:calc(var(--pt)*16);letter-spacing:-.015em}
.who-row span{display:block;font-size:calc(var(--pt)*14);color:var(--ink-58)}
#people .tiny{margin-top:calc(var(--pt)*14)}

/* ── the way in ───────────────────────────────────────────────────────────
   The widgets deal themselves along the row, then the list arrives under them.
   ⚠ IT PLAYS ONCE. Replaying it every time you switch person is an animation
     between two screens somebody is deliberately moving between. */
body.boot .cell{animation:dealx .62s var(--ease) both;animation-delay:calc(var(--i,0)*64ms + 40ms)}
body.boot .rowc{animation:rise .6s var(--ease) both;animation-delay:calc(var(--i,0)*44ms + 220ms)}
@keyframes dealx{from{opacity:0;transform:translateX(calc(var(--pt)*26)) scale(.94)}to{opacity:1;transform:none}}
@keyframes rise{from{opacity:0;transform:translateY(calc(var(--pt)*16))}to{opacity:1;transform:none}}
/* switching person is not a boot: the contents cross-fade in place */
body.swap .widgets,body.swap .list{animation:swap .46s var(--ease) both}
@keyframes swap{
  0%{opacity:1;transform:none}
  38%{opacity:0;transform:translateY(calc(var(--pt)*6))}
  100%{opacity:1;transform:none}
}

/* ── the chip ──────────────────────────────────────────────────────────────
   ⚠ A 38pt WIDGET IS MUD. Laid out at 38pt the scope's screen inset is two
     pixels and its labels are two pixels tall, so the chip came out as a black
     square — a thumbnail of nothing. Everything inside a widget is `cqw` of the
     tile, so the fix is to lay the art out at ITS OWN 171pt and then SCALE the
     whole thing down: a true miniature of the tile, still live, still the same
     object. Photograph, not redraw. */
.chip{
  position:relative;flex:none;
  width:calc(var(--pt)*56);height:calc(var(--pt)*56);
  border-radius:calc(var(--pt)*14);overflow:hidden;
  background:var(--tile);
  box-shadow:0 0 0 1px rgba(0,0,0,.06),0 calc(var(--pt)*3) calc(var(--pt)*8) rgba(0,0,0,.14);
}
.chip .field{
  position:absolute;left:0;top:0;
  transform-origin:0 0;
  border-radius:calc(var(--pt)*47);box-shadow:none;background:var(--tile);
}
.chip.in{animation:chipin .44s var(--spring) both}
@keyframes chipin{from{opacity:0;transform:scale(.5)}to{opacity:1;transform:none}}

/* ── the morph ─────────────────────────────────────────────────────────────
   The tile you tapped travels into the bar and becomes the chip. A cross-fade
   here would be the single most common motion defect in the book: the sentence
   has to come from somewhere, and it comes from the thing you touched. */
#ghost{
  position:absolute;z-index:55;pointer-events:none;
  border-radius:calc(var(--pt)*15);overflow:hidden;background:var(--tile);
  box-shadow:var(--e3);
  transform-origin:0 0;
}
#ghost .field{position:absolute;inset:0;box-shadow:none;border-radius:inherit}

/* the widget the sentence came from stays marked, so the loop closes */
.cell.picked .field{
  box-shadow:
    0 0 0 calc(var(--pt)*2) rgba(25,25,25,.86),
    0 calc(var(--pt)*4) calc(var(--pt)*8) rgba(0,0,0,.10),
    0 calc(var(--pt)*14) calc(var(--pt)*32) rgba(0,0,0,.20);
}
.cell .field{transition:box-shadow .34s var(--ease)}

/* ── the sheet: the composer ──────────────────────────────────────────────
   A tap opens this. It carries the tile you tapped (still running), the
   sentence that tile wrote, its own three refinements, and the one verb. There
   is no text field: in Wabi the field is the host's, and this hands the prompt
   to it. */
#sheetup{position:absolute;inset:0;z-index:70}
#sheetup::before{
  content:'';position:absolute;inset:0;background:rgba(18,18,17,.42);
  backdrop-filter:blur(calc(var(--pt)*4));
  -webkit-backdrop-filter:blur(calc(var(--pt)*4));
  animation:fadein .34s var(--ease) both;
}
#sheetup .sh{
  position:absolute;left:0;right:0;bottom:0;
  padding:calc(var(--pt)*10) calc(var(--pt)*22) calc(var(--bot) + var(--pt)*20);
  border-radius:calc(var(--pt)*30) calc(var(--pt)*30) 0 0;
  background:#fbfbfa;
  box-shadow:0 calc(var(--pt)*-10) calc(var(--pt)*40) rgba(0,0,0,.30);
  animation:up .46s var(--sheet) both;
}
/* ⚠ one measurement is taken while the sheet is sliding: `.still` parks it so
   the chip's rect is where it is GOING, not where it is. */
#sheetup.still .sh,#sheetup.still::before{animation:none;transform:none}
@keyframes fadein{from{opacity:0}to{opacity:1}}
@keyframes up{from{transform:translateY(100%)}to{transform:none}}
#sheetup .grip{width:calc(var(--pt)*38);height:calc(var(--pt)*5);border-radius:999px;background:rgba(25,25,25,.10);margin:0 auto calc(var(--pt)*16)}

#sheetup .shhead{display:flex;align-items:center;gap:calc(var(--pt)*11);margin-bottom:calc(var(--pt)*14)}
#sheetup .k{
  font-weight:500;font-size:calc(var(--pt)*15);letter-spacing:-.016em;color:var(--ink-58);
}
#sheetup .p{
  font-size:calc(var(--pt)*20);line-height:1.3;letter-spacing:-.022em;text-wrap:pretty;
  min-height:calc(var(--pt)*78);
}
#sheetup .row{display:flex;gap:calc(var(--pt)*10);margin-top:calc(var(--pt)*20)}
/* ⚠ 44 REAL PIXELS, not 44 design points. --pt scales with the screen, so on a
   320pt phone a button sized in points came out 38 tall — the one measurement
   that must not scale is the one about a thumb. */
.btn{
  flex:1;min-height:max(46px, calc(var(--pt)*48));
  padding:calc(var(--pt)*15) calc(var(--pt)*16);border-radius:999px;
  font-weight:500;font-size:calc(var(--pt)*15.5);letter-spacing:-.016em;
  background:var(--ink);color:#fff;
  box-shadow:0 calc(var(--pt)*6) calc(var(--pt)*14) calc(var(--pt)*-8) rgba(0,0,0,.5);
  transition:transform .2s var(--ease);
}
.btn.ghost{flex:0 0 auto;padding-inline:calc(var(--pt)*20);background:rgba(25,25,25,.06);color:var(--ink-58);box-shadow:none}
.btn:active{transform:scale(.98)}
#sheetup .tiny{margin-top:calc(var(--pt)*13);font-size:calc(var(--pt)*11.5);color:var(--ink-34);text-align:center}
#sheetup code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}

/* the refinements: this widget's own three. Deliberately NOT tiles — a tile is
   a thing you could have, a pill is a way to change the thing you just chose. */
#pills{display:flex;flex-wrap:wrap;gap:calc(var(--pt)*7);margin-top:calc(var(--pt)*4)}
.pill{
  min-height:max(38px, calc(var(--pt)*38));
  padding:calc(var(--pt)*10) calc(var(--pt)*14) calc(var(--pt)*11);
  border-radius:999px;
  font-size:calc(var(--pt)*13.5);letter-spacing:-.014em;color:var(--ink-58);
  background:rgba(25,25,25,.05);
  box-shadow:inset 0 0 0 1px rgba(25,25,25,.05);
  transition:transform .3s var(--spring),background .2s var(--ease),color .2s var(--ease);
  animation:pillin .46s var(--ease) both;animation-delay:calc(var(--i,0)*52ms);
}
@keyframes pillin{from{opacity:0;transform:translateY(calc(var(--pt)*8)) scale(.94)}to{opacity:1;transform:none}}
.pill:active{transform:scale(.96)}
.pill.on{background:var(--ink);color:#fff;box-shadow:none}

/* ── reduced motion: nothing moves unasked. The widgets stop too — they are
      ambient by definition, and ambient motion is the first thing this
      setting is about. ─────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  body.boot .cell,body.boot .rowc{animation:none}
  body.swap .widgets,body.swap .list{animation:none}
  #open.in{animation-duration:.01s}
  #sheetup .sh,#sheetup::before{animation-duration:.01s}
}

/* ── a short phone ────────────────────────────────────────────────────────
   On a 568pt screen the greeting was taking nearly half of it and only two
   tiles were above the dock. The board is the content, so the header gives way
   — measured against the DEVICE's own box (a container query), not the viewport,
   because inside the drawn frame the viewport is the desk. */
@container app (max-height: 700px){
  /* a short phone: the widgets give up a little height so a row and a half of
     the list is still under them */
  .cell{width:calc(var(--pt)*124);height:calc(var(--pt)*124)}
  .widgets{padding-bottom:calc(var(--pt)*14)}
  #open .ot b{font-size:calc(var(--pt)*24)}
}
