/* ============================================================
   layout.css
   The shell every signed in page shares, and the layout of the
   four public pages. Needs tokens.css and parts.css.
   ============================================================ */

/* ---------- the One bar shell (round 04) ----------
   Mark, sections and account in a single bar. The section you are
   in gets a rule under it. On a phone the sections drop to a
   scrolling row. */
.bar{position:sticky;top:0;z-index:5;background:var(--paper);
  box-shadow:inset 0 calc(var(--hairline) * -1) 0 var(--rule)}
.bar-in{max-width:var(--measure-page);margin:0 auto;padding:0 var(--s6);
  display:flex;align-items:stretch;gap:var(--s7);height:var(--bar-h)}
.mark{font-family:var(--f-display);font-size:var(--t-wordmark-bar);font-weight:600;
  letter-spacing:var(--tr-tight);text-decoration:none;white-space:nowrap;align-self:center}
.sections{display:flex;align-items:stretch;gap:var(--s6);height:100%}
/* `button.navlink`: it is a button, not a link, because sign out is
   a POST, but it must not look different from the navigation
   links. */
button.navlink{background:none;border:0;padding:0;cursor:pointer}
.navlink{font-family:var(--f-ui);font-size:var(--t-ui);font-weight:500;
  text-decoration:none;color:var(--muted);white-space:nowrap;
  position:relative;display:flex;align-items:center;
  transition:color var(--dur) var(--ease)}
.navlink:hover{color:var(--ink)}
.navlink.is-on{color:var(--ink)}
.navlink.is-on::after{content:"";position:absolute;left:0;right:0;bottom:0;
  height:var(--mark-rule-w);background:var(--accent)}
.account{display:flex;align-items:center;gap:var(--s3);flex:none;
  margin-left:auto;align-self:center}
/* `text-decoration:none`: because it is an <a>, the browser was
   underlining the letters, and the avatar looked like a link. */
.avatar{font-family:var(--f-ui);font-size:var(--t-micro);font-weight:600;letter-spacing:var(--tr-wide);
  width:var(--avatar-size);height:var(--avatar-size);border-radius:50%;background:var(--well);
  display:flex;align-items:center;justify-content:center;color:var(--muted);
  text-decoration:none;transition:color var(--dur) var(--ease)}
.avatar:hover{color:var(--ink)}

/* The plan badge in the top bar has no background. A badge's shape
   is for MAKING SOMETHING STAND OUT; nothing in the top bar should
   stand out. The "Most chosen" badge on the pricing page, however,
   should stay filled -- that is its job there. */
.account .badge{background:none;padding:0;color:var(--muted);
  text-decoration:none;transition:color var(--dur) var(--ease)}
.account .badge:hover{color:var(--ink)}

.col{max-width:var(--measure-page);margin:0 auto;padding:var(--s6) var(--s6) var(--s9)}
.stack{display:flex;flex-direction:column;gap:var(--s5)}

/* ---------- toasts ----------
   Messages after an action. Top right, without blocking the work.

   WITHOUT a script, it falls back to `position:static` and sits as
   a normal strip at the top of the page: the message does not
   disappear, it just does not leave on its own. The `.js` class is
   set by the one-line script in base.html. */
.toasts{display:flex;flex-direction:column;gap:var(--s3);
  margin:0 auto var(--s5);max-width:var(--measure-page);padding:0 var(--s6)}
.js .toasts{position:fixed;top:var(--s5);right:var(--s5);left:auto;
  z-index:60;margin:0;padding:0;max-width:min(var(--measure-toast),var(--measure-overlay-w))}

.toast{display:flex;align-items:center;gap:var(--s3);
  padding:var(--s3) var(--s4);border-radius:var(--r-md);
  background:var(--surface);box-shadow:var(--shadow-lift);
  font-family:var(--f-ui);font-size:var(--t-ui)}
.toast p{margin:0;flex:1}
.toast--bad{background:var(--miss-wash);color:var(--miss)}
.toast a{font-family:var(--f-ui);font-size:var(--t-small);color:inherit;
  text-decoration:none;flex:none;font-weight:600}
.toast-x{background:none;border:0;padding:0 var(--toast-x-pad);cursor:pointer;flex:none;
  font:400 var(--t-toast-x)/1 var(--f-ui);color:inherit;opacity:.5;
  transition:opacity var(--dur) var(--ease)}
.toast-x:hover{opacity:1}
/* The exit state. The motion itself is in motion.css: when turned
   off, the toast leaves instantly but it still leaves. It returns
   the way it came. */
.toast.is-going{opacity:0;transform:translateY(var(--off-toast))}

/* The number next to a navigation link. Not a badge, because a
   badge is for MAKING SOMETHING STAND OUT and nothing in the top
   bar should stand out; this is just a number saying "there is
   something waiting here". */
.navlink-n{font-family:var(--f-ui);font-size:var(--t-micro);font-weight:600;
  line-height:1;margin-left:var(--navlink-badge-gap);padding:var(--navlink-badge-pad-y) var(--navlink-badge-gap);border-radius:var(--r-pill);
  background:var(--mark);color:var(--on-mark);
  font-variant-numeric:tabular-nums}

/* ---------- conversation screen ----------
   Full height below the top bar: only the message list scrolls,
   the title and composer stay put. Left in normal page flow, the
   title would drift up in a long conversation, and reaching the
   composer would mean scrolling all the way down every time.

   `100dvh`, NOT `100vh`: a mobile browser's address bar makes `vh`
   bigger than the visible area, and the composer overflows off the
   bottom of the screen. `vh` is written first, so a browser without
   support stays on that.

   WARNING: `height`, NOT `min-height`. In the first version this
   was `min-height:100dvh` and the WHOLE PAGE scrolled: `min-height`
   is a FLOOR, not a cap. When content grows, body grows with it,
   the growth passes through `main` and `.chat` into the 1fr row,
   and that row opens up to fit its content -- meaning
   `.chat-log`'s `overflow-y:auto` never kicks in. For inner
   scrolling, the container's height has to be FIXED.

   `overflow:hidden` is part of this too: even with a fixed height,
   a single overflowing element (a long address, a wide attachment)
   would still make the page scrollable.

   `min-height:0` is needed on the WHOLE CHAIN: flex and grid items
   shrink to fit their content by default, so if even one is
   skipped, the height still does not reach the inner scroller. */
