/* ============ my.adhd — the app: dump -> triage -> one task ============
   Tokens and the type face come from theme.css, loaded first. */

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
/* the rubber-band area on iOS falls through to <html>, so it carries the same
   --surface as the body — otherwise it flashes the light ground in dark mode */
html{background:var(--surface)}

body{
  background:var(--surface);
  color:var(--ink);
  font-family:var(--display);
  -webkit-font-smoothing:antialiased;
  line-height:1.45;
  /* The document must not scroll — see #app. */
  overflow:hidden;
}

/* soft geometry in the backdrop — the reference's floating circles */

/* #app is the scroller, not the document.
   iOS drags position:fixed elements along with the rubber band when the
   *document* overscrolls, which is why the tab bar drifted up and down at
   the ends of a scroll instead of holding its place. A fixed element only
   holds still if the thing behind it never moves, so the page scrolls
   inside this box and the document stays put. overscroll-behavior stops a
   scroll that runs off either end from being handed back up to it. */
#app{
  position:relative; z-index:1;
  height:100%; height:100dvh;
  overflow-y:auto; overflow-x:hidden;
  -webkit-overflow-scrolling:touch;
  overscroll-behavior-y:contain;
}

/* One flat page in the current theme's --surface. Content is held to a
   readable measure and centred — no card, no shadow, no tinted ground for
   it to float on. */
/* The top inset and the gutter are read by both .screen and the brand bar,
   which has to stop exactly where the status bar ends. Declared once so the
   two can never drift apart.

   The floor on --safe-top is the important half. Launched from the home
   screen iOS does not always report an inset, and the gap alone puts the
   toggle hard against the clock; max() leaves a phone that reports 59px
   untouched and still clears the status bar on one that reports nothing.
   See the standalone block below. */
:root{
  --safe-top:env(safe-area-inset-top, 0px);
  --gutter:clamp(20px,5vw,40px);
  /* the air above the mark — shorter than the old 22-34px, which sat the
     lockup lower on the screen than it wanted to */
  --brand-gap:clamp(12px,2vw,20px);
}

.screen{
  min-height:100%;
  display:flex; flex-direction:column; align-items:center;
  width:100%;
  background:var(--surface);
  /* viewport-fit=cover hands us the whole screen, notch included — so the
     gutters have to carry the insets themselves or the header sits under
     the status bar once the app runs from the home screen. */
  padding-top:calc(var(--brand-gap) + var(--safe-top));
  padding-right:calc(var(--gutter) + env(safe-area-inset-right, 0px));
  padding-bottom:calc(clamp(48px,7vw,80px) + env(safe-area-inset-bottom, 0px));
  padding-left:calc(var(--gutter) + env(safe-area-inset-left, 0px));
}
.screen > *{width:100%; max-width:var(--measure)}

/* The 80px foot is thumb room on a phone. On a desktop window there is no
   thumb, and it was the whole reason a 900px-tall screen scrolled 14px to
   reach nothing. */
@media (min-width:820px){
  .screen{padding-bottom:calc(clamp(32px,4vw,56px) + env(safe-area-inset-bottom, 0px))}
}

@media (display-mode:standalone){
  :root{--safe-top:max(env(safe-area-inset-top, 0px), 34px)}
}

.is-hidden{display:none !important}

/* shared illustration ink */
.s-ink{stroke:var(--ink); stroke-width:2.2; fill:none}
.s-soft{stroke:var(--line-strong); stroke-width:2; fill:none}
.f-ink{fill:var(--ink)}
.f-mid{fill:var(--line-strong)}
.f-wash{fill:var(--wash-2)}
.f-surface{fill:var(--surface)}

/* ---------- the mascot ----------
   Hand-drawn character: the one place colour is allowed to live.
   Everything around it stays monochrome. */
.sprite{position:absolute; width:0; height:0; overflow:hidden}

.mx-ink{stroke:var(--mx-ink); stroke-width:3.2; fill:none; stroke-linejoin:round}
.mx-cap{stroke-linecap:round; stroke-linejoin:round}
/* fills come after .mx-ink so they win the fill:none */
.mx-skin{fill:var(--mx-skin)}
.mx-hair{fill:var(--mx-hair)}
.mx-tee{fill:var(--mx-tee)}
.mx-eye{fill:var(--mx-ink)}
.mx-lens{fill:var(--mx-lens); fill-opacity:var(--mx-lens-alpha)}
.mx-blob{fill:var(--mx-bg)}

/* The character's outer contour, lit only when the ground is too dark to
   draw it. Applied to the top-level <use> so the whole figure resolves to
   one silhouette; the panel behind it is left alone. */
.art svg > use{filter:var(--mx-rim)}
.mx-curls{stroke:none}
.mx-strand{stroke:var(--mx-strand); opacity:.85; stroke-width:2; fill:none; stroke-linecap:round}
.mx-tee-line{stroke:var(--mx-ink); stroke-width:2.4; fill:none; stroke-linecap:round; opacity:.5}
.mx-blush path{stroke:var(--mx-blush); stroke-width:3.4; stroke-linecap:round; fill:none; opacity:.85}
.mx-marks{fill:var(--mx-mark)}

.art{display:block; margin:0 auto}
.art--dump{width:min(264px,72%); margin-bottom:24px}
/* The mascot is sized by width alone, so a wide-but-short window (a laptop
   at 1280x800) ran past the bottom of the screen. Below 880px tall, height
   gets a say; a taller window keeps the 264px cap exactly as before.
   Sits after the base rule on purpose: a media query adds no specificity. */
@media (min-width:820px) and (max-height:880px){
  .art--dump{width:min(264px,72%,24vh); margin-bottom:16px}
}
.art--think{width:200px; margin-bottom:20px}

/* ---------- brand ---------- */
/* The bar holds its place while the page scrolls under it. #app is the
   scroller, not the document, so sticky resolves against #app and the offset
   only has to clear the status bar — which is exactly --safe-top, the same
   length .screen pads by. */
.brand{
  position:sticky; top:var(--safe-top); z-index:20;
  display:flex; align-items:center; gap:10px;
  padding-bottom:10px;
}
.brand--sm{margin-bottom:12px}

/* The ground the rows pass behind. The bar is held to --measure, so a
   background on the bar itself would leave the gutters — and the strip up
   under the status bar — uncovered. This is one full-bleed panel instead,
   reaching from the top of the screen to the bottom of the bar. It sits at
   z-index -1 inside the bar's own stacking context: behind the lockup,
   still in front of the page. */