body.is-chat{display:flex;flex-direction:column;
  height:var(--viewport-h);height:100dvh;overflow:hidden}
/* The gutter stays reserved here too, empty as it is. Dropping it made
   the bar's rule reach the right edge, but it also moved the whole bar
   half a scrollbar sideways every time a conversation was opened or
   left -- the one thing that must not move between pages. */
body.is-chat main{flex:1;min-height:0;display:flex}
/* `minmax(0,1fr)`: the implicit column was as wide as its longest
   unbreakable line, and "Also send this as an email to <address>" made
   the whole conversation a few pixels wider than a phone. */
.chat{flex:1;min-width:0;min-height:0;width:100%;max-width:var(--measure-chat-max);margin:0 auto;
  padding:0 var(--s6);display:grid;grid-template-columns:minmax(0,1fr);
  grid-template-rows:auto minmax(0,1fr) auto}
.chat-head{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s4);flex-wrap:wrap;padding:var(--s5) 0 var(--s4);
  box-shadow:inset 0 calc(var(--hairline) * -1) 0 var(--rule)}
.chat-title{font-family:var(--f-display);font-size:var(--t-chat-title);font-weight:600;
  line-height:1.2;letter-spacing:var(--tr-tight);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-who{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  margin-top:var(--gap-tight)}
/* Horizontal padding: bubbles do not STICK to the edge of the
   column. Without it, a left-aligned bubble's left edge sat in
   exactly the same spot as the container's left edge, and the
   conversation looked like it was spilling off the edge of the
   page. The scrollbar stays inside this padding too. */
.chat-log{overflow-y:auto;overscroll-behavior:contain;
  padding:var(--s5) var(--s4);display:flex;flex-direction:column;gap:var(--s5);
  /* The bar is FAINT. The default made it the darkest thing next
     to the conversation; but what is meant to be read here is the
     messages, not the bar. `--rule` is the system's lightest line,
     and it sharpens a little on hover -- so it can be found when it
     is needed. */
  scrollbar-width:thin;scrollbar-color:var(--rule) transparent}
.chat-log::-webkit-scrollbar{width:var(--scrollbar-w)}
.chat-log::-webkit-scrollbar-track{background:transparent}
.chat-log::-webkit-scrollbar-thumb{background:var(--rule);
  border-radius:var(--r-pill);border:var(--scrollbar-thumb-inset) solid transparent;
  background-clip:content-box}
.chat-log:hover::-webkit-scrollbar-thumb{background:var(--rule-firm);
  background-clip:content-box}
/* The conversation sits at the bottom even WHEN SHORT: a
   five-message exchange left hanging at the top of the screen, with
   empty space between it and the composer, looks abandoned. */
.chat-log > .thread{margin-top:auto}
.chat-foot{padding-bottom:var(--s5)}

/* ---------- mail composer ----------
   Form on the left, the mail itself on the right. The preview is
   STICKY: it stays on screen even while writing a long message. If
   it sat below, seeing it would mean scrolling every time -- and
   then being "live" would mean nothing.

   `minmax(0,...)` on both columns: without it a long address or a
   wide table column grows to fit its content and the grid
   overflows. */
.compose{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--s6);align-items:start}
.preview{position:sticky;top:var(--s5);display:flex;flex-direction:column;
  gap:var(--s3);min-width:0}
.preview-top{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s4)}
.preview-switch{display:flex;gap:var(--s4);flex-wrap:wrap}
.preview-en{display:flex;gap:var(--s2)}
/* The selected width button: on top of `.btn--quiet`, without
   switching to the filled state. Same as in the top bar -- what
   should stand out here is the mail, not the control. */
.preview-en .btn.is-on{background:var(--mark);color:var(--on-mark)}
/* The frame has its OWN ground: the mail sits in its own document
   and its own colours, independent of the panel's theme. The mail
   stays light even in dark theme -- that is how it will actually
   look. */
.preview-box{background:var(--well);border-radius:var(--r-lg);
  padding:var(--s3);display:flex;flex-direction:column;align-items:center;
  gap:var(--s3);overflow-x:auto}
/* The part visible in an inbox: from, subject, the grey line next
   to the subject. Just as much as the mail's body, these are part
   of "what will be sent" -- and they are the only thing seen before
   it is opened. */
.preview-head{width:100%;max-width:var(--measure-mail-frame-w);display:flex;flex-direction:column;
  gap:var(--gap-tight);font-family:var(--f-ui);padding:0 var(--s1)}
.preview-from{font-size:var(--t-small);font-weight:600}
.preview-from span{font-weight:400;color:var(--muted)}
.preview-subject{font-size:var(--t-ui);font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.preview-line{font-size:var(--t-small);color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-height:var(--measure-preview-line)}
/* The background is NOT set here. It used to say `#faf9f7`, and
   while showing the mail's dark version, a white frame stayed
   around the edges. The mail's colour is decided by the mail
   ITSELF -- which is exactly what is supposed to be shown. */
.preview-frame{border:0;border-radius:var(--r-md);
  height:var(--measure-mail-frame-h);width:var(--measure-mail-frame-w);max-width:100%;flex:none;
  color-scheme:light dark}
/* A preview that cannot be refreshed: what is on screen is no
   longer the same as what is written, and that needs to be SAID.
   Showing the wrong thing is worse than showing nothing. */
.preview.is-stale .preview-box{opacity:.5}
.preview.is-stale [data-preview-status]{color:var(--miss)}
/* `[hidden]` DOES NOT WORK here on its own: an author stylesheet's
   `display` always beats the browser's own `[hidden]{display:none}`
   rule. If hiding is needed, the rule has to be written explicitly. */
.preview[hidden]{display:none}

@media (max-width:980px){
  .compose{grid-template-columns:1fr;gap:var(--s5)}
  /* Once stacked, stickiness no longer means anything: the preview
     sits under the form, in normal flow. */
  .preview{position:static}
  .preview-frame{height:var(--measure-mail-frame-h-sm)}
}

/* ---------- second-tier bar ----------
   The admin panel's tabs. Because it sits outside `main`, it does
   not fade on page transitions: the tabs stay in place, only the
   marked one changes -- which is the only thing that needs to
   change anyway. */
.subbar{max-width:var(--measure-page);margin:0 auto;padding:var(--s5) var(--s6) 0}

/* ---------- page header ---------- */
.page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s5);
  flex-wrap:wrap}
.page-date{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  margin-bottom:var(--s1)}
.page-title{font-family:var(--f-display);font-size:var(--t-page-title);font-weight:600;
  line-height:1.1;letter-spacing:var(--tr-tight-lg)}
.page-actions{display:flex;gap:var(--s2);flex:none;flex-wrap:wrap}

/* ---------- dashboard: work first (round 06) ----------
   Nothing stands between the bar and the thing you came to do.
   Plan and history sit under the work in a quiet band. */
.under{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--s6);
  align-items:start;padding-top:var(--s5);box-shadow:inset 0 var(--hairline) 0 var(--rule)}
.status{display:flex;align-items:center;justify-content:space-between;gap:var(--s5);
  background:var(--surface);border-radius:var(--r-lg);padding:var(--s4) var(--s5);
  flex-wrap:wrap}
.status-main{display:flex;flex-direction:column;gap:var(--s2);min-width:0;flex:1}
.status-plan{display:flex;align-items:center;gap:var(--s3);
  font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted)}
.status-usage{font-family:var(--f-ui);font-size:var(--t-ui);font-weight:600}
.log{display:flex;flex-direction:column;gap:var(--s3)}
.log ul{display:flex;flex-direction:column;gap:var(--s1)}
.log li{display:flex;gap:var(--s4);font-family:var(--f-ui);font-size:var(--t-small);
  padding:var(--s2) 0}
.log-time{color:var(--muted);flex:none;width:var(--measure-log-time)}

/* ---------- landing: split (round 03) ---------- */
/* `.wrap` owns the side gutter and nothing below it may touch the
   sides. The bands used to set `padding: X 0`, which zeroed the gutter
   on a wide screen (the bar, the outcome band and the plan strip sat
   32px left of the hero and the footer), while the phone rule
   `padding: 0 s5` zeroed the vertical instead (the bar touched the top
   of the screen and the bands had no air). Block and inline are now
   set separately. */
.wrap{max-width:var(--measure-wrap);margin:0 auto;padding-inline:var(--s6)}
.wrap-top{padding-block:var(--s5)}
/* ---------- landing (round 12, 2026-10-06) ----------
   The claim with the way in on the left, the product working on the
   right; under them the plans and the first questions, then the
   footer band. The headline is large and light: the page gets its
   weight from space, not from bold type. */
.hero{display:grid;grid-template-columns:minmax(0,0.96fr) minmax(0,1.04fr);
  gap:var(--s8);align-items:center;min-height:var(--hero-min-h);padding:var(--s5) 0 var(--s7)}
.hero-copy{display:flex;flex-direction:column;align-items:center;text-align:center;
  width:100%;max-width:var(--measure-hero-copy);margin-inline:auto}
.hero-h1{font-family:var(--f-display);font-size:var(--t-display-xl);font-weight:var(--w-light);
  line-height:1.06;letter-spacing:var(--tr-tight-lg);margin-bottom:var(--s4);text-wrap:balance}
.hero-sub{font-family:var(--f-ui);font-size:var(--t-hero-sub);line-height:1.45;color:var(--muted);
  margin-bottom:var(--s6);text-wrap:balance}
/* Sign-up starts here: one field, and the sign-up page carries on
   from the password with the address already in it. */
.hero-card{width:100%;background:var(--surface);border-radius:var(--r-xl);padding:var(--s5);
  box-shadow:inset 0 0 0 var(--hairline) var(--rule),var(--shadow-card);
  display:flex;flex-direction:column;gap:var(--s3);text-align:left}
.hero-form{display:flex;flex-direction:column;gap:var(--s3)}
.hero-card-note,.hero-card-line{font-family:var(--f-ui);font-size:var(--t-small);
  color:var(--muted);line-height:1.5;text-align:center}
.hero-card-note a{color:var(--ink);text-decoration:none;
  box-shadow:inset 0 calc(var(--hairline) * -1) 0 var(--rule-firm)}
.hero-card-line b{color:var(--ink);font-weight:600}
.hero-second{margin-top:var(--s4)}
.hero-demo{min-width:0}

/* The moving picture (templates/_demo.html, js/landing.js). Scenes are
   stacked; one is on. Without script the still one is on and stays.
   It is a size container: a video's frame is a strip in a short
   panel and spans the top of a tall one. */
.demo{position:relative;height:var(--demo-h);border-radius:var(--r-xl);overflow:hidden;
  container:demo / size;
  background-color:var(--demo-ground);
  background-image:radial-gradient(var(--demo-dot) var(--demo-dot-size),
                                   transparent calc(var(--demo-dot-size) * 1.6));
  background-size:var(--demo-grid) var(--demo-grid);
  background-position:calc(var(--demo-grid) / 2) calc(var(--demo-grid) / 2);
  box-shadow:inset 0 0 0 var(--hairline) var(--rule),var(--shadow-card)}
.demo .screen{box-shadow:inset 0 0 0 var(--hairline) var(--rule),var(--shadow-card)}
.demo-scene{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  padding:var(--s6);opacity:0;visibility:hidden;transform:translateY(var(--s2));
  transition:opacity var(--dur-fade) var(--ease),transform var(--dur-in) var(--ease-out),
             visibility 0s linear var(--dur-fade)}
.demo-scene.is-on{opacity:1;visibility:visible;transform:none;transition-delay:0s}
.demo-scene .screen{width:100%}
.demo-title{font-family:var(--f-display);font-size:var(--t-h1);font-weight:var(--w-light);
  line-height:1.12;letter-spacing:var(--tr-tight-lg);text-align:center;max-width:var(--measure-demo-title);
  text-wrap:balance}
.demo-card{width:min(100%,var(--measure-demo-card));background:var(--demo-card);border-radius:var(--r-lg);
  box-shadow:inset 0 0 0 var(--hairline) var(--rule),var(--shadow-card);
  padding:var(--s5);display:flex;flex-direction:column;gap:var(--s4)}