.brand::before{
  content:"";
  position:absolute; z-index:-1;
  left:50%; transform:translateX(-50%); width:100vw;
  top:calc(-1 * (var(--safe-top) + var(--brand-gap)));
  bottom:0;
  background:var(--surface);
}
/* The mark links out to the landing page, on both screens. A real <a>, not a
   button: this leaves the app, so it should open in a new tab on middle-click
   and offer a URL on hover like any other link. Relative, so it also works
   when index.html is opened straight off disk. */
/* .brand-lockup, .logo and .wordmark now live in theme.css */
.lg-pill{stroke:var(--violet)}
.brand .theme-toggle{margin-left:auto}

/* the toggle button itself is styled in theme.css */

/* ---------- screen 1: dump ---------- */
.dump-wrap{margin:auto 0; padding:26px 0 0}

.headline{
  font-family:var(--display);
  font-size:clamp(30px,7vw,40px); font-weight:800;
  letter-spacing:-.04em; line-height:1.06;
  text-align:center; margin-bottom:12px;
}

.dump-input{
  width:100%;
  background:var(--wash);
  border:1.5px solid var(--line);
  border-radius:var(--radius-lg);
  color:var(--ink);
  font:inherit; font-size:15.5px; line-height:1.7;
  padding:15px 18px;
  resize:vertical; min-height:112px;
  margin-bottom:22px;
  transition:border-color .2s var(--ease), background .2s var(--ease), box-shadow .2s var(--ease);
}
/* Same short-desktop squeeze as the mascot: four fewer lines of empty box
   so a returning user — who also carries the "View my lists" row — still
   lands the whole composer on a 768px-tall window. Placed after the base
   rule; a media query adds no specificity. */
@media (min-width:820px) and (max-height:880px){
  /* rows="4" sets the height, so min-height alone changes nothing */
  .dump-input{min-height:96px; height:112px}
}
.dump-input::placeholder{color:var(--faint); line-height:1.7}
.dump-input:focus{
  outline:none;
  background:var(--surface);
  border-color:var(--accent);
  box-shadow:0 0 0 4px var(--focus);
}

/* primary CTA — black pill with circular arrow, as in the reference */
.btn-primary{
  width:100%;
  display:flex; align-items:center; justify-content:center; gap:12px;
  background:var(--grad); border:none; border-radius:999px;
  color:#fff; font-family:var(--display);
  font-size:16.5px; font-weight:700; letter-spacing:-.01em;
  padding:17px 24px; cursor:pointer;
  transition:transform .16s var(--ease), opacity .18s var(--ease);
  box-shadow:0 16px 34px -16px rgba(71,55,255,.85);
}
.btn-arrow svg{width:19px; height:19px; display:block}
.btn-primary:hover{transform:translateY(-1px)}
.btn-primary:active{transform:translateY(0)}
.btn-primary:disabled{opacity:.4; cursor:not-allowed; transform:none}
.kbd{
  font:inherit; font-size:11px; font-weight:600;
  background:rgba(255,255,255,.14); padding:4px 8px; border-radius:6px;
  letter-spacing:.02em; display:none;
}
@media (min-width:520px){
  .kbd{display:inline-block}
}
/* the typing preview: what the app has already spotted a day in */
.dump-dates{
  /* The box already carries 22px of floor. The strip borrows the top half
     of it so it reads as attached to what was typed, and restores the rest
     underneath so the button keeps its breathing room. */
  margin-top:-10px; margin-bottom:20px;
  display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  animation:rise .22s var(--ease) both;
}
.dump-dates-label{
  flex:none; font-size:11.5px; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:var(--faint);
}
.dump-chips{display:flex; gap:6px; flex-wrap:wrap; min-width:0}
.dump-chips .chip--when{font-size:12.5px; padding:4px 11px}
.dump-more{font-size:12px; color:var(--faint); align-self:center}

.hint{margin-top:14px; font-size:13px; color:var(--faint); text-align:center}
.hint strong{color:var(--ink); font-weight:600}

/* shortcut from the dump box back into the lists */
.btn-lists{
  display:flex; align-items:center; justify-content:center; gap:9px;
  width:100%; margin-top:14px;
  background:var(--surface); border:1.5px solid var(--line-strong);
  color:var(--muted); font:inherit; font-family:var(--display);
  font-size:14.5px; font-weight:600;
  padding:12px; border-radius:999px; cursor:pointer;
  transition:all .18s var(--ease);
}
.btn-lists:hover{color:var(--accent); border-color:var(--accent); background:var(--wash)}
.btn-lists-count{
  min-width:21px; height:21px; padding:0 7px; border-radius:999px;
  background:var(--accent); color:var(--on-accent);
  font-size:12px; font-weight:700;
  display:grid; place-items:center;
}

/* ---------- screen 2: loading ---------- */
/* The wait is the logo mark morphing through its own states — eight arms
   changing length and radius, never added or removed, so it reads as one
   shape thinking rather than a spinner. 4s loop; the copy rotates at 1.9s
   underneath it, so the two never land together and the wait stays alive. */
.loading{margin:auto; text-align:center}
/* The mp4 carries its own ground, one render per theme, because H.264 has no
   alpha channel. It still cannot match --surface exactly: 8-bit yuv420 does
   not round-trip RGB, so #101018 comes back as #11111A and the frame reads as
   a faint square on the dark theme. One or two values out of 255 is invisible
   on its own — what gives it away is the hard edge — so the edge is feathered
   off. The mark itself reaches ~67% of the half-width, well inside the mask. */