.demo-card--wide{width:min(100%,var(--measure-demo-wide))}
.demo-label{font-family:var(--f-ui);font-size:var(--t-label);font-weight:600;
  letter-spacing:var(--tr-caps);text-transform:uppercase;color:var(--muted)}
.demo-field{display:flex;align-items:center;font-family:var(--f-ui);font-size:var(--t-ui);
  background:var(--well);border-radius:var(--r-md);padding:var(--field-pad-y) var(--field-pad-x);
  min-height:calc(var(--t-ui) * 1.5 + var(--field-pad-y) * 2);white-space:nowrap;overflow:hidden}
.demo-caret{display:inline-block;width:var(--ring-w);height:1.15em;margin-left:var(--hairline);
  background:var(--ink);opacity:0}
.demo-caret.is-on{animation:demo-blink 1s steps(1) infinite}
@keyframes demo-blink{0%{opacity:1}50%{opacity:0}}
.demo-press{align-self:flex-start;transition:transform var(--dur) var(--ease),
  background-color var(--dur) var(--ease)}
.demo-press.is-pressed{transform:scale(.95);background:var(--mark-hover)}

/* A mark arriving: a logo pops in, a little past its size and back,
   and its lines follow it. */
.demo-mark{display:flex;flex-direction:column;align-items:center;gap:var(--s3);text-align:center}
.demo-mark-art{margin-bottom:var(--s2);
  transition:transform var(--dur-pop) var(--ease-spring),opacity var(--dur-fade) var(--ease)}
.demo-mark-art svg{height:var(--demo-mark-h);width:auto;max-width:100%}
.demo-mark-text{font-family:var(--f-display);font-size:var(--t-h2);font-weight:var(--w-light);
  line-height:1.15;letter-spacing:var(--tr-tight)}
.demo-mark-sub{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted)}
.demo-mark-text,.demo-mark-sub{transition:opacity var(--dur-fade) var(--ease) var(--dur-fade),
  transform var(--dur-in) var(--ease-out) var(--dur-fade)}
.demo-scene.is-start .demo-mark-art{transform:scale(.45);opacity:0;transition:none}
.demo-scene.is-start .demo-mark-text,
.demo-scene.is-start .demo-mark-sub{opacity:0;transform:translateY(var(--s2));transition:none}

/* A feed: a video and the comments under it, the newest arriving on
   top and pushing the rest down, then each one given its category. */
.demo-page{width:100%;height:100%;display:flex;flex-direction:column;gap:var(--s4);
  background:var(--demo-card);border-radius:var(--r-lg);padding:var(--s5);
  box-shadow:inset 0 0 0 var(--hairline) var(--rule),var(--shadow-card)}
.demo-url{align-self:center;font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  background:var(--well);border-radius:var(--r-pill);padding:var(--s1) var(--s4);
  margin-top:calc(var(--s2) * -1)}
.demo-video{display:flex;align-items:center;gap:var(--s3)}
.demo-frame{flex:none;width:var(--demo-frame-w);aspect-ratio:16 / 9;border-radius:var(--r-sm);
  display:grid;place-items:center;color:var(--demo-frame-ink);
  background:linear-gradient(135deg,var(--demo-frame-a),var(--demo-frame-b))}
.demo-play{display:grid;place-items:center;width:var(--demo-play);height:var(--demo-play);
  border-radius:50%;background:color-mix(in srgb,var(--demo-frame-ink) 16%,transparent)}
.demo-video-text{min-width:0;display:flex;flex-direction:column;gap:var(--gap-tight)}
.demo-video-title,.demo-video-meta{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.demo-video-title{font-family:var(--f-ui);font-size:var(--t-ui);font-weight:600;line-height:1.35}
.demo-video-meta{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted)}
.demo-feed-head{position:relative;display:flex;align-items:center;justify-content:space-between;
  gap:var(--s3);padding-bottom:var(--s3);font-family:var(--f-ui);font-size:var(--t-ui);
  box-shadow:inset 0 calc(var(--hairline) * -1) 0 var(--rule)}
.demo-feed-head b{font-weight:600}
/* The button's three labels share one cell, so it keeps the width of
   the longest and does not jump as they change. */
.demo-sort{display:inline-grid;align-self:center}
.demo-sort>span{grid-area:1 / 1;visibility:hidden;text-align:center}
.demo-sort .demo-sort-done,
.demo-scene.is-idle .demo-sort .demo-sort-idle,
.demo-scene.is-working .demo-sort .demo-sort-working{visibility:visible}
.demo-scene.is-idle .demo-sort .demo-sort-done,
.demo-scene.is-working .demo-sort .demo-sort-done{visibility:hidden}
.demo-sort-bar{position:absolute;left:0;bottom:0;height:var(--ring-w);width:0;
  background:var(--ink);opacity:0}
.demo-scene.is-working .demo-sort-bar{width:100%;opacity:1;
  transition:width var(--sort-ms,2s) linear}
.demo-feed{flex:1;min-height:0;position:relative;overflow:hidden;display:flex;flex-direction:column;
  -webkit-mask-image:linear-gradient(to bottom,black calc(100% - var(--s7)),transparent);
  mask-image:linear-gradient(to bottom,black calc(100% - var(--s7)),transparent)}
.demo-feed>li{display:grid;grid-template-rows:1fr;
  transition:grid-template-rows var(--dur-in) var(--ease-out),opacity var(--dur-fade) var(--ease)}
.demo-feed>li.is-out{grid-template-rows:0fr;opacity:0}
.demo-post-clip{min-height:0;overflow:hidden}
.demo-post{display:flex;gap:var(--s3);padding-top:var(--s4);font-family:var(--f-ui)}
.demo-avatar{flex:none;width:var(--demo-avatar);height:var(--demo-avatar);border-radius:50%;
  display:grid;place-items:center;background:var(--well-hover);color:var(--badge-ink);
  font-size:var(--t-micro);font-weight:600}
.demo-post-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--gap-tight)}
.demo-post-head{display:flex;align-items:center;gap:var(--s2);font-size:var(--t-small);
  color:var(--muted);min-height:calc(var(--t-small) * 1.7);white-space:nowrap}
/* A long category name (German, Turkish) keeps the line: the time gives
   way first, then the chip ends in an ellipsis. */
.demo-post-when{min-width:0;overflow:hidden;text-overflow:ellipsis;flex:0 8 auto}
.demo-post-head b{color:var(--ink);font-weight:600}
.demo-post-likes{display:inline-flex;align-items:center;gap:var(--s1)}
.demo-post-text{font-size:var(--t-read);line-height:1.45}
/* A narrow panel keeps the name and the category on the line. */
@container demo (max-width:520px){
  .demo-post-when,.demo-post-likes{display:none}
}
.demo-tag{margin-left:auto;flex:0 1 auto;min-width:0;overflow:hidden;
  display:inline-flex;align-items:center;gap:var(--s1);
  padding:var(--gap-tight) var(--s2);border-radius:var(--r-pill);font-size:var(--t-label);
  font-weight:600;color:var(--ink);background:var(--well);
  background:color-mix(in srgb,var(--c,var(--accent)) 14%,var(--demo-card));
  opacity:0;transform:scale(.8);
  transition:opacity var(--dur-fade) var(--ease),transform var(--dur-pop) var(--ease-spring)}
.demo-tag i,.demo-legend i{flex:none;width:var(--demo-tag-dot);height:var(--demo-tag-dot);
  border-radius:50%;background:var(--c,var(--accent))}
.demo-tag span{min-width:0;overflow:hidden;text-overflow:ellipsis}
.demo-feed>li.is-tagged .demo-tag{opacity:1;transform:none}

.demo-steps{display:flex;flex-direction:column;gap:var(--s3);font-family:var(--f-ui);
  font-size:var(--t-ui)}
.demo-steps li{position:relative;display:flex;align-items:center;gap:var(--s3);
  transition:color var(--dur) var(--ease)}
.demo-steps li::before{content:"";flex:none;width:var(--check-size);height:var(--check-size);
  border-radius:50%;box-shadow:inset 0 0 0 var(--hairline) var(--rule-firm);
  transition:background-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}
.demo-steps li.is-now{font-weight:600}
.demo-steps li.is-now::before{box-shadow:inset 0 0 0 var(--ring-w) var(--accent)}
.demo-steps li.is-done{color:var(--muted)}
.demo-steps li.is-done::before{background-color:var(--mark);box-shadow:none}
/* The tick: the same drawn checkmark as a done row, centred the same way. */
.demo-steps li.is-done::after{content:"";position:absolute;top:50%;
  left:calc(var(--check-size) / 2);width:var(--checkmark-w);height:var(--checkmark-h-b);
  border:solid var(--on-mark);border-width:0 var(--checkmark-stroke) var(--checkmark-stroke) 0;
  transform:translate(-50%,-62%) rotate(var(--rot-b))}

/* Figures: tiles rising in turn, each counting up to its value. */
.demo-stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
.demo-stats li{display:flex;flex-direction:column;gap:var(--s1);padding:var(--s4);
  border-radius:var(--r-md);background:var(--surface);
  box-shadow:inset 0 0 0 var(--hairline) var(--rule);
  transition:opacity var(--dur-fade) var(--ease) calc(var(--d, 0) * var(--stagger)),
             transform var(--dur-in) var(--ease-out) calc(var(--d, 0) * var(--stagger))}
.demo-stats b{font-family:var(--f-ui);font-size:var(--t-stat-lg);font-weight:600;line-height:1.1}
.demo-stats span{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted)}
.demo-scene.is-empty .demo-stats li{opacity:0;transform:translateY(var(--s2));transition:none}

.demo-bars{display:flex;flex-direction:column;gap:var(--s4);font-family:var(--f-ui);
  font-size:var(--t-small)}
.demo-bars li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--s2) var(--s3)}
.demo-bars b{grid-column:2;grid-row:1;font-weight:600;font-variant-numeric:tabular-nums}
.demo-bars i{grid-column:1 / -1;grid-row:2;height:var(--s2);border-radius:var(--r-pill);
  background:var(--well);position:relative;overflow:hidden}
.demo-bars i::after{content:"";position:absolute;inset:0 auto 0 0;width:var(--w);
  border-radius:inherit;background:var(--c,var(--accent));
  transition:width var(--dur-progress) var(--ease-out) calc(var(--d, 0) * var(--stagger))}
.demo-scene.is-empty .demo-bars i::after{width:0;transition:none}

/* Columns: one per day, stacked by category from the baseline up,
   with the surface between the parts and a rounded top. */
.demo-cols{display:flex;gap:var(--s2);height:var(--demo-chart-h);font-family:var(--f-ui)}
.demo-col{flex:1;min-width:0;display:grid;grid-template-rows:minmax(0,1fr) auto;gap:var(--s2);
  justify-items:center}
.demo-col span{font-size:var(--t-label);color:var(--muted)}
.demo-col-stack{width:100%;max-width:var(--demo-col-max);height:100%;display:flex;
  flex-direction:column-reverse;justify-content:flex-start;gap:var(--demo-data-gap);
  transform-origin:bottom;
  transition:transform var(--dur-progress) var(--ease-out) calc(var(--d, 0) * var(--stagger))}
.demo-col-stack i{flex:0 1 var(--h);min-height:0;background:var(--c,var(--accent))}
.demo-col-stack i:last-child{border-radius:var(--demo-data-r) var(--demo-data-r) 0 0}
.demo-scene.is-empty .demo-col-stack{transform:scaleY(0);transition:none}
.demo-legend{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);font-family:var(--f-ui);
  font-size:var(--t-small);color:var(--muted)}
.demo-legend li{display:flex;align-items:center;gap:var(--s2)}

/* Notes: findings arriving one at a time. */
.demo-notes{display:flex;flex-direction:column;gap:var(--s4);font-family:var(--f-ui);
  font-size:var(--t-ui);line-height:1.5}
.demo-notes li{padding-left:var(--s4);box-shadow:inset var(--mark-rule-w) 0 0 var(--rule-firm)}

.demo .row,.demo-notes li{transition:opacity var(--dur-fade) var(--ease),
  transform var(--dur-in) var(--ease-out)}