.logo-morph{
  display:block; width:100%; height:auto;
  -webkit-mask-image:radial-gradient(closest-side,#000 74%,transparent 99%);
          mask-image:radial-gradient(closest-side,#000 74%,transparent 99%);
}
.loading-text{color:var(--muted); font-size:15px}

/* ---------- screen 3: now ---------- */
.now-wrap{margin:0; padding-top:clamp(18px,3vh,32px); padding-bottom:8px}
.eyebrow{
  font-size:11px; font-weight:700; letter-spacing:.13em; text-transform:uppercase;
  color:var(--faint); margin-bottom:12px;
}

@keyframes rise{from{opacity:0; transform:translateY(10px)} to{opacity:1; transform:none}}

.chip{
  font-size:12px; font-weight:500;
  background:var(--surface); border:1.5px solid var(--line-strong);
  color:var(--muted); padding:5px 12px; border-radius:999px;
  white-space:nowrap;
}
.chip--time{background:var(--accent); border-color:var(--accent); color:var(--on-accent); font-weight:600}
.chip--why{border-style:dashed; color:var(--faint)}

.first-step{
  background:var(--wash);
  border-left:3px solid var(--accent);
  border-radius:12px;
  padding:15px 17px; margin-bottom:20px;
}
.first-step-label{
  display:block; font-size:10.5px; font-weight:700; letter-spacing:.11em;
  text-transform:uppercase; color:var(--accent); margin-bottom:6px;
}
.first-step-text{font-size:15.5px; color:var(--ink-soft); line-height:1.55}

.steps-block{
  background:var(--wash); border-radius:12px;
  padding:15px 17px; margin-bottom:20px;
  border-left:3px solid var(--line-strong);
}
.steps-block .first-step-label{color:var(--muted)}
.steps{list-style:none; counter-reset:s}
.steps li{
  counter-increment:s;
  display:flex; gap:11px; align-items:flex-start;
  font-size:15px; color:var(--ink-soft); padding:7px 0;
}
.steps li::before{
  content:counter(s);
  flex:none; width:21px; height:21px; border-radius:50%;
  background:var(--accent); color:var(--on-accent);
  font-size:11px; font-weight:700;
  display:grid; place-items:center; margin-top:1px;
}

.btn-soft{
  flex:1 1 0; min-width:140px;
  background:var(--surface); border:1.5px solid var(--line-strong);
  color:var(--muted); font:inherit; font-size:14px; font-weight:500;
  padding:12px; border-radius:999px; cursor:pointer;
  transition:all .18s var(--ease);
}
.btn-soft:hover{color:var(--accent); border-color:var(--accent); background:var(--wash)}
.btn-soft:disabled{opacity:.45; cursor:not-allowed}

/* ---------- screen 3: the lists ----------
   The dump comes back grouped by category. Within a list: most urgent
   first, then shortest. Between lists: whichever holds the most urgent
   item leads. Detail stays collapsed so the lists stay scannable. */

.lists-summary{
  font-size:13.5px; color:var(--faint); margin-bottom:22px;
}

.lists{display:flex; flex-direction:column; gap:26px}

/* offline notice — the fallback should never be able to masquerade
   as the real analysis */
.offline-note{
  background:var(--wash);
  border:1.5px solid var(--line-strong);
  border-left:3px solid var(--orange);
  border-radius:14px;
  padding:14px 16px; margin-bottom:22px;
}
.offline-note p{font-size:13.5px; color:var(--ink-soft); line-height:1.55; margin-bottom:11px}
.offline-note strong{color:var(--orange); font-weight:700}
.offline-note .btn-soft{width:100%; min-width:0}

.list-group{animation:rise .18s var(--ease) both}
@keyframes rise{from{opacity:0; transform:translateY(10px)} to{opacity:1; transform:none}}

.list-head{
  display:flex; align-items:center; gap:9px;
  padding-bottom:10px; margin-bottom:10px;
  border-bottom:1.5px solid var(--line);
}
.list-name{
  font-family:var(--display); font-size:17px; font-weight:700;
  letter-spacing:-.02em; color:var(--ink);
}
.list-count{
  font-size:12px; font-weight:700; color:var(--muted);
  background:var(--wash); border-radius:999px;
  min-width:22px; height:22px; padding:0 7px;
  display:grid; place-items:center;
}

.list-items{list-style:none; display:flex; flex-direction:column; gap:8px}

.task{
  display:flex; gap:13px; align-items:flex-start;
  background:var(--surface); border:1.5px solid var(--line);
  border-radius:16px; padding:14px 16px;
  cursor:pointer;
  transition:border-color .18s var(--ease), background .18s var(--ease);
}
.task:hover{border-color:var(--line-strong)}
.task.is-open{border-color:var(--accent); background:var(--wash)}
.task--urgent{border-left:3px solid var(--orange)}

.task-check{
  flex:none; width:24px; height:24px; margin-top:1px;
  border-radius:50%; border:2px solid var(--line-strong);
  background:none; color:transparent; cursor:pointer;
  display:grid; place-items:center;
  transition:all .16s var(--ease);
}
.task-check svg{width:13px; height:13px}
.task-check:hover{border-color:var(--accent); color:var(--accent)}

.task-body{flex:1; min-width:0}
.task-title{
  font-size:15.5px; font-weight:600; color:var(--ink);
  line-height:1.35; letter-spacing:-.01em; margin-bottom:8px;
}
.task-meta{display:flex; gap:6px; flex-wrap:wrap}
.chip--urgent{
  background:var(--orange); border-color:var(--orange);
  color:#fff; font-weight:600;
}

.task-detail{margin-top:14px}
.task-detail .first-step{margin-bottom:12px}
.task-detail .steps-block{margin-bottom:12px}
.task-break{width:100%}

/* repair — edit and remove.
   Deliberately the quietest thing in the detail: they are the exits, not
   the offer. Sitting below the break-it-down button, which is the one the
   detail was opened for. */
.task-fix{display:flex; gap:8px; margin-top:10px}
.task-fix-btn{
  flex:1 1 0;
  background:none; border:none; cursor:pointer;
  font:inherit; font-size:13px; font-weight:600;
  color:var(--faint); padding:8px 6px; border-radius:999px;
  transition:color .18s var(--ease), background .18s var(--ease);
}
.task-fix-btn:hover{color:var(--accent); background:var(--wash)}
.task-fix-btn:focus-visible{outline:none; box-shadow:0 0 0 3px var(--wash-2)}
/* --danger is for the thing that cannot be undone; removing one task can,
   so this takes the softer --danger-ink and only on hover. */
.task-fix-btn--danger:hover{color:var(--danger-ink); background:var(--danger-wash)}
.task-fix-btn--danger:focus-visible{box-shadow:0 0 0 3px var(--danger-edge)}

/* The title, while it is being reworded. Sized and weighted exactly like
   the .task-title it replaces, so the row does not jump on either swap. */
.task-edit{
  display:block; width:100%;
  font:inherit; font-size:15.5px; font-weight:600; color:var(--ink);
  line-height:1.35; letter-spacing:-.01em;
  margin:-7px 0 1px; padding:6px 9px;
  background:var(--surface);
  border:1.5px solid var(--accent); border-radius:10px;
  outline:none;
}

/* done pile */
.done-block{margin-top:30px; padding-top:6px}
.done-list{list-style:none; margin-top:10px; display:flex; flex-direction:column; gap:7px}
.done-item{
  display:flex; align-items:center; gap:12px;
  background:var(--surface); border:1.5px solid var(--line);
  border-radius:14px; padding:11px 15px;
  font-size:14.5px; color:var(--faint);
}
.done-item .p-title{flex:1; min-width:0; text-decoration:line-through}

/* the tail of the pile — a count, not a row */
.done-note{
  font-size:12.5px; line-height:1.45; color:var(--faint);
  padding:2px 4px;
}

/* Undo. Orange because putting something back is the one move on this
   screen that reverses a decision — it should catch the eye without
   reading as destructive, which is what --danger is for. Sized to its
   word rather than left at the browser's default button metrics. */
.done-item .p-do{
  flex:none; background:none;
  border:1.5px solid var(--orange); border-radius:999px;
  color:var(--orange); font:inherit; font-size:12.5px; font-weight:700;
  line-height:1; letter-spacing:.01em;
  padding:6px 13px; cursor:pointer;
  transition:background .18s var(--ease), color .18s var(--ease), transform .12s var(--ease);
}
.done-item .p-do:active{transform:scale(.94)}
.done-item .p-do:focus-visible{outline:none; box-shadow:0 0 0 3px rgba(247,92,3,.28)}
@media (hover:hover){
  .done-item .p-do:hover{background:var(--orange); color:#FFFFFF}
}

/* clear everything — deliberately quiet until armed, then loud */
.danger-zone{margin-top:34px; padding-top:20px; border-top:1.5px solid var(--line)}

.btn-danger-quiet{
  background:none; border:none; cursor:pointer;
  font:inherit; font-size:13.5px; font-weight:600;
  color:var(--faint); padding:6px 0;
  transition:color .18s var(--ease);
}
.btn-danger-quiet:hover{color:var(--danger-ink)}

.clear-confirm{
  background:var(--wash); border:1.5px solid var(--line-strong);
  border-left:3px solid var(--danger-ink);
  border-radius:14px; padding:15px 17px;
  animation:rise .22s var(--ease) both;
}
.clear-confirm.is-final{
  background:var(--danger-wash);
  border-color:var(--danger-edge);
}
.clear-confirm-text{
  font-size:14px; line-height:1.55; color:var(--ink);
  margin-bottom:13px; font-weight:500;
}
.clear-confirm-actions{display:flex; gap:9px; flex-wrap:wrap}
.clear-confirm-actions .btn-soft{flex:1 1 0; min-width:110px}

.btn-danger{
  flex:1 1 0; min-width:130px;
  background:var(--danger); border:1.5px solid var(--danger);
  color:#fff; font:inherit; font-family:var(--display);
  font-size:14px; font-weight:700;
  padding:12px; border-radius:999px; cursor:pointer;
  transition:filter .18s var(--ease), transform .16s var(--ease);
}
.btn-danger:hover{filter:brightness(1.08); transform:translateY(-1px)}
.btn-danger:active{transform:translateY(0)}

/* leftover shared bits */
.parked-toggle{
  display:flex; align-items:center; gap:7px;
  background:none; border:none; cursor:pointer;
  color:var(--faint); font:inherit; font-size:13.5px; font-weight:600;
  padding:6px 0;
  transition:color .18s var(--ease);
}
.parked-toggle:hover{color:var(--accent)}
.chev{transition:transform .2s var(--ease); display:grid; place-items:center; width:14px; height:14px}
.chev svg{width:14px; height:14px}
.parked-toggle[aria-expanded="true"] .chev{transform:rotate(180deg)}


.cleared-note{
  text-align:center; color:var(--muted); font-size:15px;
  padding:40px 0;
}
.cleared-note strong{
  display:block; font-family:var(--display); color:var(--ink);
  font-size:20px; font-weight:700; letter-spacing:-.02em; margin-bottom:6px;
}
.link-btn{
  background:none; border:none; color:var(--accent);
  font:inherit; font-size:15px; font-weight:600;
  cursor:pointer; text-decoration:underline; text-underline-offset:3px;
  margin-top:8px;
}

/* toast */
.toast{
  position:fixed; left:50%; bottom:calc(26px + env(safe-area-inset-bottom, 0px)); transform:translateX(-50%);
  background:var(--toast-bg); border:none;
  color:var(--toast-ink); font-size:14px; font-weight:500;
  padding:12px 22px; border-radius:999px; z-index:50;
  box-shadow:0 18px 40px -16px rgba(16,16,24,.55);
  animation:toastIn .3s var(--ease) both;
  max-width:calc(100vw - 40px); text-align:center;
}
@keyframes toastIn{from{opacity:0; transform:translate(-50%,10px)} to{opacity:1; transform:translate(-50%,0)}}

/* A toast carrying an offer rather than a message: it holds an Undo, so
   it needs a row and a longer life (see toast() in app.js). */
.toast--action{
  display:flex; align-items:center; gap:14px;
  text-align:left; padding:10px 12px 10px 20px;
}
.toast-do{
  flex:none; background:none;
  border:1.5px solid currentColor; border-radius:999px;
  color:var(--toast-ink); font:inherit; font-size:12.5px; font-weight:700;
  line-height:1; letter-spacing:.01em;
  padding:7px 14px; cursor:pointer;
  transition:transform .12s var(--ease), opacity .18s var(--ease);
}
.toast-do:active{transform:scale(.94)}
.toast-do:hover{opacity:.75}
.toast-do:focus-visible{outline:none; box-shadow:0 0 0 3px rgba(255,255,255,.3)}


/* ---------- the floating tab bar ----------
   A pill that hovers over the page rather than sitting in a bar welded to
   the floor. It only appears past the dump screen: the dump is the one
   place where the whole screen is the job. Its own tokens, because the
   translucent ground has to survive both themes and no shared token
   carries alpha. */
:root{
  --tab-bg:rgba(255,255,255,.88);
  --tab-edge:rgba(16,16,24,.07);
  --tab-shadow:0 22px 46px -20px rgba(16,16,24,.42), 0 3px 10px -6px rgba(16,16,24,.22);
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --tab-bg:rgba(30,30,46,.90);
    --tab-edge:rgba(255,255,255,.09);
    --tab-shadow:0 22px 46px -20px rgba(0,0,0,.72), 0 3px 10px -6px rgba(0,0,0,.5);
  }
}
:root[data-theme="dark"]{
  --tab-bg:rgba(30,30,46,.90);
  --tab-edge:rgba(255,255,255,.09);
  --tab-shadow:0 22px 46px -20px rgba(0,0,0,.72), 0 3px 10px -6px rgba(0,0,0,.5);
}

.tabbar{
  position:fixed; z-index:45;
  /* Low, close to the home indicator rather than floating well above it.
     The inset reserves more room than the indicator actually occupies —
     it is a ~5pt bar sitting ~8pt off the floor — so the pill sits a
     little way into that strip and still clears it. max() keeps a sane
     gap on anything reporting no inset at all, like a desktop window. */
  bottom:max(8px, calc(env(safe-area-inset-bottom, 0px) - 4px));
  /* Stretched between the two edges rather than sized by its contents, so
     the five sections spread across the screen instead of huddling in the
     middle. left+right+auto margins keep it centred once the max-width
     starts binding on a desktop window. */
  left:calc(14px + env(safe-area-inset-left, 0px));
  right:calc(14px + env(safe-area-inset-right, 0px));
  max-width:440px; margin-inline:auto;
  display:flex; align-items:center;
  padding:7px 8px;
  background:var(--tab-bg);
  border:1.5px solid var(--tab-edge);
  border-radius:999px;
  box-shadow:var(--tab-shadow);
  -webkit-backdrop-filter:blur(16px) saturate(1.5);
  backdrop-filter:blur(16px) saturate(1.5);
  animation:tabIn .3s var(--ease) both;
}
@keyframes tabIn{from{opacity:0; transform:translateY(14px)} to{opacity:1; transform:translateY(0)}}

.tab{
  position:relative;
  flex:1 1 0; min-width:0; height:46px;
  display:grid; place-items:center;
  background:none; border:none; border-radius:15px;
  color:var(--muted); cursor:pointer; padding:0;
  /* The switch itself costs a few ms — what made it feel slow was waiting
     for it to be acknowledged, so the "you are here" slab lands in .12s
     rather than .18s. */
  transition:color .12s var(--ease), background .12s var(--ease), transform .16s var(--ease);
  /* no double-tap-zoom delay to sit through before the tap counts */
  touch-action:manipulation;
}
.tab svg{width:23px; height:23px; display:block}
/* The press dent is the receipt for the tap, so it has to be instant —
   easing it in over .12s meant the finger was already lifting before the
   button admitted it had been touched. It still eases back out on release,
   which is what the base transition above is for. */
.tab:active{transform:scale(.92); transition-duration:0s}
.tab:focus-visible{outline:none; box-shadow:0 0 0 3px var(--focus)}
@media (hover:hover){ .tab:hover{color:var(--ink)} }

/* the current section: the same soft slab the reference uses, not a colour */
.tab.is-on{background:var(--wash-2); color:var(--ink)}

/* ...and its glyph fills in, which is the reference's real "you are here"
   signal. --icon-fill is a custom property because it has to cross into
   the <use> shadow tree, and only inherited properties do that. The
   calendar is left outlined — a filled one is an unreadable slab. */
.tab{--icon-fill:none}
#tab-lists.is-on, #tab-loved.is-on{--icon-fill:currentColor}

/* the + never marks itself current — it is an action, not a place */
.tab--add{color:var(--ink)}

/* something waiting on the lists */
.tab-dot{
  position:absolute; top:8px; left:calc(50% + 7px);
  width:8px; height:8px; border-radius:50%;
  background:var(--accent);
  box-shadow:0 0 0 2.5px var(--surface);
}

/* the calendar's count. Sits where the dot sits, sized to its digits, and
   turns orange the moment any of what it counts is due or overdue — the
   number is the volume, the colour is the urgency. */
.tab-badge{
  position:absolute; top:5px; left:calc(50% + 4px);
  min-width:16px; height:16px; padding:0 4px;
  display:grid; place-items:center;
  border-radius:999px; background:var(--accent); color:var(--on-accent);
  font-size:10px; font-weight:800; line-height:1;
  font-variant-numeric:tabular-nums;
  box-shadow:0 0 0 2px var(--surface);
}
.tab-badge.is-late{background:var(--orange); color:#FFFFFF}

.tab-avatar{
  width:31px; height:31px; border-radius:50%;
  display:grid; place-items:center; font-size:17px; line-height:1;
  background:var(--wash-2); border:1.5px solid var(--line-strong);
  transition:border-color .18s var(--ease);
}
.tab--me.is-on{background:none}
.tab--me.is-on .tab-avatar{border-color:var(--accent); box-shadow:0 0 0 2px var(--focus)}

/* Room for the bar to hover over, rather than on top of, the last line of
   the page — and the toast has to clear it too. */
body.has-tabbar .screen{
  padding-bottom:calc(96px + env(safe-area-inset-bottom, 0px));
}
body.has-tabbar .toast{
  bottom:calc(88px + env(safe-area-inset-bottom, 0px));
}

/* ---------- feedback ---------- */
.fb-wrap{margin:0; padding-top:clamp(6px,1.5vh,18px)}

.fb-glyph{
  width:60px; height:60px; display:grid; place-items:center; margin:0 auto 18px;
  border-radius:22px; background:var(--wash); border:1.5px solid var(--line);
  color:var(--accent);
}
.fb-glyph svg{width:27px; height:27px; display:block}

.fb-title{
  font-size:clamp(25px,6vw,31px); font-weight:800; letter-spacing:-.03em;
  line-height:1.1; text-align:center; margin-bottom:12px;
}
.fb-lede{
  font-size:15px; color:var(--muted); line-height:1.6;
  text-align:center; max-width:38ch; margin:0 auto 26px;
}

.fb-input{
  width:100%; resize:vertical; min-height:130px;
  font-family:var(--display); font-size:16px; line-height:1.55; color:var(--ink);
  background:var(--wash); border:1.5px solid var(--line); border-radius:var(--radius-lg);
  padding:15px 16px;
  transition:border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.fb-input::placeholder{color:var(--faint)}
.fb-input:focus{outline:none; border-color:var(--accent); box-shadow:0 0 0 4px var(--focus)}

.fb-foot{display:flex; align-items:center; gap:12px; margin-top:14px}
.fb-count{
  flex:1; font-size:12.5px; color:var(--faint);
  font-variant-numeric:tabular-nums;
}
.fb-send{width:auto; flex:none; margin-top:0; padding-left:26px; padding-right:26px}

.fb-note{
  margin-top:20px; padding-top:16px; border-top:1.5px solid var(--line);
  font-size:13px; color:var(--faint); line-height:1.6;
}
.fb-note strong{color:var(--ink); font-weight:700}

.fb-thanks{
  text-align:center; padding:34px 16px;
  background:var(--wash); border:1.5px solid var(--line);
  border-radius:var(--radius-card);
}
.fb-thanks-title{font-size:20px; font-weight:800; letter-spacing:-.02em; margin-bottom:8px}
.fb-thanks-text{font-size:14.5px; color:var(--muted); line-height:1.6; max-width:34ch; margin:0 auto}

/* ---------- the calendar ----------
   A month for orientation, an agenda for reading. The grid is deliberately
   quiet: a dot is enough to say "something is on this day", and the detail
   lives underneath where there is room for it. */
.cal-wrap{margin:0; padding-top:clamp(6px,1.5vh,16px)}

.cal-head{display:flex; align-items:center; gap:8px; margin-bottom:16px}
.cal-month{
  flex:1; text-align:center;
  font-size:19px; font-weight:800; letter-spacing:-.02em;
}
.cal-nav{
  flex:none; width:38px; height:38px; display:grid; place-items:center;
  background:none; border:1.5px solid var(--line-strong); border-radius:999px;
  color:var(--muted); cursor:pointer; padding:0;
  transition:color .18s var(--ease), border-color .18s var(--ease), background .18s var(--ease);
}
.cal-nav svg{width:17px; height:17px; display:block}
.cal-nav:focus-visible{outline:none; border-color:var(--accent); box-shadow:0 0 0 4px var(--focus)}
@media (hover:hover){ .cal-nav:hover{color:var(--accent); border-color:var(--accent); background:var(--wash)} }

.cal-dow,
.cal-grid{display:grid; grid-template-columns:repeat(7,1fr); gap:3px}
.cal-dow{margin-bottom:6px}
.cal-dow span{
  text-align:center; font-size:11.5px; font-weight:700;
  color:var(--faint); letter-spacing:.06em;
}

.cal-day{
  position:relative;
  aspect-ratio:1; width:100%; max-height:48px;
  display:grid; place-items:center;
  background:none; border:1.5px solid transparent; border-radius:13px;
  font-family:var(--display); font-size:14.5px; font-weight:600;
  color:var(--ink-soft); cursor:pointer; padding:0;
  transition:background .16s var(--ease), border-color .16s var(--ease), color .16s var(--ease);
}
.cal-day.is-blank{pointer-events:none}
.cal-day:focus-visible{outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--focus)}
@media (hover:hover){ .cal-day:not(.is-blank):hover{background:var(--wash)} }

/* today is outlined, the picked day is filled — so both can show at once */
.cal-day.is-today{border-color:var(--line-strong); color:var(--ink); font-weight:800}
.cal-day.is-picked{background:var(--accent); border-color:var(--accent); color:var(--on-accent); font-weight:800}

.cal-dot{
  position:absolute; bottom:6px; left:50%; transform:translateX(-50%);
  width:5px; height:5px; border-radius:50%; background:var(--accent);
}
.cal-day.is-late .cal-dot{background:var(--orange)}
.cal-day.is-picked .cal-dot{background:var(--on-accent)}

/* the earliest time that day, in the dot's place. Out of flow so the date
   stays optically centred whether or not there is a time under it. */
.cal-time{
  position:absolute; bottom:3px; left:0; right:0;
  /* The widest label ("12.30pm") is what sizes this: at a fixed 9px it
     clips by a hair once the cells drop under ~40px on a 320px phone. */
  font-size:clamp(8px, 2.4vw, 9px);
  font-weight:700; line-height:1; letter-spacing:-.02em;
  color:var(--accent); font-variant-numeric:tabular-nums;
  white-space:nowrap; overflow:hidden;
}
.cal-day.is-late .cal-time{color:var(--orange)}
.cal-day.is-picked .cal-time{color:var(--on-accent)}

.cal-today{
  display:block; margin:14px auto 0;
  background:none; border:none; padding:4px 8px;
  font-family:var(--display); font-size:13.5px; font-weight:600;
  color:var(--accent); cursor:pointer;
  text-decoration:underline; text-underline-offset:3px;
}

.cal-tip{
  margin-top:20px; font-size:12.5px; color:var(--faint); text-align:center;
}

.cal-agenda{margin-top:14px; display:flex; flex-direction:column; gap:22px}

/* ---- dragging a row onto a day ---- */
.cal-item{
  cursor:grab;
  transition:opacity .18s var(--ease), transform .14s var(--ease);
}
.cal-item.is-pressed{transform:scale(.985)}
/* the row stays in place, faded, so the list does not reflow under the hand */
.cal-item.is-lifted{opacity:.3}

.cal-ghost{
  position:fixed; z-index:60; margin:0;
  pointer-events:none;          /* so elementFromPoint sees the cell beneath */
  max-width:min(230px, 62vw);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  background:var(--surface);
  border:1.5px solid var(--accent); border-radius:999px;
  padding:9px 15px;
  font-family:var(--display); font-size:13.5px; font-weight:600; color:var(--ink);
  box-shadow:0 18px 36px -12px rgba(16,16,24,.6);
  transform:rotate(-1.2deg);
}

/* A ring rather than a fill, so it reads on a plain cell and on the
   selected one, which is already carrying the accent as its background. */
.cal-day.is-drop{
  box-shadow:0 0 0 3px var(--accent);
  transform:scale(1.08);
}

body.is-dragging{cursor:grabbing}
body.is-dragging *{user-select:none; -webkit-user-select:none}

.cal-group{animation:rise .18s var(--ease) both}
.cal-group-head{
  font-size:13px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--muted); margin-bottom:10px;
  padding-bottom:9px; border-bottom:1.5px solid var(--line);
}
.cal-group--late .cal-group-head{color:var(--orange); border-bottom-color:var(--orange)}

.cal-items{list-style:none; display:flex; flex-direction:column; gap:8px}
.cal-item{
  display:flex; align-items:flex-start; gap:11px;
  border:1.5px solid var(--line); border-radius:var(--radius-lg);
  padding:13px 15px;
}
.cal-group--late .cal-item{border-left:3px solid var(--orange)}

/* the time column: fixed width so every title starts on the same line */
.cal-slot{
  flex:none; width:62px; padding-top:1px;
  font-size:13.5px; font-weight:700; color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.cal-slot.is-loose{color:var(--faint); font-weight:600}

.cal-item-body{flex:1; min-width:0}
.cal-item-title{font-size:15px; font-weight:600; line-height:1.35}
.cal-item-meta{margin-top:3px; font-size:12.5px; color:var(--faint)}

.cal-empty{
  font-size:14.5px; color:var(--muted); line-height:1.6;
  text-align:center; padding:26px 10px;
}
.cal-undated{
  margin-top:24px; padding-top:16px; border-top:1.5px solid var(--line);
  font-size:13px; color:var(--faint); line-height:1.55;
}

/* the day stamp on a task card, over on the lists screen */
.chip--when{border-style:solid; color:var(--ink-soft); font-weight:600}
.chip--when.is-late{color:var(--orange); border-color:var(--orange)}

/* ---------- profile ---------- */
.profile-wrap{margin:0; padding-top:clamp(10px,2vh,22px)}

.profile-card{
  display:flex; flex-direction:column; align-items:center;
  background:var(--wash); border:1.5px solid var(--line);
  border-radius:var(--radius-card); padding:28px 22px 24px;
}
.avatar-big{
  width:78px; height:78px; border-radius:50%;
  display:grid; place-items:center; font-size:42px; line-height:1;
  background:var(--surface); border:1.5px solid var(--line-strong);
}
.profile-name-big{
  margin-top:14px; font-size:22px; font-weight:800; letter-spacing:-.02em;
}

.field{display:block; width:100%; margin-top:22px}
.field-label{
  display:block; font-size:12.5px; font-weight:600; color:var(--muted);
  margin-bottom:8px;
}
.field-input{
  width:100%; font-family:var(--display); font-size:16px; color:var(--ink);
  background:var(--surface); border:1.5px solid var(--line-strong);
  border-radius:var(--radius); padding:12px 14px;
  transition:border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.field-input::placeholder{color:var(--faint)}
.field-input:focus{outline:none; border-color:var(--accent); box-shadow:0 0 0 4px var(--focus)}

.avatar-picker{display:flex; flex-wrap:wrap; gap:8px}
.avatar-opt{
  width:44px; height:44px; border-radius:14px;
  display:grid; place-items:center; font-size:22px; line-height:1;
  background:var(--surface); border:1.5px solid var(--line-strong);
  cursor:pointer; padding:0;
  transition:border-color .18s var(--ease), transform .12s var(--ease), box-shadow .18s var(--ease);
}
.avatar-opt:active{transform:scale(.93)}
.avatar-opt:focus-visible{outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--focus)}
@media (hover:hover){ .avatar-opt:hover{border-color:var(--accent)} }
.avatar-opt.is-on{border-color:var(--accent); box-shadow:0 0 0 3px var(--focus)}

/* A fourth stat will not sit in one row on a phone without squeezing the
   labels to shreds, so the row is a grid that folds to 2x2 when the cards
   would go under 140px, and lines all four up once there is room. */
.stat-row{
  display:grid; gap:10px; margin-top:18px;
  grid-template-columns:repeat(auto-fit, minmax(min(140px, 100%), 1fr));
}
.stat{
  text-align:center;
  border:1.5px solid var(--line); border-radius:var(--radius-lg);
  padding:16px 8px;
}
/* Overdue takes the whole row: it is the odd one out of five, and it is
   the only card here that is ever bad news, so it reads better as its own
   line than as a stray fifth tile with a hole beside it. */
.stat--overdue{grid-column:1 / -1}
.stat--overdue.is-late{border-color:var(--orange); background:var(--danger-wash)}
.stat--overdue.is-late strong{color:var(--orange)}

.stat strong{display:block; font-size:26px; font-weight:800; letter-spacing:-.03em; line-height:1.1}
.stat span{display:block; margin-top:4px; font-size:12.5px; color:var(--faint)}

.profile-wrap .hint{margin-top:18px}
/* The policy link sits directly under the hint it qualifies, so it gets a
   tighter gap than the hint's own — they read as one block. */
.hint--link{margin-top:6px}
.hint--link a{color:var(--muted); text-underline-offset:2px}
.hint--link a:hover{color:var(--accent)}


/* ---------- the Google Calendar card ----------
   Deliberately quieter than the profile card above it: it is a setting,
   not the subject of the screen. It only earns the accent border once it
   is actually linked, and the amber only when it needs a hand. */

.gcal-card{
  margin-top:18px; padding:20px 18px;
  background:var(--surface); border:1.5px solid var(--line);
  border-radius:var(--radius-card);
  transition:border-color .22s var(--ease), background .22s var(--ease);
}
.gcal-card.is-on{border-color:var(--line-strong); background:var(--wash)}
.gcal-card.is-stale{border-color:var(--orange); background:var(--danger-wash)}

.gcal-head{display:flex; align-items:center; gap:12px}
.gcal-mark{
  width:34px; height:34px; flex:none; padding:6px;
  border-radius:12px; color:var(--accent);
  background:var(--wash); border:1.5px solid var(--line-strong);
}
.gcal-card.is-on .gcal-mark{background:var(--surface)}
.gcal-card.is-stale .gcal-mark{color:var(--orange); border-color:var(--orange)}

.gcal-title{font-size:15.5px; font-weight:700; letter-spacing:-.015em; line-height:1.2}
.gcal-state{margin-top:2px; font-size:12.5px; font-weight:600; color:var(--faint)}
.gcal-card.is-on .gcal-state{color:var(--accent)}
.gcal-card.is-stale .gcal-state{color:var(--orange)}

.gcal-note{margin-top:12px; font-size:13.5px; line-height:1.5; color:var(--muted)}

/* Narrower than the full-bleed primary on the dump screen — this is a
   settings action, and a button the width of the phone reads like the
   point of the page. */
.gcal-go{margin-top:16px; font-size:15px; padding:13px 20px}

.gcal-more{
  display:flex; align-items:center; justify-content:space-between;
  gap:12px; margin-top:12px;
}
.gcal-more:empty{display:none}
.gcal-more .btn-soft{flex:0 1 auto; min-width:0; padding:9px 16px; font-size:13.5px}
.gcal-more .is-hidden{display:none}

/* ---------- night: the same monochrome, inverted ---------- */

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important; transition-duration:.01ms !important}
}

/* ---------- the composer ----------
   The + opens this over whatever is on screen. Anchored to the top rather
   than centred, because the keyboard takes the bottom half the moment it
   opens — the input has to already be up where the eye is, not slide out
   from under a keyboard. Nothing here reaches below the fold on purpose. */
.composer{position:fixed; inset:0; z-index:70}

.composer-scrim{
  position:absolute; inset:0;
  background:rgba(16,16,24,.42);
  animation:scrimIn .38s var(--ease) both;
  /* same reasoning as the sheet: its own layer before the drag, not during */
  will-change:opacity;
}
/* dragging thins it out in step with the sheet, so the page behind comes
   back as the sheet leaves rather than all at once at the end */
.composer.is-dragging .composer-scrim{animation:none}
@keyframes scrimIn{from{opacity:0} to{opacity:1}}

.composer-sheet{
  position:absolute; left:0; right:0;
  /* just clear of the status bar, so the screen underneath still shows as a
     sliver and the sheet reads as sitting on top of it */
  top:calc(env(safe-area-inset-top, 0px) + 10px);
  bottom:0;
  display:flex; flex-direction:column;
  background:var(--surface);
  border-radius:22px 22px 0 0;
  /* On a dark page the sheet and the screen behind it are the same value,
     and a shadow alone does not separate them — the hairline does. */
  border-top:1.5px solid var(--line);
  box-shadow:0 -12px 40px -12px rgba(16,16,24,.45);
  overflow:hidden;
  /* Promoted while the sheet exists at all, not once a finger lands on it.
     Building the layer costs a frame, and asking for it on the first
     pointermove spent that frame in the middle of the gesture — the sheet
     sat still, then caught up. The whole composer is display:none when it
     is closed, so there is no layer to hold in the meantime. */
  will-change:transform;
}
/* Comes up from below the screen rather than fading in place. The curve is
   the one iOS uses for a sheet: almost all of the travel is spent slowing
   down, which is what makes it feel like it was thrown rather than played.

   On its own class, not on .composer-sheet, and taken off again the moment
   it has played. Held on the base rule it had to be suppressed with
   animation:none by every other state, and the moment one of those was
   removed — a spring-back finishing, say — the entrance would start over and
   the sheet would drop away and fly back up. */
.composer-sheet.is-entering{animation:sheetUp .38s cubic-bezier(.32,.72,0,1) both}
@keyframes sheetUp{from{transform:translateY(100%)} to{transform:translateY(0)}}

/* While a finger is on it: no transition, the sheet is pinned to the
   pointer. On release one of the two below takes over. */
.composer-sheet.is-dragging{transition:none}

/* The transform itself is written inline by closeComposer, over the drag's
   own inline one — a rule here could never win against the style attribute.
   This owns the curve; the duration is set inline too, from how far the
   sheet still has to fall and how fast it was going when it was let go. */

/* No transitions on either of these: the sheet and the scrim are moved by
   script, with the Web Animations API, so that a release can start from
   wherever the finger left them. See slideSheet in app.js. */
/* The bar has nothing to scroll, ever, so it never has to arbitrate. The
   body's is set live in syncComposer — pan-y only while its content really
   does overflow. */
.composer-bar{touch-action:none}

.composer-bar{
  flex:none;
  display:grid; grid-template-columns:1fr auto 1fr; align-items:center; gap:10px;
  padding:14px clamp(16px,4vw,22px);
  border-bottom:1.5px solid var(--line);
}
.composer-title{font-size:16px; font-weight:800; letter-spacing:-.02em; text-align:center}

.composer-cancel{
  justify-self:start;
  background:none; border:none; padding:6px 2px;
  font-family:var(--display); font-size:15px; font-weight:600;
  color:var(--ink); cursor:pointer; touch-action:manipulation;
}
.composer-cancel:active{transform:scale(.96); transition-duration:0s}

.composer-post{
  justify-self:end;
  background:var(--grad); color:#fff;
  border:none; border-radius:999px; padding:9px 20px;
  font-family:var(--display); font-size:14.5px; font-weight:700;
  cursor:pointer; touch-action:manipulation;
  transition:opacity .14s var(--ease), transform .16s var(--ease);
}
.composer-post:active{transform:scale(.96); transition-duration:0s}
/* Dimmed rather than hidden — the button is the thing you are working
   towards, so it should be visible before it is usable. */
.composer-post:disabled{opacity:.4; cursor:default}
.composer-cancel:focus-visible,
.composer-post:focus-visible{outline:none; box-shadow:0 0 0 3px var(--focus)}

.composer-body{
  flex:1 1 auto; min-height:0; overflow-y:auto;
  /* a scroll that runs off the end stays here rather than moving the list
     the sheet is covering */
  overscroll-behavior:contain;
  display:flex; gap:12px;
  padding:16px clamp(16px,4vw,22px) 24px;
}
.composer-face{
  flex:none; width:38px; height:38px; border-radius:999px;
  display:grid; place-items:center; font-size:21px; line-height:1;
  background:var(--wash-2);
}
.composer-field{flex:1 1 auto; min-width:0}
.composer-name{
  display:block; font-size:14.5px; font-weight:700; color:var(--ink);
  margin-bottom:2px;
}
.composer-input{
  display:block; width:100%; resize:none;
  background:none; border:none; padding:0;
  font-family:var(--display); font-size:16.5px; line-height:1.45; color:var(--ink);
  /* grown to fit by script; this is the floor, about one line */
  min-height:26px;
}
.composer-input:focus{outline:none}
.composer-input::placeholder{color:var(--faint)}
.composer .dump-dates{margin-top:16px}

/* Someone who has asked for less movement gets the sheet without the
   journey — it is still a sheet, it just does not fly. */
@media (prefers-reduced-motion:reduce){
  .composer-sheet.is-entering{animation:none}
  .composer-scrim{animation:none}
  /* the leaving and settling moves are script's, and check the same
     preference themselves — see stillMotion in app.js */
}

/* The tab bar blurs whatever is behind it, and a backdrop filter is redrawn
   whenever that backdrop changes — so dragging the sheet across it made the
   browser re-blur the width of the screen on every frame of the gesture, for
   a bar the sheet is covering anyway. Nothing to see, all of the cost. */
body.is-composing .tabbar{
  -webkit-backdrop-filter:none;
  backdrop-filter:none;
}