.demo .row.is-out,.demo-notes li.is-out{opacity:0;transform:translateY(var(--s2))}
.demo-cursor{position:absolute;left:0;top:0;z-index:2;pointer-events:none;opacity:0;
  transform:translate(60%,70%);
  transition:transform var(--dur-cursor) var(--ease-out),opacity var(--dur-fade) var(--ease)}
.demo.is-playing .demo-cursor.is-on{opacity:1}

/* Under the hero: the plans themselves, then the first questions. */
.home-section{padding-top:var(--s9)}
.home-section--narrow{max-width:var(--measure-home-narrow);margin-inline:auto}
.home-head{display:flex;flex-direction:column;align-items:center;text-align:center;
  gap:var(--s3);margin-bottom:var(--s7)}
.home-title{font-family:var(--f-display);font-size:var(--t-home-title);
  font-weight:var(--w-light);line-height:1.1;letter-spacing:var(--tr-tight-lg)}
.home-sub{font-family:var(--f-ui);font-size:var(--t-read);color:var(--muted)}
.home-more{text-align:center;margin-top:var(--s5);font-family:var(--f-ui);
  font-size:var(--t-small)}
.home-more a{color:var(--ink);font-weight:600;text-decoration:none;
  transition:color var(--dur) var(--ease)}
.home-more a:hover{color:var(--muted)}
.home-faq{border-top:var(--hairline) solid var(--rule)}
.home-faq-item{border-bottom:var(--hairline) solid var(--rule)}
.home-faq-item summary{list-style:none;cursor:pointer;display:flex;align-items:center;
  justify-content:space-between;gap:var(--s4);padding:var(--s5) 0;
  font-family:var(--f-display);font-size:var(--t-h3);font-weight:500;line-height:1.35}
.home-faq-item summary::-webkit-details-marker{display:none}
.home-faq-item summary::after{content:"+";flex:none;font-family:var(--f-ui);font-weight:400;
  color:var(--muted);transition:transform var(--dur) var(--ease)}
.home-faq-item[open] summary::after{transform:rotate(45deg)}
.home-faq-item summary:focus-visible{outline:var(--ring-w) solid var(--ink);
  outline-offset:var(--ring-offset)}
.home-faq-item p{padding-bottom:var(--s5);color:var(--muted);line-height:1.6;
  max-width:var(--measure-prose-md)}

/* ---------- pricing: three cards (round 08) ---------- */
.head{padding:var(--s8) 0 var(--s6);display:flex;align-items:flex-end;
  justify-content:space-between;gap:var(--s6);flex-wrap:wrap}
.head-text{color:var(--muted);max-width:var(--measure-prose-sm);margin-top:var(--s3)}
/* FIXED position, not part of the hiding trick. These two radios
   have to sit BEFORE both .head and .plans so that sibling
   selectors can reach them, meaning they are at the very top of the
   page. When they had absolute position, that was also their
   physical location: clicking the label moved browser focus to the
   radio and brought it into view, and the page jumped to the very
   top -- making it impossible to switch the billing period while
   reading prices further down. With fixed position the radio is
   already in the viewport, so there is no scrolling. The visible
   control is the label itself; the focus ring is drawn on it too
   (the :focus-visible rules below). */
.cycle-radio{position:fixed;top:0;left:0;width:var(--sz-hidden);height:var(--sz-hidden);opacity:0}
.cycle{display:inline-flex;background:var(--well);border-radius:var(--r-pill);
  padding:var(--pad-cycle-outer);flex:none}
.cycle label{font-family:var(--f-ui);font-size:var(--t-small);font-weight:600;
  padding:var(--pad-pill-y) var(--pad-cycle-x);border-radius:var(--r-pill);cursor:pointer;white-space:nowrap;
  display:flex;align-items:baseline;gap:var(--gap-baseline);
  transition:background-color var(--dur) var(--ease),color var(--dur) var(--ease)}
.cycle-save{font-weight:400;color:var(--muted)}
#cy-m:checked ~ .head .cycle label[for="cy-m"],
#cy-y:checked ~ .head .cycle label[for="cy-y"],
#cy-m:checked ~ .home-section .cycle label[for="cy-m"],
#cy-y:checked ~ .home-section .cycle label[for="cy-y"]{background:var(--paper)}
#cy-y:checked ~ .head .cycle label[for="cy-y"] .cycle-save,
#cy-y:checked ~ .home-section .cycle label[for="cy-y"] .cycle-save{color:var(--ink)}
#cy-m:focus-visible ~ .head .cycle label[for="cy-m"],
#cy-y:focus-visible ~ .head .cycle label[for="cy-y"],
#cy-m:focus-visible ~ .home-section .cycle label[for="cy-m"],
#cy-y:focus-visible ~ .home-section .cycle label[for="cy-y"]{outline:var(--ring-w) solid var(--ink);
  outline-offset:var(--ring-offset-tight)}
/* The price line: one line, swapping its content does not change
   its height. */
#cy-m:checked ~ * .price .per-year,
#cy-y:checked ~ * .price .per-month,
#cy-m:checked ~ * .per-year-cta,
#cy-y:checked ~ * .per-month-cta{display:none}

/* The yearly note: it used to appear and disappear with
   `display:none` and the card's height jumped suddenly. By opening
   through the grid row going from 0fr to 1fr, the card's height
   grows smoothly. On a browser without support it is instant like
   before, so nothing breaks. */
.price-note{display:grid;grid-template-rows:0fr;opacity:0}
.price-note > *{overflow:hidden;min-height:0}
#cy-y:checked ~ * .price-note{grid-template-rows:1fr;opacity:1}

.plans{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s4);
  align-items:stretch}
.plan{background:var(--surface);border-radius:var(--r-xl);padding:var(--s6);
  box-shadow:inset 0 0 0 var(--hairline) var(--rule);
  display:flex;flex-direction:column;gap:var(--s3)}
.plan-top{display:flex;align-items:center;justify-content:space-between;gap:var(--s3)}
.plan-name{font-family:var(--f-display);font-size:var(--t-title-sm);font-weight:600}
.plan-adds{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  line-height:1.6}
.plan-adds b{color:var(--ink);font-weight:600;display:block;margin-bottom:var(--s1)}
.plan .btn{margin-top:auto;width:100%}
.price{font-family:var(--f-ui);font-variant-numeric:tabular-nums;display:flex;
  align-items:baseline;gap:var(--gap-baseline);flex-wrap:wrap}
.price b{font-size:var(--t-price-amount);font-weight:600;color:var(--ink)}
.price span{font-size:var(--t-small);color:var(--muted)}
.price-note{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted)}
.handoff{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  padding-top:var(--s5);line-height:1.55}
.pass{display:flex;align-items:center;gap:var(--s5);flex-wrap:wrap;
  background:var(--surface);border-radius:var(--r-lg);padding:var(--s4) var(--s5);
  margin-top:var(--s7)}
.pass-text{font-family:var(--f-ui);font-size:var(--t-ui);flex:1;min-width:var(--measure-pass-text-min);
  line-height:1.5}
.pass-text b{font-weight:600}
.pass-buy{display:flex;align-items:center;gap:var(--s4);flex:none}
.pass-price{font-family:var(--f-ui);font-size:var(--t-ui);font-weight:600;
  font-variant-numeric:tabular-nums}
.faq{padding:var(--s8) 0 var(--s7);display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s6) var(--s8);
  box-shadow:inset 0 var(--hairline) 0 var(--rule);margin-top:var(--s8)}
.faq h3{font-family:var(--f-display);font-size:var(--t-h3);font-weight:600;
  margin-bottom:var(--s2)}
.faq p{font-size:var(--t-read);color:var(--muted);line-height:1.55}

/* ---------- auth: split (round 09) ----------
   No navigation bar: every page in this family has exactly one
   thing to do. On a phone the left half becomes one line above
   the form so the reason survives the fold. */
.auth{min-height:var(--viewport-h);display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
.auth-side{background:var(--well);padding:var(--s8) var(--s7);
  display:flex;flex-direction:column;gap:var(--s5)}
.auth-side .mark{align-self:flex-start}
/* The product, between its name and its claim (round 15). One still
   picture sized by its content, not the landing page's tall stage. */
.auth-preview{margin-block:auto;width:100%;max-width:var(--measure-auth-preview);align-self:center}
.auth-preview .demo{height:auto;container-type:inline-size}
.auth-preview .demo-scene{position:relative;inset:auto}
.auth-preview~.auth-line{margin-top:0}
/* One comment over the chart, lifted off it. */
.auth-post{position:relative;z-index:1;width:min(82%,var(--measure-demo-card));
  margin:0 0 calc(var(--s5) * -1) calc(var(--s6) * -1);padding:0 var(--s4) var(--s4);
  background:var(--demo-card);border-radius:var(--r-lg);
  box-shadow:inset 0 0 0 var(--hairline) var(--rule),var(--shadow-lift)}
.auth-post .demo-tag{opacity:1;transform:none}
/* A short window keeps the form in view: the picture goes first. */
@media (max-height:680px){.auth-preview{display:none}}
.auth-line{font-family:var(--f-display);font-size:var(--t-auth-line);font-weight:600;line-height:1.25;
  letter-spacing:var(--tr-snug);max-width:var(--measure-auth-line);margin-top:auto}
.auth-note{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  line-height:1.6;max-width:var(--measure-auth-note)}
.auth-work{padding:var(--s8) var(--s7);display:flex;flex-direction:column;
  justify-content:center}
.auth-in{width:100%;max-width:var(--measure-auth-form);display:flex;flex-direction:column;gap:var(--s5)}
.auth-head{display:flex;flex-direction:column;gap:var(--s2)}
.auth-title{font-family:var(--f-display);font-size:var(--t-auth-title);font-weight:600;
  letter-spacing:var(--tr-tight-lg);line-height:1.15}
.auth-text{font-family:var(--f-ui);font-size:var(--t-ui);color:var(--muted);line-height:1.6}
.auth-text b{color:var(--ink);font-weight:600}
.form{display:flex;flex-direction:column;gap:var(--s4)}
.form .btn{width:100%}
.auth-alt{font-family:var(--f-ui);font-size:var(--t-ui);color:var(--muted)}
/* No underline: these pages have two endpoint links and an
   underline under them crowded the page. What sets them apart is
   weight and colour; the underline comes on hover, so it is still
   clear they are a link. */
.auth-alt a{color:var(--ink);text-decoration:none;font-weight:500;
  transition:color var(--dur) var(--ease)}
.auth-alt a:hover{color:var(--muted)}
.waiting{display:flex;flex-direction:column;gap:var(--s3)}
.resend{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap}
.resend-note{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  font-variant-numeric:tabular-nums}
.auth-foot{display:flex;gap:var(--s5);flex-wrap:wrap}
.auth-foot a{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  text-decoration:none;transition:color var(--dur) var(--ease)}
.auth-foot a:hover{color:var(--ink)}

/* ---------- narrow screens ---------- */
@media (max-width:980px){
  .plans{grid-template-columns:1fr}
  .hero{grid-template-columns:1fr;gap:var(--s7);padding:var(--s7) 0 var(--s8)}
  /* As on most product pages: on a narrow screen the claim and the way
     in are the page; the moving picture would push the card below
     the fold. */
  .hero-demo{display:none}
}
@media (max-width:860px){
  .auth{grid-template-columns:1fr;min-height:0}
  .auth-side{padding:var(--s5) var(--s4);gap:var(--s3)}
  .auth-line{font-size:var(--t-auth-line-sm);margin-top:0}
  .auth-note{display:none}
  .auth-preview{display:none}
  .auth-work{padding:var(--s6) var(--s4);justify-content:flex-start}
}
@media (max-width:820px){
  .under{grid-template-columns:1fr;gap:var(--s5)}
}
@media (max-width:680px){
  .chat{padding:0 var(--s3)}
  .chat-head{padding:var(--s4) 0 var(--s3)}
  .chat-log{padding:var(--s4) var(--s2);gap:var(--s4)}
  .msg{max-width:90%}

  .bar-in{height:auto;padding:var(--s3) var(--s4) 0;flex-wrap:wrap;gap:var(--s3);
    align-items:center}
  .sections{order:3;flex:1 0 100%;overflow-x:auto;gap:var(--s5);height:auto;
    margin-top:var(--s2);box-shadow:inset 0 var(--hairline) 0 var(--rule);scrollbar-width:none}
  .sections::-webkit-scrollbar{display:none}
  .navlink{padding:var(--s3) 0}
  .col{padding:var(--s5) var(--s4) var(--s8)}
  .wrap{padding-inline:var(--s5)}
  .page-title{font-size:var(--t-title-md)}
  .home-section{padding-top:var(--s8)}
  .hero-card{padding:var(--s4)}
  .faq{grid-template-columns:1fr;gap:var(--s5);padding:var(--s6) 0;margin-top:var(--s6)}
  .status{padding:var(--s4)}
  .log-time{width:var(--measure-log-time-sm)}
}

/* ---------- the document layout ----------
   Privacy, terms, credits, FAQ and anything else that is mostly
   reading. One measure, a contents list that stays put, and no
   component the rest of the system does not already have. */
.doc{padding:var(--s7) 0 var(--s9);display:grid;
  grid-template-columns:var(--measure-toc-col) minmax(0,1fr);gap:var(--s8);align-items:start}
.doc-head{grid-column:1 / -1;max-width:var(--measure-prose-md)}
.doc-meta{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  margin-top:var(--s3)}
.doc-note{font-family:var(--f-ui);font-size:var(--t-small);color:var(--ink);background:var(--well);
  border-radius:var(--r-md);padding:var(--s2) var(--s3);margin-top:var(--s3);align-self:flex-start}
.toc{position:sticky;top:var(--s6);display:flex;flex-direction:column;gap:var(--s2)}
.toc-label{font-family:var(--f-ui);font-size:var(--t-label);font-weight:600;
  letter-spacing:var(--tr-caps);text-transform:uppercase;color:var(--muted);margin-bottom:var(--s1)}
.toc a{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  text-decoration:none;line-height:1.5;transition:color var(--dur) var(--ease)}
.toc a:hover{color:var(--ink)}

.prose{max-width:var(--measure-prose-lg)}
.prose h2{font-family:var(--f-display);font-size:var(--t-h2);font-weight:600;
  line-height:1.2;letter-spacing:var(--tr-snug);margin:var(--s8) 0 var(--s4);
  scroll-margin-top:var(--s7)}
.prose h2:first-child{margin-top:0}
.prose h3{font-family:var(--f-display);font-size:var(--t-h3);font-weight:600;
  margin:var(--s6) 0 var(--s3)}
.prose p{margin-bottom:var(--s4);line-height:1.7}
.prose ul{margin:0 0 var(--s4) 0;display:flex;flex-direction:column;gap:var(--s2)}
.prose li{padding-left:var(--s5);position:relative;line-height:1.7}
.prose li::before{content:"";position:absolute;left:var(--s2);top:var(--bullet-dash-top);
  width:var(--bullet-dash-w);height:var(--hairline);background:var(--rule-firm)}
.prose a{text-decoration:none;box-shadow:inset 0 calc(var(--hairline) * -1) 0 var(--rule-firm);
  transition:box-shadow var(--dur) var(--ease)}
.prose a:hover{box-shadow:inset 0 calc(var(--hairline) * -1) 0 var(--ink)}
.prose .small{margin-bottom:var(--s4)}
.prose dl{margin-bottom:var(--s4)}
.prose dt{font-weight:600;margin-top:var(--s4)}
.prose dd{margin:var(--s1) 0 0;color:var(--muted);line-height:1.7}

/* ---------- panels, used by settings and by forms ---------- */
.panel{background:var(--surface);border-radius:var(--r-lg);padding:var(--s5);
  display:flex;flex-direction:column;gap:var(--s4)}
.panel-title{font-family:var(--f-display);font-size:var(--t-h3);font-weight:600}
.panel-text{font-family:var(--f-ui);font-size:var(--t-small);color:var(--muted);
  line-height:1.6}
.panel-row{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s4);flex-wrap:wrap}
.choice{display:flex;gap:var(--s2);flex-wrap:wrap}
.choice input{position:absolute;width:var(--sz-hidden);height:var(--sz-hidden);opacity:0}
.choice label{font-family:var(--f-ui);font-size:var(--t-small);font-weight:600;
  background:var(--well);border-radius:var(--r-pill);padding:var(--pad-pill-y) var(--pad-choice-x);cursor:pointer;
  transition:background-color var(--dur) var(--ease),color var(--dur) var(--ease)}
.choice label:hover{background:var(--well-hover)}
.choice input:checked + label{background:var(--mark);color:var(--on-mark)}
.choice input:focus-visible + label{outline:var(--ring-w) solid var(--ink);outline-offset:var(--ring-offset-tight)}

/* ---------- a full page state: 404, 500, offline ---------- */
.state-page{min-height:var(--measure-state-min-h);display:flex;flex-direction:column;
  justify-content:center;align-items:flex-start;gap:var(--s4);max-width:var(--measure-state)}
.state-code{font-family:var(--f-ui);font-size:var(--t-label);font-weight:600;
  letter-spacing:var(--tr-caps);text-transform:uppercase;color:var(--muted)}

@media (max-width:900px){
  .doc{grid-template-columns:1fr;gap:var(--s5);padding:var(--s6) 0 var(--s8)}
  .toc{position:static;flex-direction:row;flex-wrap:wrap;gap:var(--s2) var(--s5);
    padding-bottom:var(--s4);box-shadow:inset 0 calc(var(--hairline) * -1) 0 var(--rule)}
  .toc-label{width:100%;margin-bottom:0}
}

/* A document with no contents list does not need the column it
   would have sat in. */
.doc--wide{grid-template-columns:minmax(0,1fr)}
.doc--wide .prose{max-width:var(--measure-prose-xl)}

/* ---------- the shell ----------
   Everything js/navigate.js replaces in one step. It must add no box:
   the chat page lays out <main> as a flex child of <body>, and every
   other page assumes its blocks are body's children too. */
.app{display:contents}
/* Focus lands on <main> after a swap when the focused element has
   left the page. It is a landing point for the keyboard, not a
   control, so it shows no ring. */
main:focus{outline:none}
