/*
  The app (/app): sign in, first-run setup, Today and everything an owner
  configures. Colours, type, buttons and the drawn X3 come from brand.css;
  this file lays the app out on top of them.

  One idea runs through it: the X3 itself is the hero. Home, the screen
  builder, setup and the settings pages all show a drawn X3 whose screen is
  rendered here, in the browser, by the same renderer the device uses.
  Everything around it stays quiet: paper ground, white panels, hairlines,
  Recoleta only for page titles and Deckle's own words.
*/

:root {
  --rail-w: 256px;
  --danger: #a23b2c;
  --danger-soft: #f7e7e3;
  --field-bg: #ffffff; /* inside inputs; their borders are brand.css's --field */
  --desk: #ebebe5;
  /* An X3 that has been quiet a few hours: a dot, never text (3.6:1 on white). */
  --amber: #b7791f;
  --topbar-h: 60px;
  --tabbar-h: 66px;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8d91' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --danger: #ef9d90;
    --danger-soft: #2f1f1c;
    --field-bg: #151618;
    --desk: #1d1e21;
    --amber: #e0b35a;
  }
}
:root[data-theme="dark"] {
  --danger: #ef9d90;
  --danger-soft: #2f1f1c;
  --field-bg: #151618;
  --desk: #1d1e21;
  --amber: #e0b35a;
}

html {
  /* Room for what stays in view at the top: the mini X3, or its folded line,
     while it's sticky (--mini-h, measured by the app). */
  scroll-padding-top: calc(24px + var(--mini-h, 0px));
}
body {
  min-height: 100vh;
  min-height: 100dvh;
  overflow-x: hidden;
}
/* Clicking a page title to focus it (for screen readers) draws nothing. */
[tabindex="-1"]:focus {
  outline: none;
}
/* One icon style: 1-bit pixels, filled, never smoothed. */
.icon {
  width: 24px;
  height: 24px;
  flex: none;
  fill: currentColor;
  shape-rendering: crispEdges;
}
.px32 {
  width: 32px;
  height: 32px;
  flex: none;
  fill: currentColor;
  shape-rendering: crispEdges;
}
.skiplink {
  position: absolute;
  left: 12px;
  top: -80px;
  z-index: 100;
  padding: 10px 18px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font-weight: 600;
  text-decoration: none;
}
.skiplink:focus {
  top: 12px;
}

/* ------------------------------------------------------------------ states
   Until Firebase says who is here, a quiet mark -- or, for someone this
   browser hasn't seen signed in, the sign-in page at once. Then either the
   sign-in page or the app, never a flash of the wrong one. */
.splash {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
}
.splash .sprite {
  --s: 72px;
  opacity: 0.85;
}
@media (prefers-reduced-motion: no-preference) {
  .splash .sprite {
    animation: breathe 2.4s ease-in-out infinite;
  }
  @keyframes breathe {
    50% {
      transform: translateY(-6px);
      opacity: 0.55;
    }
  }
}
/* The app's own script never ran: say so, with Reload (the head's script). */
.loadfail {
  display: none;
}
html[data-fail] .loadfail {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 14px;
  padding: 24px;
  text-align: center;
  background: var(--paper);
}
.loadfail .sprite {
  --s: 72px;
  margin-bottom: 6px;
}
.loadfail h1 {
  font-size: clamp(1.9rem, 1.4rem + 2vw, 2.6rem);
}
.loadfail p {
  margin: 0 0 8px;
  max-width: 28em;
  color: var(--ink-2);
}
/* Stronger than the rules that show the sign-in page early, below. */
html[data-fail][data-fail] body[data-auth] .splash,
html[data-fail][data-fail] body[data-auth] .gate,
html[data-fail][data-fail] body[data-auth] .shell {
  display: none !important;
}
body:not([data-auth="pending"]):not([data-auth="loading"]) .splash,
body:not([data-auth="out"]) .gate,
body:not([data-auth="in"]) .shell {
  display: none !important;
}
html[data-guess="out"] body[data-auth="pending"] .splash {
  display: none !important;
}
html[data-guess="out"] body[data-auth="pending"] .gate {
  display: grid !important;
}

/* ------------------------------------------------------------------ brand mark */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  text-decoration: none;
  font: 700 1.625rem/1 var(--display);
  letter-spacing: -0.02em;
}
.brand .sprite {
  --s: 30px;
}
.brand:hover {
  text-decoration: none;
}

/* The wordmark, as on the website. */
.brand-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

/* ------------------------------------------------------------------ signed out */
.gate {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
}
.gate-top,
.gate-foot {
  display: flex;
  align-items: center;
  gap: 20px;
  justify-content: space-between;
  padding: 24px max(var(--gutter), env(safe-area-inset-right)) 24px max(var(--gutter), env(safe-area-inset-left));
  max-width: var(--max);
  width: 100%;
  margin-inline: auto;
}
.gate-top a:not(.brand) {
  color: var(--ink-2);
  font-weight: 600;
  text-decoration: none;
}
.gate-main {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  align-items: center;
  gap: clamp(40px, 6vw, 96px);
  max-width: var(--max);
  width: 100%;
  margin-inline: auto;
  padding: clamp(24px, 5vw, 64px) max(var(--gutter), env(safe-area-inset-right)) clamp(24px, 5vw, 64px) max(var(--gutter), env(safe-area-inset-left));
}
.gate-copy h1 {
  font-size: var(--t-1);
  line-height: 1.02;
  letter-spacing: -0.025em;
}
.gate-copy .lede {
  margin: 24px 0 36px;
}
.gate-copy .fine {
  margin: 20px 0 0;
  color: var(--ink-3);
  font-size: var(--t-small);
}
/* An invitation: who it's from, with their companion. */
.gate-from {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 20px;
  font: 600 var(--t-tiny) / 1.2 var(--text);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.gate-from .sprite {
  --s: 56px;
  flex: none;
}
.gate-nox3 {
  margin-top: 32px;
  padding: 20px 22px;
  border-radius: 18px;
  background: var(--surface-2);
}
.gate-nox3 h2 {
  font: 700 1.25rem/1.2 var(--display);
  margin: 0 0 6px;
}
.gate-nox3 p {
  margin: 0 0 12px;
  color: var(--ink-2);
}
.gate-status {
  margin: 16px 0 0;
  color: var(--danger);
  font-weight: 500;
}
.gate-status:empty {
  margin: 0;
}
.gbtn svg {
  width: 20px;
  height: 20px;
}
#gateBye .bye-sprite {
  --s: 96px;
  margin-bottom: 24px;
}
#gateBye .fine {
  margin: 0 0 28px;
}
.gate-visual {
  display: grid;
  justify-items: center;
}
.gate-visual .x3 {
  --w: var(--x3-sm);
}
.gate-foot {
  color: var(--ink-3);
  font-size: var(--t-small);
  border-top: 1px solid var(--rule);
  flex-wrap: wrap;
}
.gate-foot a {
  color: var(--ink-2);
}

/* ------------------------------------------------------------------ the shell
   Desktop: a rail on the left with the X3 switcher, the sections and the
   account. Phone: a top bar with the switcher and account, and a tab bar
   along the bottom. */
.rail {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.switcher {
  position: relative;
  display: flex;
  align-items: center;
}
.switcher:has(select[hidden]) {
  display: none;
}
.switcher .dot {
  position: absolute;
  left: 14px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--rule-2);
  pointer-events: none;
}
.switcher .dot[data-state="good"] {
  background: var(--accent);
}
/* Green only while it keeps its hours; amber after three quiet ones. */
.switcher .dot[data-state="late"] {
  background: var(--amber);
}
.switcher .dot[data-state="stale"] {
  background: var(--warn);
}
.switcher select {
  margin: 0;
  min-height: 44px;
  padding-left: 32px;
  font-weight: 600;
  border-radius: 999px;
  background-color: var(--surface);
  text-overflow: ellipsis;
}
.nav {
  display: grid;
  gap: 2px;
}
.nav a {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0 12px;
  border-radius: 12px;
  color: var(--ink-2);
  text-decoration: none;
  font-weight: 500;
}
.nav a > span:not(.navdot):not(.badge) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nav a:hover {
  background: var(--surface-2);
  color: var(--ink);
}
.nav a[aria-current="page"] {
  background: var(--surface);
  color: var(--ink);
  font-weight: 600;
  box-shadow: var(--shadow-1), inset 0 0 0 1px var(--rule);
}
.nav .navlook,
.tabbar .navlook {
  --s: 24px;
  width: 24px;
  height: 24px;
}
.nav-sep {
  height: 1px;
  background: var(--rule);
  margin: 10px 12px;
}
/* Unpublished screens: a small dot beside Screens. */
.navdot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--warn);
  flex: none;
  display: inline-block;
}
.nav .navdot {
  margin-left: auto;
}
/* Friend requests waiting: a count beside Letters. */
.badge {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font: 700 0.75rem/1 var(--text);
  font-variant-numeric: tabular-nums;
  flex: none;
}
.nav .badge {
  margin-left: auto;
}

/* the account */
#acct {
  position: relative;
}
#acct > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 6px 8px;
  border-radius: 12px;
  color: var(--ink-2);
  font-size: var(--t-small);
}
#acct > summary::-webkit-details-marker {
  display: none;
}
#acct > summary:hover,
#acct[open] > summary {
  background: var(--surface-2);
}
#acctInitial {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  display: grid;
  place-items: center;
  font: 600 0.9375rem/1 var(--text);
  flex: none;
}
#who {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.acctmenu {
  position: absolute;
  z-index: 30;
  min-width: 248px;
  max-width: calc(100vw - 32px);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 16px;
  box-shadow: var(--shadow-2);
  padding: 16px;
  display: grid;
  gap: 12px;
  font-size: var(--t-small);
}
.acctmenu .email {
  display: block;
  color: var(--ink);
  font-weight: 600;
  overflow-wrap: anywhere;
}
.acctmenu nav {
  display: grid;
  gap: 2px;
  border-top: 1px solid var(--rule);
  padding-top: 10px;
}
.acctmenu nav a {
  color: var(--ink-2);
  text-decoration: none;
  padding: 6px 0;
}
.acctmenu nav a:hover {
  color: var(--ink);
}
.acct-actions {
  display: grid;
  gap: 2px;
  border-top: 1px solid var(--rule);
  padding-top: 8px;
  margin: 0 -8px;
}
/* Menu rows, quieter than buttons: the words, and a fill on hover. */
.acct-actions button {
  justify-content: flex-start;
  width: 100%;
  min-height: 40px;
  padding: 0 8px;
  border-color: transparent;
  border-radius: 10px;
  font-weight: 500;
  font-size: inherit;
}
@media (hover: hover) {
  .acct-actions button:hover:not(:disabled) {
    border-color: transparent;
    background: var(--surface-2);
  }
}

.main {
  min-width: 0;
}
.view {
  max-width: 1120px;
  margin-inline: auto;
}
/* One rhythm down every page; the page head keeps its own larger space. */
.view > * + * {
  margin-top: 20px;
}
.tabbar {
  display: none;
}

@media (min-width: 960px) {
  .shell {
    display: grid;
    grid-template-columns: var(--rail-w) minmax(0, 1fr);
    min-height: 100vh;
  }
  .rail {
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100dvh;
    overflow-y: auto;
    padding: 28px 16px 16px max(16px, env(safe-area-inset-left));
    border-right: 1px solid var(--rule);
  }
  .rail .brand {
    padding: 0 12px;
  }
  .rail .brand-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }
  #acct {
    margin-top: auto;
  }
  .acctmenu {
    left: 0;
    bottom: calc(100% + 8px);
  }
  .main {
    padding: clamp(32px, 4vw, 56px) max(clamp(24px, 4vw, 56px), env(safe-area-inset-right)) 96px clamp(24px, 4vw, 56px);
  }
}
@media (min-width: 960px) and (max-width: 1199.98px) {
  :root {
    --rail-w: 228px;
  }
}
@media (max-width: 959.98px) {
  /* Focused fields scroll clear of the top bar and the tab bar, and of
     Publish over it on Screens (--pub-h, measured by the app). */
  html {
    scroll-padding: calc(var(--topbar-h) + 16px + var(--mini-h, 0px)) 0 calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 16px + var(--pub-h, 0px));
  }
  .rail {
    position: sticky;
    top: 0;
    z-index: 25;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    height: var(--topbar-h);
    padding: 0 max(12px, env(safe-area-inset-right)) 0 max(16px, env(safe-area-inset-left));
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
  }
  .rail .brand {
    margin-right: auto;
    font-size: 1.375rem;
  }
  /* the pill under the word, so a second X3's switcher has the room */
  .rail .brand-row {
    flex: none;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    margin-right: auto;
  }
  .rail .brand-row .brand {
    margin-right: 0;
  }
  .rail .brand .sprite {
    --s: 24px;
  }
  .rail .nav {
    display: none;
  }
  .switcher {
    min-width: 0;
    max-width: 46vw;
  }
  .switcher select {
    min-height: 40px;
    font-size: 16px;
    padding-top: 6px;
    padding-bottom: 6px;
  }
  #acct > summary {
    padding: 4px;
  }
  #who {
    display: none;
  }
  .acctmenu {
    right: 0;
    top: calc(100% + 8px);
  }
  .main {
    padding: 28px max(16px, env(safe-area-inset-right)) calc(var(--tabbar-h) + 40px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
  }
  .tabbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 25;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    height: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
    padding: 0 max(4px, env(safe-area-inset-right)) env(safe-area-inset-bottom) max(4px, env(safe-area-inset-left));
    background: var(--surface);
    border-top: 1px solid var(--rule);
  }
  .tabbar a,
  .tabbar button {
    all: unset;
    box-sizing: border-box;
    display: grid;
    justify-items: center;
    align-content: center;
    gap: 4px;
    min-width: 0;
    padding: 6px 2px;
    color: var(--ink-3);
    font: 600 0.75rem/1.1 var(--text);
    cursor: pointer;
    text-align: center;
  }
  .tabbar .tab-label {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .tabbar .icon-wrap {
    position: relative;
    display: grid;
    place-items: center;
    width: 52px;
    height: 30px;
    border-radius: 999px;
    transition: background-color 0.15s ease;
  }
  .tabbar .badge,
  .tabbar .navdot {
    position: absolute;
    top: -3px;
    right: 4px;
  }
  .tabbar .badge {
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    font-size: 0.6875rem;
    box-shadow: 0 0 0 2px var(--surface);
  }
  .tabbar .navdot {
    top: 1px;
    right: 10px;
    box-shadow: 0 0 0 2px var(--surface);
  }
  .tabbar [aria-current="page"],
  .tabbar [data-current="true"] {
    color: var(--ink);
  }
  .tabbar [aria-current="page"] .icon-wrap,
  .tabbar [data-current="true"] .icon-wrap {
    background: var(--surface-2);
  }
  .tabbar a:focus-visible,
  .tabbar button:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -4px;
    border-radius: 14px;
  }
}

/* ------------------------------------------------------------------ page heads */
.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 28px;
  margin: 0 0 32px;
}
.page-head > div:first-child {
  min-width: 0;
  flex: 1 1 420px;
}
.page-title {
  font: 700 clamp(2.2rem, 1.6rem + 1.7vw, 3.1rem) / 1.04 var(--display);
  letter-spacing: -0.022em;
  color: var(--ink);
}
.page-lede {
  margin: 12px 0 0;
  font-size: 1.125rem;
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 40em;
}
/* Home's one line about the X3: "Checked in 12 min ago · 86% · Up to date". */
.statline {
  font-variant-numeric: tabular-nums;
}
.page-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

/* ------------------------------------------------------------------ settings pages
   One calm column of cards, and at wide sizes a sticky X3 beside it showing
   what the page changes. */
.col {
  max-width: 780px;
  min-width: 0;
}
.col > * + * {
  margin-top: 20px;
}
.settings > .side {
  display: none;
}
/* One width for every X3 column beside a page: room for an X3 at its small
   exact size (brand.css's --x3-sm), with the desk around it. */
:root {
  --preview-col: calc(var(--x3-sm) + 48px);
}
@media (min-width: 1200px) {
  .settings {
    display: grid;
    grid-template-columns: minmax(0, 780px) var(--preview-col);
    gap: 32px;
    align-items: start;
  }
  .settings > .side {
    display: block;
    position: sticky;
    top: 32px;
  }
  .settings > .side .desk {
    padding: 28px 24px 20px;
  }
  .settings > .side .x3 {
    --w: var(--x3-sm);
  }
  .mini-toggle {
    display: none;
  }
}
/* Below 1200px the X3 sits at the top of the page, at its small exact size,
   and folds to a line when it's in the way (remembered). Where the window is
   tall it stays in view as the page scrolls, but only while it takes no more
   than a third of the window (the app measures it): on a tablet held upright
   the X3 at its exact size takes up to half, over the page, so there it
   scrolls with the page, and only its folded line stays in view. */
@media (max-width: 1199.98px) {
  .settings {
    display: flex;
    flex-direction: column;
  }
  .settings > .side {
    display: block;
    order: -1;
    z-index: 6;
    margin: 0 0 20px;
  }
  .settings > .side .desk {
    grid-template-columns: auto minmax(0, 1fr) auto;
    justify-items: start;
    align-items: center;
    gap: 14px 20px;
    padding: 16px 20px;
    border-radius: 20px;
  }
  .settings > .side .x3 {
    --w: var(--x3-sm);
  }
  .settings > .side .desk-caption {
    margin: 0;
    text-align: left;
    max-width: none;
  }
  .settings > .side[data-folded="true"] .x3 {
    display: none;
  }
  .settings > .side[data-folded="true"] .desk {
    grid-template-columns: minmax(0, 1fr) auto;
    padding: 8px 8px 8px 16px;
    box-shadow: none;
  }
  .settings > .side[data-folded="true"] .desk-caption {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Nothing to draw (Letters with no letter yet): just what it says. */
  .settings > .side[data-empty="true"] .desk {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .mini-toggle {
    min-height: 36px;
    padding: 0 12px;
    font-size: 0.8125rem;
    background: var(--surface);
  }
}
@media (max-width: 1199.98px) and (min-height: 1100px) {
  .settings > .side {
    top: 12px;
  }
  .settings > .side[data-fits="true"] {
    position: sticky;
  }
  .settings > .side[data-fits="true"]:not([data-folded="true"]) .desk {
    box-shadow: var(--shadow-2);
  }
}
/* On a phone the X3 starts as a thumbnail beside its caption, so the page's
   own controls come first. A tap on it shows it at its small exact size (and
   another takes it back); Hide folds it to a line, which is remembered. */
.mini-zoom {
  display: none;
}
@media (max-width: 600px) {
  .settings > .side .desk {
    grid-template-columns: auto minmax(0, 1fr);
    justify-items: start;
    gap: 10px 16px;
  }
  .settings > .side[data-folded="true"] .desk {
    justify-items: stretch;
  }
  .settings > .side:not([data-folded="true"]) .x3 {
    --w: 96px;
    grid-row: 1 / span 2;
  }
  .settings > .side:not([data-folded="true"]) .desk-caption {
    align-self: end;
  }
  .settings > .side:not([data-folded="true"]) .mini-toggle {
    grid-column: 2;
    align-self: start;
  }
  /* A thumbnail is smoothed rather than cut to whole panel pixels. */
  .settings > .side:not([data-big="true"]) .x3-screen canvas {
    image-rendering: auto;
  }
  .settings > .side[data-big="true"]:not([data-folded="true"]) .desk {
    grid-template-columns: minmax(0, 1fr) auto;
    justify-items: stretch;
  }
  .settings > .side[data-big="true"]:not([data-folded="true"]) .x3 {
    --w: var(--x3-sm);
    grid-row: auto;
    grid-column: 1 / -1;
    justify-self: center;
  }
  .settings > .side[data-big="true"]:not([data-folded="true"]) .desk-caption,
  .settings > .side[data-big="true"]:not([data-folded="true"]) .mini-toggle {
    align-self: center;
  }
  .settings > .side:not([data-folded="true"]) .mini-zoom {
    all: unset;
    position: absolute;
    inset: 0;
    z-index: 2;
    display: block;
    box-sizing: border-box;
    border-radius: calc(var(--u) * 9);
    cursor: zoom-in;
    -webkit-tap-highlight-color: transparent;
  }
  .settings > .side[data-big="true"] .mini-zoom {
    cursor: zoom-out;
  }
  .settings > .side[data-empty="true"] .desk-caption,
  .settings > .side[data-empty="true"] .mini-toggle {
    align-self: center;
  }
  .settings > .side .mini-zoom:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
  }
}

/* ------------------------------------------------------------------ cards */
.card {
  padding: 28px;
  min-width: 0;
}
/* The middle of the type scale: page titles are big Recoleta, card titles a
   step down in the same face, and everything inside them Figtree. */
.card > h2,
.card-title,
.buildbox > summary .sumtitle,
.outline-head h2 {
  font: 700 1.5rem/1.2 var(--display);
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: 0 0 8px;
  text-wrap: balance;
}
.card-lede,
.card > p.hint:first-of-type {
  color: var(--ink-2);
  margin: 0 0 20px;
  font-size: 1rem;
  max-width: 44em;
}
.actions + h3.sub {
  border-top: 0;
  padding-top: 0;
}
#frAdd::placeholder,
#pairCode::placeholder {
  text-transform: none;
}
h3.sub {
  font: 650 1.0625rem/1.3 var(--text);
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 28px 0 14px;
  padding-top: 24px;
  border-top: 1px solid var(--rule);
}
h3.sub.first {
  margin-top: 8px;
}
.hint {
  margin: 8px 0 14px;
  color: var(--ink-3);
  font-size: var(--t-small);
  line-height: 1.5;
}
.locknote {
  display: none;
  margin: 0 0 16px;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--warn-soft);
  color: var(--warn);
  font-size: var(--t-small);
}
.ownerOnly[data-locked="true"] .locknote {
  display: block;
}
.empty {
  color: var(--ink-3);
  font-size: var(--t-small);
}
code {
  font: 0.875em/1.4 var(--mono);
  background: var(--surface-2);
  border-radius: 6px;
  padding: 0.1em 0.4em;
  color: var(--ink);
}
b,
strong {
  color: var(--ink);
  font-weight: 600;
}

/* ------------------------------------------------------------------ fields */
label,
p.label {
  display: block;
  font: 600 0.9375rem/1.35 var(--text);
  color: var(--ink);
  margin: 0 0 8px;
}
p.label .hint,
label .muted {
  font-weight: 400;
}
input[type="text"],
input[type="url"],
input[type="search"],
input[type="tel"],
input[type="email"],
input[type="password"],
input[type="number"],
textarea,
select {
  width: 100%;
  font: 400 1rem/1.45 var(--text);
  color: var(--ink);
  background-color: var(--field-bg);
  border: 1px solid var(--field);
  border-radius: 12px;
  padding: 11px 14px;
  min-height: 48px;
  margin: 0 0 18px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
textarea {
  resize: vertical;
  min-height: 110px;
}
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 42px;
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 18px 18px;
  cursor: pointer;
}
input:focus,
textarea:focus,
select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
input[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: var(--danger);
}
input[aria-invalid="true"]:focus,
textarea[aria-invalid="true"]:focus {
  box-shadow: 0 0 0 3px var(--danger-soft);
}
input[readonly] {
  background-color: var(--surface-2);
  border-color: transparent;
}
::placeholder {
  color: var(--ink-3);
  opacity: 0.85;
}
.field + .field {
  margin-top: 4px;
}
.formrow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0 14px;
}
.formrow .wide {
  grid-column: span 2;
}
@media (min-width: 601px) {
  .formrow.half {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}
.card > h2 + p.label,
.card > .locknote + p.label {
  margin-top: 16px;
}
#bOpensRow {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
}
#bOpensRow .wide {
  grid-column: auto;
}
.imaprow {
  grid-template-columns: 1fr 110px;
}
/* A field with its button beside it, the button on the field's line. */
.addrow {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}
.addrow .field {
  flex: 1 1 220px;
  min-width: 0;
}
.addrow .field input,
.addrow .field select {
  margin-bottom: 0;
}
.addrow > button {
  min-height: 48px;
}
.namefield-c {
  max-width: 360px;
}
.namefield-c input {
  margin-bottom: 0;
}
.namefield-c .hint {
  margin: 8px 0 0;
}
.namerow {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}
.namerow .field {
  flex: 1 1 240px;
}
.namerow input {
  margin-bottom: 0;
}
.namerow button {
  min-height: 48px;
}
label.check {
  display: flex;
  gap: 10px;
  align-items: center;
  font-weight: 500;
  color: var(--ink-2);
  margin: 0 0 18px;
  cursor: pointer;
}
label.check input {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
  margin: 0;
}
.countline {
  display: block;
  text-align: right;
  font-size: var(--t-tiny);
  color: var(--ink-3);
  margin: -12px 0 12px;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ buttons
   Plain buttons are small quiet pills; .primary is the one ink action; the
   big ones use brand.css's .btn. */
button {
  font: 600 0.9375rem/1 var(--text);
  min-height: 40px;
  padding: 0 16px;
  border-radius: 999px;
  border: 1.5px solid var(--rule-2);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  white-space: nowrap;
  transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
@media (hover: hover) {
  button:hover:not(:disabled) {
    border-color: var(--ink);
  }
  .looks button:hover:not([aria-checked="true"]):not(:disabled) {
    border-color: var(--rule-2);
    background: var(--surface-2);
  }
}
button:disabled {
  opacity: 0.45;
  cursor: default;
}
button.primary {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
button.primary:hover:not(:disabled) {
  transform: translateY(-1px);
}
button.quiet {
  color: var(--danger);
}
button.quiet:hover:not(:disabled) {
  border-color: var(--danger);
}
button.danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--paper);
}
button.linkish {
  border: 0;
  padding: 0;
  min-height: 0;
  border-radius: 4px;
  background: none;
  color: var(--accent);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 0.18em;
  display: inline;
  white-space: normal;
}
.buttonrow {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin: 4px 0 0;
}
.status {
  font-size: var(--t-small);
  margin-left: 12px;
  color: var(--ink-3);
  line-height: 1.45;
}
.status.ok {
  color: var(--accent);
}
.status.bad {
  color: var(--danger);
}
p.status,
div.status {
  margin: 12px 0 0;
}
/* A message under what it is about. */
.fieldnote {
  display: block;
  margin: 8px 0 0;
  font-size: var(--t-small);
  line-height: 1.45;
  color: var(--ink-3);
}
.fieldnote:empty {
  margin: 0;
}
.fieldnote.ok {
  color: var(--accent);
}
.fieldnote.bad {
  color: var(--danger);
  font-weight: 500;
}
.field .fieldnote,
.combo + .fieldnote {
  margin-top: -10px;
  margin-bottom: 14px;
}
.field .fieldnote:empty,
.combo + .fieldnote:empty {
  margin: 0;
}

/* ------------------------------------------------------------------ disclosures */
details.how {
  margin: 0 0 16px;
  font-size: var(--t-small);
  color: var(--ink-2);
}
details.how > summary,
details.reference > summary {
  cursor: pointer;
  list-style: none;
  color: var(--accent);
  font-weight: 600;
  width: fit-content;
  padding: 6px 0;
  display: flex;
  align-items: center;
  gap: 8px;
}
details.how > summary::-webkit-details-marker,
details.reference > summary::-webkit-details-marker,
details.buildbox > summary::-webkit-details-marker,
details.snips > summary::-webkit-details-marker {
  display: none;
}
details.how > summary::before,
details.reference > summary::before {
  content: "";
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
  flex: none;
}
details[open].how > summary::before,
details[open].reference > summary::before {
  transform: rotate(45deg);
}
details.how p {
  margin: 8px 0 0;
  line-height: 1.6;
}
details.how .formrow,
details.how .addrow {
  margin-top: 14px;
}
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 6px;
}
/* Cards that fold: the title is the summary, the chevron on the right. */
details.buildbox > summary,
details.snips > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
details.buildbox > summary::after,
details.snips > summary::after {
  content: "";
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--ink-3);
  border-bottom: 2px solid var(--ink-3);
  transform: rotate(45deg) translateY(-3px);
  transition: transform 0.15s ease;
  flex: none;
  margin-right: 4px;
}
details.buildbox[open] > summary::after,
details.snips[open] > summary::after {
  transform: rotate(-135deg) translateY(-2px);
}
details.buildbox[open] > summary,
details.snips[open] > summary {
  margin-bottom: 18px;
}
details.buildbox > summary .sumtitle {
  margin: 0;
}
details.buildbox > summary .sumnote {
  display: block;
  font: 400 var(--t-small) / 1.4 var(--text);
  color: var(--ink-3);
  margin-top: 2px;
}
details.snips > summary {
  font: 650 1rem/1.3 var(--text);
  color: var(--ink);
}

/* numbered steps */
.steps {
  margin: 0;
  padding-left: 0;
  list-style: none;
  counter-reset: step;
  display: grid;
  gap: 18px;
}
.steps > li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: 14px;
  align-items: start;
}
.steps > li::before {
  content: counter(step);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--ink);
  display: grid;
  place-items: center;
  font: 600 0.875rem/1 var(--text);
  font-variant-numeric: tabular-nums;
  margin-top: -2px;
}
.steps > li > * {
  grid-column: 2;
}
.steps .formrow,
.steps .addrow {
  margin-top: 12px;
}
.calsteps {
  gap: 12px;
  margin-bottom: 8px;
  font-size: var(--t-small);
}
.calsteps > li::before {
  width: 24px;
  height: 24px;
  font-size: 0.8125rem;
}

/* segmented control (radios) */
.seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 4px;
  margin: 0 0 20px;
  border: 0;
  border-radius: 999px;
  background: var(--surface-2);
  min-width: 0;
}
.seg label {
  margin: 0;
  padding: 9px 16px;
  border-radius: 999px;
  font: 600 0.9375rem/1.2 var(--text);
  color: var(--ink-2);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.seg label:has(input:checked) {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-1), inset 0 0 0 1px var(--rule);
}
.seg label:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.seg input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.seg.units {
  margin: 4px 0 12px;
}
.seg.units label {
  min-width: 56px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ lists */
.actions {
  display: grid;
  margin: 0 0 18px;
}
.action {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px 16px;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid var(--rule);
  font-size: var(--t-small);
}
.action:first-child {
  border-top: 1px solid var(--rule);
}
.action b {
  font-size: 1rem;
}
.action span {
  color: var(--ink-3);
}
.action > div:last-child:not(:first-child),
.action .rowbuttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
  align-items: center;
}
.action button {
  min-height: 36px;
  padding: 0 14px;
  font-size: 0.875rem;
}
.action .problem {
  color: var(--danger);
  font-style: normal;
}
.action .chatty {
  color: var(--warn);
  font-weight: 500;
}
.action button.linkish {
  min-height: 0;
  padding: 0;
  font-size: inherit;
}
.action .who {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.action .who .sprite {
  --s: 36px;
  flex: none;
}
.action .rownote {
  grid-column: 1 / -1;
  margin: 0;
}
.action .rownote:empty {
  display: none;
}
.actions > .empty {
  padding: 14px 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
/* The "…" menu on a row: what's rare and weighty (block, report) waits here. */
.rowmenu {
  position: relative;
}
.rowmenu > summary {
  list-style: none;
  cursor: pointer;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  border: 1.5px solid var(--rule-2);
  color: var(--ink);
}
.rowmenu > summary::-webkit-details-marker {
  display: none;
}
.rowmenu > summary .icon {
  width: 18px;
  height: 18px;
}
.rowmenu[open] > summary,
.rowmenu > summary:hover {
  border-color: var(--ink);
}
.rowmenu .menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 20;
  display: grid;
  gap: 4px;
  min-width: 150px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 14px;
  box-shadow: var(--shadow-2);
}
.rowmenu .menu button {
  justify-content: flex-start;
  border: 0;
  border-radius: 10px;
  width: 100%;
}
.rowmenu .menu button:hover:not(:disabled) {
  background: var(--surface-2);
}

.copybox {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.copybox input {
  margin: 0;
  min-width: 0;
}
.copybox button {
  min-height: 48px;
}
.copyrow {
  margin-bottom: 18px;
}
dl {
  margin: 0;
}

/* ------------------------------------------------------------------ status bars */
#status {
  margin: 0 0 20px;
  padding: 12px 16px;
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: var(--t-small);
  line-height: 1.5;
}
#status:empty {
  padding: 0;
  margin: 0;
  background: none;
}
#status.ok {
  background: var(--accent-soft);
  color: var(--accent);
}
#status.warn {
  background: var(--warn-soft);
  color: var(--warn);
}
#status.error {
  background: var(--danger-soft);
  color: var(--danger);
}

/* A popover (in the top layer, so it shows over setup too), laid out by hand. */
.toast {
  position: fixed;
  inset: auto;
  left: 50%;
  bottom: 28px;
  z-index: 60;
  margin: 0;
  border: 0;
  overflow: visible;
  height: auto;
  width: max-content;
  max-width: min(560px, calc(100vw - 32px));
  padding: 14px 20px;
  border-radius: 14px;
  background: var(--ink);
  color: var(--paper);
  font-weight: 500;
  box-shadow: var(--shadow-2);
  opacity: 0;
  translate: -50% 12px;
  pointer-events: none;
  transition: opacity 0.2s ease, translate 0.25s var(--ease);
}
.toast[data-show="true"] {
  opacity: 1;
  translate: -50% 0;
}
.toast[data-kind="error"] {
  background: var(--danger);
}
/* With something to take back: Undo, pressable while it shows. */
.toast[data-action="true"][data-show="true"] {
  pointer-events: auto;
}
.toast .toast-undo {
  margin-left: 14px;
  min-height: 34px;
  padding: 0 14px;
  border-color: currentColor;
  color: inherit;
  vertical-align: middle;
}
.toast .toast-undo:focus-visible {
  outline-color: currentColor;
}
/* Over setup, clear of its Back and Continue. */
html:has(#onboard[open]) .toast {
  bottom: calc(104px + env(safe-area-inset-bottom));
}
@media (max-width: 959.98px) {
  .toast {
    bottom: calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom));
  }
}

/* ------------------------------------------------------------------ no X3 yet */
.nodevnote {
  display: none;
}
body[data-nodev="true"] .nodevnote {
  display: flex;
}
body[data-nodev="true"] .needs-x3 {
  display: none !important;
}
.emptystate {
  margin: 0 0 20px;
  padding: 28px;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--ink-2);
  gap: 22px;
  align-items: flex-start;
}
.emptystate .sprite {
  --s: 64px;
  flex: none;
}
.emptystate b {
  display: block;
  font: 650 1.125rem/1.3 var(--text);
  margin-bottom: 6px;
}
.emptystate p {
  margin: 0 0 16px;
}

/* ------------------------------------------------------------------ home */
.banner {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: -12px 0 28px;
  padding: 14px 18px;
  border-radius: 16px;
  background: var(--warn-soft);
  color: var(--warn);
  font-weight: 500;
}
.banner .sprite {
  --s: 40px;
  flex: none;
}
.banner p {
  margin: 0;
}
.home-hero {
  display: grid;
  grid-template-columns: minmax(300px, 420px) minmax(0, 1fr);
  gap: clamp(28px, 4.5vw, 72px);
  align-items: start;
}
.desk {
  background: var(--desk);
  border-radius: 28px;
  padding: 40px 28px 26px;
  display: grid;
  /* One column that never grows to fit what's in it: an X3 wider than the
     window (the big one on a phone) is cropped, not the page widened. */
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: 22px;
  min-width: 0;
}
/* Every drawn X3 in the app is one of brand.css's exact sizes, so its
   screen lands the panel's pixels on whole device pixels. */
.desk .x3 {
  --w: var(--x3-sm);
}
.desk .seg {
  margin: 0;
  background: var(--paper);
}
.desk-caption {
  margin: -6px 0 0;
  color: var(--ink-3);
  font-size: var(--t-small);
  text-align: center;
  max-width: 30em;
  text-wrap: balance;
}
.desk-caption:empty {
  display: none;
}
/* Every screen is drawn at one of the exact sizes; from 2x up brand.css
   keeps its pixels hard, and below 2x the smaller sizes are smoothed rather
   than losing rows. */
.x3-screen canvas {
  width: 100%;
  height: 100%;
  display: block;
}
.today {
  min-width: 0;
  padding-top: 8px;
}
.today-title {
  font: 600 var(--t-tiny) / 1.2 var(--text);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 18px;
}
.says {
  margin: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 18px 22px;
  align-items: start;
}
.says .sprite {
  --s: 72px;
  margin-top: 4px;
}
.says blockquote {
  margin: 0;
  font: 500 clamp(1.45rem, 1.1rem + 1vw, 2rem) / 1.25 var(--display);
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: pretty;
}
.says figcaption {
  color: var(--ink-3);
  font-size: var(--t-small);
  margin-top: 8px;
}
.says .says-go {
  margin-top: 10px;
  font-size: var(--t-small);
}
.today-list {
  list-style: none;
  margin: 28px 0 0;
  padding: 0;
  display: grid;
  gap: 10px;
}
.today-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 14px 16px;
  align-items: center;
  padding: 16px 18px;
  border-radius: 16px;
  background: var(--surface);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-1);
}
.today-item > .sprite {
  --s: 40px;
}
.today-item > .icon {
  width: 24px;
  height: 24px;
  margin: 0 8px;
  color: var(--ink);
}
.today-words b {
  display: block;
  font: 650 1.0625rem/1.35 var(--text);
}
.today-words > span {
  display: block;
  margin-top: 2px;
  color: var(--ink-3);
  font-size: var(--t-small);
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.today-words .fieldnote:empty {
  display: none;
}
/* Today's facts: what's next, outside and what Deckle noticed, one to a line,
   with the word for each in the margin. */
.today-facts {
  display: grid;
  margin: 26px 0 0;
  border-top: 1px solid var(--rule);
}
.today-facts > div {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr);
  gap: 4px 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}
.today-facts dt {
  font: 600 var(--t-tiny) / 1.9 var(--text);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.today-facts dd {
  margin: 0;
  color: var(--ink);
  font-size: 1.0625rem;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}
.today-facts .linkish {
  font-size: var(--t-small);
}
.today-sub {
  font: 600 var(--t-tiny) / 1.2 var(--text);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 30px 0 12px;
}
.today-sub + .today-list {
  margin-top: 0;
}
.edition .stories {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: story;
  display: grid;
  gap: 2px;
}
.edition .stories li {
  counter-increment: story;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: 2px 8px;
  padding: 10px 0;
  border-bottom: 1px solid var(--rule);
}
.edition .stories li::before {
  content: counter(story);
  grid-row: span 2;
  font: 700 1.25rem/1.2 var(--display);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.edition .stories li > a {
  font: 500 1.125rem/1.35 var(--display);
  color: var(--ink);
  text-decoration: none;
  text-wrap: pretty;
}
.edition .stories li > a:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
}
.story-meta {
  color: var(--ink-3);
  font-size: var(--t-tiny);
}
.story-meta a {
  color: var(--ink-3);
}
.edition .hint {
  margin: 10px 0 0;
}
.home-block {
  margin-top: 48px;
}
.quick {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}
.quick-tile {
  all: unset;
  box-sizing: border-box;
  cursor: pointer;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 16px;
  align-items: center;
  padding: 18px 20px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-1);
  color: var(--ink-2);
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.quick-tile:hover {
  border-color: var(--rule-2);
  transform: translateY(-2px);
}
.quick-tile:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.quick-tile .px32 {
  color: var(--ink);
}
.quick-tile b {
  display: block;
  font: 650 1.0625rem/1.3 var(--text);
  margin-bottom: 4px;
}
.quick-tile span {
  display: block;
  font-size: var(--t-small);
  line-height: 1.45;
  color: var(--ink-3);
}
.home-empty {
  grid-template-columns: minmax(260px, 380px) minmax(0, 1fr);
  gap: clamp(28px, 4.5vw, 72px);
  align-items: center;
}
body[data-nodev="true"] .home-empty {
  display: grid;
}
.home-empty .desk .x3 {
  --w: var(--x3-sm);
}
.home-empty h2 {
  font-size: var(--t-2);
  line-height: 1.08;
}
.home-empty .lede {
  margin: 16px 0 28px;
}
.home-empty .home-pals {
  max-width: 34rem;
  margin: 28px 0 0;
}
/* With nothing connected, Home leads with connecting: What's new follows. */
body[data-nodev="true"] .home-empty {
  margin-bottom: 32px;
}

/* get started */
#cardStart {
  padding: 28px 28px 12px;
}
.block-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}
.block-head h2 {
  font: 650 1.1875rem/1.3 var(--text);
  letter-spacing: -0.012em;
  margin: 0;
}
.block-head .buttonrow {
  margin: 0;
}
#cardStart .progress {
  margin: 0 0 16px;
  font-size: var(--t-small);
  color: var(--ink-3);
}
.meter {
  display: block;
  height: 6px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
  margin: 10px 0 18px;
}
.meter > i {
  display: block;
  height: 100%;
  width: var(--p, 0%);
  background: var(--accent);
  border-radius: inherit;
  transition: width 0.4s var(--ease);
}
.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
}
.checklist li {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
  padding: 16px 0;
  border-top: 1px solid var(--rule);
}
.checklist .mark {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1.5px solid var(--field);
  display: grid;
  place-items: center;
  font: 700 14px/1 system-ui, sans-serif;
  color: transparent;
}
.checklist li[data-done="true"] .mark {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--paper);
}
.checklist li[data-locked="true"] {
  opacity: 0.55;
}
.checklist li[data-locked="true"] .mark {
  border-style: dashed;
}
.checklist .what b {
  display: block;
  color: var(--ink);
  font-weight: 600;
}
.checklist .what span {
  display: block;
  color: var(--ink-3);
  font-size: var(--t-small);
  margin-top: 2px;
}
.checklist li[data-done="true"] .what b {
  color: var(--ink-3);
  font-weight: 500;
}
.checklist li[data-done="true"] button {
  border-color: transparent;
  color: var(--ink-3);
}

/* ------------------------------------------------------------------ screens
   The X3 is the editor: a strip of every screen, drawn small, across the top;
   the screen's lines beside the X3; and the X3 itself, in a sticky column
   with Publish under it. The code is one button away. */
.strip {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 28px;
  align-items: flex-start;
}
.strip-group {
  min-width: 0;
  max-width: 100%;
}
.strip-label {
  font: 600 var(--t-tiny) / 1.2 var(--text);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 10px;
}
.strip-row {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding: 2px 2px 6px;
  scrollbar-width: thin;
}
.strip .thumb {
  all: unset;
  box-sizing: border-box;
  flex: none;
  display: grid;
  justify-items: center;
  gap: 7px;
  width: 84px;
  padding: 7px 7px 8px;
  border-radius: 14px;
  cursor: pointer;
  color: var(--ink-2);
  font: 500 0.8125rem/1.25 var(--text);
  text-align: center;
  transition: background-color 0.15s ease;
}
.strip .thumb:hover {
  background: var(--surface-2);
}
.strip .thumb:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.thumb-frame {
  display: grid;
  place-items: center;
  width: 64px;
  aspect-ratio: 528 / 792;
  border-radius: 7px;
  overflow: hidden;
  background: var(--eink-paper);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.14), var(--shadow-1);
}
.thumb-frame canvas {
  width: 100%;
  height: 100%;
  display: block;
}
/* An X4's panel is 480 x 800 (html[data-model="x4"], ADR-020). */
[data-model="x4"] .thumb-frame,
[data-model="x4"] .tpl canvas {
  aspect-ratio: 480 / 800;
}
.thumb-label {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.strip .thumb[aria-current="true"] {
  color: var(--ink);
  font-weight: 650;
}
.strip .thumb[aria-current="true"] .thumb-frame {
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--ink);
}
.thumbwrap {
  position: relative;
  flex: none;
  display: grid;
}
.thumbmore {
  position: absolute;
  top: 2px;
  right: 0;
  width: 30px;
  min-height: 30px;
  height: 30px;
  padding: 0;
  border-radius: 999px;
  background: var(--surface);
  border: 1.5px solid var(--rule-2);
  box-shadow: var(--shadow-1);
}
.thumbmore .icon {
  width: 16px;
  height: 16px;
}
.thumbmore[aria-expanded="true"] {
  border-color: var(--ink);
}
.screenmenu {
  position: fixed;
  inset: auto;
  margin: 0;
  display: grid;
  gap: 4px;
  min-width: 190px;
  padding: 6px;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 14px;
  box-shadow: var(--shadow-2);
}
.screenmenu:not([data-open="true"]) {
  display: none;
}
.screenmenu button {
  justify-content: flex-start;
  border: 0;
  border-radius: 10px;
  width: 100%;
}
.screenmenu button:hover:not(:disabled) {
  background: var(--surface-2);
}
.thumb-new .thumb-frame {
  background: transparent;
  box-shadow: none;
  border: 1.5px dashed var(--rule-2);
  color: var(--ink-2);
}
.strip .thumb-new:hover .thumb-frame {
  border-color: var(--ink);
  color: var(--ink);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .thumb-frame canvas {
    filter: brightness(0.84);
  }
}
:root[data-theme="dark"] .thumb-frame canvas {
  filter: brightness(0.84);
}

/* An X3 whose Home is Deckle's room: what the home screen made here is. */
.more-hint {
  margin: 16px 0 0;
  padding: 12px 16px;
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: var(--t-small);
  line-height: 1.5;
  max-width: 44em;
}
/* Add to More: ready-made rows, one tap each, two across where they fit. */
.quickrows-note {
  margin: -8px 0 16px;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: var(--t-small);
  line-height: 1.45;
}
.quickrows-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  column-gap: 28px;
}
.quickrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-width: 0;
  padding: 10px 0;
  border-top: 1px solid var(--rule);
}
.quickrow-words {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.quickrow-words b {
  font-size: 1rem;
  line-height: 1.3;
}
.quickrow-words span {
  color: var(--ink-3);
  font-size: var(--t-small);
  line-height: 1.4;
}
.quickrow button {
  flex: none;
  min-width: 92px;
  min-height: 36px;
  padding: 0 14px;
  font-size: 0.875rem;
  gap: 7px;
}
.quickrow button .icon {
  width: 12px;
  height: 12px;
}
.quickrow button[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
#addRowsStatus:empty {
  display: none;
}

/* The builder's X3 is always one of the exact sizes (--pv-w, set below
   with the preview). */
.screens-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) calc(var(--pv-w) + 48px);
  gap: 28px;
  align-items: start;
}
.screens-main > * + * {
  margin-top: 20px;
}
/* Beside the page, the X3's column stays in view while it fits the window
   (the app measures it); when it doesn't, it scrolls with the page, and
   Publish, at its foot, stays in view at the bottom of the window instead of
   the X3 shrinking. In the page's one column (a phone, or a tablet held
   upright) it always scrolls with the page: held in view there it would
   cover the lines, the code and Advanced's forms as they scrolled under it. */
.screens-side {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
  min-width: 0;
  align-self: start;
}
.screens-side {
  top: 24px;
}
@media (min-width: 960px) {
  .screens-side[data-fits="true"] {
    position: sticky;
  }
}
/* From a laptop up, the builder's X3 starts level with the page's title
   rather than under its introduction, so in a window 800px tall the X3, the
   note under it and Publish are all in view at once. */
@media (min-width: 1200px) {
  #viewScreens {
    display: grid;
    grid-template-columns: minmax(0, 1fr) calc(var(--pv-w) + 48px);
    grid-template-rows: auto auto 1fr;
    column-gap: 28px;
    align-items: start;
  }
  #viewScreens > .screens-layout {
    display: contents;
  }
  #viewScreens > .page-head,
  #viewScreens > #status,
  #viewScreens .screens-main {
    grid-column: 1;
  }
  #viewScreens .screens-main {
    grid-row: 3;
  }
  #viewScreens .screens-side {
    grid-column: 2;
    grid-row: 1 / span 3;
    /* Where it starts (the page's top padding), so it never moves. */
    top: clamp(32px, 4vw, 56px);
  }
}
@media (min-width: 1380px) {
  #viewScreens:has(#panel.actual) {
    grid-template-columns: minmax(0, 1fr) calc(var(--x3-lg) + 48px);
  }
}
/* While the column fits the window it stays in view whole, so Publish keeps
   its place under the X3 rather than sticking over the note. Wherever
   Publish does stick to the bottom of the window (a big X3 in a short
   window, or the narrower layout), the note and what just happened sit
   above the X3, where it never covers them. */
@media (min-width: 1200px) {
  #viewScreens .screens-side[data-fits="true"] .pubbar {
    position: relative;
    bottom: auto;
  }
  #viewScreens .screens-side[data-fits="false"] .pv-status,
  #viewScreens .screens-side[data-fits="false"] .pv-hint {
    order: -1;
  }
}
@media (min-width: 960px) and (max-width: 1199.98px) {
  #viewScreens .screens-side .pv-status,
  #viewScreens .screens-side .pv-hint {
    order: -1;
  }
}
/* The lines on the screen being changed. */
.outline-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.outline-head h2 {
  margin: 0;
}
/* The heading folds the lines away (remembered). */
.outline-head .fold {
  all: unset;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  border-radius: 8px;
}
.outline-head .fold::after {
  content: "";
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--ink-3);
  border-bottom: 2px solid var(--ink-3);
  transform: rotate(45deg) translateY(-3px);
  transition: transform 0.15s ease;
  flex: none;
}
.outline-head .fold[aria-expanded="false"]::after {
  transform: rotate(-45deg);
}
.outline-head .fold:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}
.keys-hint {
  margin: 12px 0 0;
  font-size: var(--t-tiny);
}
/* Keys are for a keyboard: a touch screen doesn't need telling. */
@media (hover: none) and (pointer: coarse) {
  .keys-hint {
    display: none;
  }
}
.outline-head .count {
  color: var(--ink-3);
  font-size: var(--t-small);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.outline-hint {
  margin: 6px 0 16px;
}
.outline-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 14px;
}
.outline-foot .icon,
#showMarkup .icon,
#walletAdd .icon {
  width: 14px;
  height: 14px;
}
.codebar {
  display: flex;
  align-items: center;
  gap: 8px 16px;
  flex-wrap: wrap;
}
.codebar .hint {
  margin: 0;
  flex: 1 1 240px;
}
#showMarkup[aria-expanded="true"] {
  border-color: var(--ink);
}
.codearea > * + * {
  margin-top: 20px;
}

/* Publish, under the X3: what's changed, and the one solid button. */
.pubbar {
  position: sticky;
  bottom: 16px;
  z-index: 4;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  padding: 14px 16px;
  border-radius: 20px;
  background: var(--surface);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-2);
}
.pub-words {
  margin: 0;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 2px 8px;
  color: var(--ink-3);
  font-size: var(--t-small);
  line-height: 1.4;
}
.pub-words b {
  font: 700 1.1875rem/1.2 var(--display);
  color: var(--ink);
}
.pubbar[data-state="dirty"] .pub-words b::before {
  content: "";
  display: inline-block;
  width: 9px;
  height: 9px;
  margin: 0 8px 1px 0;
  border-radius: 50%;
  background: var(--warn);
}
.pubbar #publish {
  width: 100%;
  min-height: 48px;
  font-size: 1rem;
  white-space: normal;
  line-height: 1.2;
}
.pubbar[data-state="clean"] #publish {
  background: transparent;
  border-color: var(--rule-2);
  color: var(--ink-3);
  opacity: 1;
}
.pub-more {
  display: flex;
  gap: 16px;
  justify-content: center;
}
.pub-more:not(:has(button:not([hidden]))) {
  display: none;
}
.pub-more .linkish {
  font-size: var(--t-small);
}
.pub-none {
  display: none;
  margin: 0;
  color: var(--ink-3);
  font-size: var(--t-small);
}
.pubbar[data-state="none"] > :not(.pub-none) {
  display: none;
}
.pubbar[data-state="none"] .pub-none {
  display: block;
}

.preview {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: 14px;
  padding: 24px 20px 18px;
  border-radius: 24px;
  background: var(--desk);
}
/* The preview is exact: the small exact size, the large one (one panel
   pixel to one screen pixel at 1x) wherever the window gives it room, and
   the large one with Zoom where it fits beside the lines. A phone has the
   big phone size (set with the phone's layout). */
:root {
  --pv-w: var(--x3-sm);
}
.preview .x3 {
  --w: var(--pv-w);
}
@media (min-width: 1500px) and (min-height: 900px), (min-width: 1500px) and (max-resolution: 1.49dppx), (min-width: 1500px) and (-webkit-max-device-pixel-ratio: 1.49),
  (min-width: 1200px) and (min-resolution: 1.5dppx) and (max-resolution: 1.99dppx), (min-width: 1200px) and (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 1.99) {
  /* At 1.5x the large exact size is 400px, which fits beside the lines from
     1200px wide. */
  :root {
    --pv-w: var(--x3-lg);
  }
  #zoom {
    display: none;
  }
}
@media (min-width: 1380px) {
  .preview .x3:has(canvas.actual) {
    --w: var(--x3-lg);
  }
  .screens-layout:has(#panel.actual) {
    grid-template-columns: minmax(0, 1fr) calc(var(--x3-lg) + 48px);
  }
}
@media (max-width: 1379.98px) {
  #zoom {
    display: none;
  }
}
#zoom {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  min-width: 40px;
  min-height: 32px;
  padding: 0 12px;
  font-size: 0.8125rem;
  background: var(--surface);
}
#zoom[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
#panel {
  cursor: pointer;
}
.pv-x3[data-dragging] #panel {
  cursor: grabbing;
}
.pv-x3[data-dragging] .pv-plus {
  display: none;
}
/* The line picked on the X3, and the one a click would pick. */
.pv-sel,
.pv-hover {
  position: absolute;
  border-radius: 6px;
  pointer-events: none;
}
.pv-sel {
  box-shadow: 0 0 0 2px var(--accent), 0 0 0 5px rgba(44, 106, 85, 0.18);
  transition: top 0.12s ease, left 0.12s ease, width 0.12s ease, height 0.12s ease;
}
.pv-hover {
  box-shadow: 0 0 0 1.5px rgba(44, 106, 85, 0.55);
  background: rgba(44, 106, 85, 0.05);
}
/* Where a new line would go: a guide across the screen, and a + in the
   margin beside it. */
.pv-guide {
  position: absolute;
  left: 2%;
  right: 2%;
  height: 0;
  border-top: 3px solid var(--accent);
  translate: 0 -1.5px;
  box-shadow: 0 0 0 3px rgba(44, 106, 85, 0.18);
  border-radius: 2px;
  pointer-events: none;
}
.pv-guide::before {
  content: "";
  position: absolute;
  left: -4px;
  top: -5px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}
.pv-gutter {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -26px;
  width: calc(26px + var(--u) * 6);
  cursor: pointer;
}
.pv-plus {
  position: absolute;
  width: 26px;
  height: 26px;
  min-height: 0;
  padding: 0;
  margin: 0;
  border-radius: 50%;
  border: 0;
  background: var(--accent);
  color: var(--paper);
  translate: calc(26px - 50%) -50%;
  box-shadow: var(--shadow-2);
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.pv-plus .icon {
  width: 12px;
  height: 12px;
}
.pv-plus[data-rest="true"] {
  opacity: 0.55;
  transform: scale(0.85);
}
.pv-x3:hover .pv-plus[data-rest="true"],
.pv-plus:hover {
  opacity: 1;
  transform: none;
}
body[data-view="advanced"] .pv-gutter,
body[data-view="advanced"] .pv-guide,
body[data-view="advanced"] #zoom {
  display: none;
}
/* The drawn X3's four face keys, pressable. They sit where brand.css paints
   them: 16% wide, centred at 13%, 37.7%, 62.3% and 87% across. */
.pv-keys {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.pv-key {
  position: absolute;
  top: 91.4%;
  height: 5.2%;
  width: 16%;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  pointer-events: auto;
  cursor: pointer;
}
.pv-key[data-key="prev"] {
  left: 10.92%;
}
.pv-key[data-key="next"] {
  left: 31.67%;
}
.pv-key[data-key="back"] {
  left: 52.33%;
}
.pv-key[data-key="ok"] {
  left: 73.08%;
}
/* The X4 draws its keys lower (brand.css), and its bottom row is BACK, OK,
   PREV, NEXT from the left (ADR-020), as is an X3's set to Back first
   (Settings > Buttons > Bottom keys: html[data-keys], app.html followModel).
   The app puts the buttons in that order too, so Tab meets them as they sit. */
[data-model="x4"] .pv-key {
  top: 91.04%;
  height: 4.73%;
}
[data-model="x4"] .pv-key[data-key="back"],
[data-keys="back-first"] .pv-key[data-key="back"] {
  left: 10.92%;
}
[data-model="x4"] .pv-key[data-key="ok"],
[data-keys="back-first"] .pv-key[data-key="ok"] {
  left: 31.67%;
}
[data-model="x4"] .pv-key[data-key="prev"],
[data-keys="back-first"] .pv-key[data-key="prev"] {
  left: 52.33%;
}
[data-model="x4"] .pv-key[data-key="next"],
[data-keys="back-first"] .pv-key[data-key="next"] {
  left: 73.08%;
}
@media (hover: hover) {
  .pv-key:hover {
    background: rgba(20, 20, 20, 0.08);
  }
}
.pv-key:active {
  background: rgba(20, 20, 20, 0.16);
}
.pv-key:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
/* The tools for the picked line, beside it on the X3. */
.pv-tools {
  position: absolute;
  z-index: 5;
  padding: 6px;
  border-radius: 16px;
  background: var(--surface);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-2);
}
/* One row where the window allows (spilling a little past the X3's card),
   two on a phone. */
.pv-tools {
  max-width: min(400px, calc(100vw - 16px));
}
.pv-toolrow,
.pv-editrow {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px;
  align-items: center;
}
.pv-tools button {
  min-height: 36px;
  padding: 0 12px;
  font-size: 0.875rem;
}
.pv-tools .pv-x,
#pvAdd {
  width: 36px;
  padding: 0;
}
.pv-tools .pv-x {
  border-color: transparent;
}
.pv-tools .pv-x .icon,
#pvAdd .icon {
  width: 14px;
  height: 14px;
}
.pv-editrow input {
  margin: 0;
  min-height: 36px;
  width: 190px;
  padding: 6px 10px;
  font-size: 0.9375rem;
}
.pv-status {
  margin: 0;
  max-width: 280px;
  text-align: center;
}
.pv-status:empty {
  display: none;
}
.pv-hint {
  margin: 0;
  max-width: 280px;
  text-align: center;
  color: var(--ink-3);
  font-size: var(--t-small);
  line-height: 1.45;
  text-wrap: balance;
}
.pv-hint:empty {
  display: none;
}
/* Right after a change, what happened says enough; the standing hint waits. */
.pv-status:not(:empty) + .pv-hint {
  display: none;
}

/* Adding a line: a small panel beside the X3, or a sheet on a phone. */
.addpop {
  position: fixed;
  z-index: 70; /* over the page where popovers aren't in the top layer */
  inset: auto;
  margin: 0;
  width: min(340px, calc(100vw - 24px));
  max-height: calc(100vh - 24px);
  overflow: auto;
  padding: 18px 18px 14px;
  background: var(--surface);
  color: var(--ink-2);
  border: 1px solid var(--rule);
  border-radius: 20px;
  box-shadow: var(--shadow-2), 0 0 0 1px rgba(0, 0, 0, 0.02);
}
.addpop:not([data-open="true"]) {
  display: none;
}
.addpop h2 {
  font: 700 1.25rem/1.2 var(--display);
  margin: 0 0 12px;
  padding-right: 8px;
}
.kinds {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 16px;
  padding: 0;
  border: 0;
  min-width: 0;
}
.kinds label {
  margin: 0;
  padding: 7px 12px;
  border-radius: 999px;
  border: 1.5px solid var(--rule-2);
  font: 600 0.875rem/1.2 var(--text);
  color: var(--ink-2);
  cursor: pointer;
}
.kinds label:has(input:checked) {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
.kinds label:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.kinds input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.addpop input[type="text"],
.addpop select {
  margin-bottom: 12px;
}
.addpop .countline {
  margin: -8px 0 10px;
}
.addpop .buttonrow {
  margin-top: 4px;
}

.sheet.sheet-wide {
  width: min(720px, calc(100vw - 32px));
}
.items {
  list-style: none;
  margin: 0 0 4px;
  padding: 0;
  display: grid;
  gap: 6px;
}
.items li {
  list-style: none;
  position: relative;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: 2px 4px;
  align-items: start;
}
.items li.empty {
  display: block;
}
.items li > input {
  grid-column: 1 / -1;
}
.items li > .itemtools {
  grid-column: 2;
}
/* A handle to drag a line by. */
.grip {
  display: grid;
  place-items: center;
  min-height: 44px;
  color: var(--ink-3);
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  border-radius: 8px;
}
.grip .icon {
  width: 18px;
  height: 18px;
}
.grip[data-fixed] {
  cursor: default;
}
@media (hover: hover) {
  .grip:not([data-fixed]):hover {
    color: var(--ink);
    background: var(--surface-2);
  }
}
.items[data-dragging] {
  cursor: grabbing;
  user-select: none;
  -webkit-user-select: none;
}
.items li[data-dragging] .pickitem {
  opacity: 0.45;
  border-style: dashed;
}
/* Where a dragged line would go: a mark between lines. */
.items li[data-drop="before"]::before,
.items li[data-drop="after"]::after {
  content: "";
  position: absolute;
  left: 22px;
  right: 0;
  height: 3px;
  border-radius: 2px;
  background: var(--accent);
  pointer-events: none;
}
.items li[data-drop="before"]::before {
  top: -5px;
}
.items li[data-drop="after"]::after {
  bottom: -5px;
}
.items .pickitem {
  display: block;
  width: 100%;
  text-align: left;
  white-space: normal;
  padding: 10px 14px;
  border: 1px solid var(--rule);
  border-radius: 12px;
  font: 400 var(--t-small) / 1.45 var(--text);
  color: var(--ink-2);
  min-height: 0;
}
.items .pickitem[aria-current="true"] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
  background: var(--surface-2);
}
.items .pickitem b {
  margin-right: 8px;
}
.items .pickitem .opens {
  display: block;
  color: var(--ink-3);
}
/* On More, a line of the home screen that isn't there. */
.items .pickitem .offmore {
  display: inline-block;
  margin: 0 0 0 8px;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-3);
  font-size: var(--t-tiny);
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
}
.items input {
  margin: 0;
}
.itemtools {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 8px 0 6px;
}
/* New screens start from one of these, each drawn by the X3's renderer. */
.templates {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 10px;
  margin: 0 0 20px;
}
.tpl {
  display: grid;
  grid-template-rows: auto 1fr;
  justify-items: start;
  gap: 10px;
  padding: 10px 10px 12px;
  border-radius: 16px;
  border: 1.5px solid var(--rule);
  background: var(--surface);
  min-height: 0;
  white-space: normal;
  text-align: left;
  font-weight: 400;
}
.tpl canvas {
  width: 100%;
  height: auto;
  aspect-ratio: 528 / 792;
  border-radius: 8px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12);
  background: var(--eink-paper);
}
.tpl b {
  display: block;
  font-size: 0.9375rem;
}
.tpl span span {
  display: block;
  margin-top: 2px;
  color: var(--ink-3);
  font-size: 0.8125rem;
  line-height: 1.35;
}
.tpl[aria-checked="true"] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1.5px var(--ink);
  background: var(--surface-2);
}
.palette {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.palette button {
  min-height: 34px;
  padding: 0 12px;
  font: 500 0.8125rem/1 var(--mono);
}
#markupArea {
  min-width: 0;
}
.plain-editor {
  width: 100%;
  min-height: 360px;
  font: 13.5px/1.65 var(--mono);
}
.CodeMirror {
  height: 56vh;
  min-height: 360px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: 13.5px/1.65 var(--mono);
  box-shadow: var(--shadow-1);
}
.CodeMirror-gutters {
  background: var(--surface-2);
  border-right: 1px solid var(--rule);
  border-radius: var(--radius) 0 0 var(--radius);
}
.CodeMirror-linenumber {
  color: var(--ink-3);
}
.CodeMirror-cursor {
  border-left: 2px solid var(--ink);
}
.CodeMirror-selected,
.CodeMirror-focused .CodeMirror-selected {
  background: var(--accent-soft) !important;
}
/* The editor's colours, a few and quiet: tags in the accent, attributes and
   strings in two inks, comments muted. CodeMirror's own sheet is put before
   this one, so these win, and each has 4.5:1 or more on the editor's ground
   in both themes. */
.CodeMirror .cm-tag {
  color: var(--cm-tag);
  font-weight: 600;
}
.CodeMirror .cm-attribute {
  color: var(--cm-attr);
}
.CodeMirror .cm-string {
  color: var(--cm-string);
}
.CodeMirror .cm-comment {
  color: var(--ink-3);
  font-style: italic;
}
.CodeMirror .cm-bracket,
.CodeMirror .cm-meta {
  color: var(--ink-3);
}
.CodeMirror .cm-error {
  color: var(--danger);
}
.CodeMirror .cm-qualifier,
.CodeMirror .cm-atom,
.CodeMirror .cm-number,
.CodeMirror .cm-keyword,
.CodeMirror .cm-def,
.CodeMirror .cm-variable,
.CodeMirror .cm-builtin {
  color: var(--ink);
}
.CodeMirror div.CodeMirror-cursor {
  border-left-color: var(--ink);
}
.CodeMirror-matchingtag {
  background: var(--accent-soft);
}
:root {
  --cm-tag: #2c6a55;
  --cm-attr: #7d5212;
  --cm-string: #2d5a83;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --cm-tag: #8ccab2;
    --cm-attr: #dcbb85;
    --cm-string: #a9c6e6;
  }
}
:root[data-theme="dark"] {
  --cm-tag: #8ccab2;
  --cm-attr: #dcbb85;
  --cm-string: #a9c6e6;
}
.refpart h3 {
  font: 650 0.9375rem/1.3 var(--text);
  color: var(--ink);
  margin: 18px 0 10px;
}
.refpart dl {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: 8px 16px;
  font-size: var(--t-small);
}
.refpart dd {
  margin: 0;
  color: var(--ink-2);
}
details.reference {
  padding: 20px 28px;
}
details.reference[open] > summary {
  margin-bottom: 8px;
}
.bundle-dl {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 8px 20px;
  font-size: var(--t-small);
}
.bundle-dl dt {
  color: var(--ink-3);
}
.bundle-dl dd {
  margin: 0;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ deckle */
.looks {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: 10px;
  margin-bottom: 20px;
}
.looks button {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 8px;
  padding: 14px 6px 12px;
  border-radius: 16px;
  border: 1.5px solid var(--rule);
  background: var(--surface);
  min-height: 0;
  white-space: normal;
  line-height: 1.2;
  font-weight: 500;
  font-size: 0.875rem;
  color: var(--ink-2);
}
.looks button .sprite {
  --s: 52px;
}
.looks button[aria-checked="true"] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1.5px var(--ink);
  background: var(--surface-2);
  color: var(--ink);
  font-weight: 600;
}
/* The looks found along the way: after the twelve to start with, under a
   heading of their own with how many are found. */
.looks-found {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 2px 12px;
  margin: 14px 0 0;
  font: 600 0.9375rem/1.35 var(--text);
  color: var(--ink);
}
.looks-found .count {
  font-weight: 400;
  font-size: var(--t-tiny);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
/* One not found yet: its shape, soft, in a dashed place of its own, and what
   it waits for. Found and never chosen, it says New. */
.looks button.locked:disabled {
  opacity: 1;
  cursor: default;
  border-style: dashed;
  border-color: var(--rule-2);
  background: transparent;
  color: var(--ink-3);
  font-size: var(--t-tiny);
  line-height: 1.3;
}
.looks button.locked .sprite {
  opacity: 0.14;
}
.looks .new {
  position: absolute;
  top: -9px;
  right: 10px;
  padding: 0.1em 0.55em;
  border-radius: 999px;
  background: var(--accent-soft);
  box-shadow: 0 0 0 2px var(--surface);
  color: var(--accent);
  font: 600 0.6875rem/1.4 var(--text);
}
.lookpreview {
  display: flex;
  gap: 14px 22px;
  flex-wrap: wrap;
  align-items: flex-start;
  margin: 0 0 22px;
  padding: 18px 20px;
  border-radius: 16px;
  background: var(--surface-2);
}
.lookpreview figure {
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 6px;
}
.lookpreview .sprite {
  --s: 48px;
}
.lookpreview figcaption {
  font-size: var(--t-tiny);
  color: var(--ink-3);
}
.lookpreview .about {
  flex-basis: 100%;
  margin: 0;
  font-size: var(--t-small);
  color: var(--ink-2);
}
.memory {
  white-space: pre-wrap;
  font-size: var(--t-small);
  line-height: 1.65;
  color: var(--ink-2);
  background: var(--surface-2);
  border-radius: 14px;
  padding: 16px 18px;
  max-height: 260px;
  overflow: auto;
}
/* More below: the foot fades, so it reads as cut off on purpose. */
.memory[data-more="true"] {
  mask-image: linear-gradient(#000 calc(100% - 56px), transparent);
  -webkit-mask-image: linear-gradient(#000 calc(100% - 56px), transparent);
}
.usage {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin: 6px 0 0;
}
.usage .big {
  font: 700 2.5rem/1 var(--display);
  color: var(--ink);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.usage .of {
  color: var(--ink-3);
}
#cardThinking[data-own="true"] .usage,
#cardThinking[data-own="true"] .meter,
#cardThinking[data-unlimited="true"] .meter {
  display: none;
}
#usageLine {
  margin-top: 0;
}
/* With no limit, the line under the count is where the meter would be. */
#cardThinking[data-unlimited="true"] #usageLine {
  margin-top: 10px;
}

/* ------------------------------------------------------------------ places */
.combo {
  position: relative;
}
.combo input {
  margin-bottom: 18px;
}
.combo-list {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% - 12px);
  z-index: 30;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 14px;
  box-shadow: var(--shadow-2);
  max-height: 320px;
  overflow: auto;
}
.combo-list li {
  display: grid;
  gap: 1px;
  padding: 10px 12px;
  border-radius: 10px;
  cursor: pointer;
}
.combo-list li b {
  font-weight: 600;
}
.combo-list li span {
  color: var(--ink-3);
  font-size: var(--t-small);
}
.combo-list li[aria-selected="true"],
.combo-list li:hover {
  background: var(--surface-2);
}
.combo-list li[aria-selected="true"] {
  box-shadow: inset 3px 0 0 var(--accent);
}
/* With more room above the field than below, it opens upward. */
.combo-list.up {
  top: auto;
  bottom: calc(100% + 6px);
}

/* ------------------------------------------------------------------ waiting */
.srcpanel {
  padding-top: 4px;
}
.browse {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin: 0 0 18px;
}
.browse .hint {
  margin: 0;
  flex: 1;
  min-width: 200px;
}
.feedlogo {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  flex: none;
  object-fit: contain;
  background: #fff;
  padding: 3px;
  box-shadow: inset 0 0 0 1px var(--rule);
}
.feedlogo.letter {
  display: grid;
  place-items: center;
  padding: 0;
  background: var(--surface-2);
  color: var(--ink);
  font: 600 0.875rem/1 var(--text);
}
.action .who .feedlogo {
  width: 26px;
  height: 26px;
  padding: 2px;
}
#imapWhich.bad {
  color: var(--danger);
}

/* ------------------------------------------------------------------ letters */
.codeface {
  font: 700 1.0625rem/1 var(--mono);
  letter-spacing: 0.08em;
  color: var(--ink);
}
/* Everyone you write to, in one list: an X3 friend's companion, or a pen
   pal's initial, and a small word for which. */
.people .action .tag,
#frAskedList .action .tag {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-2);
  font: 600 0.75rem/1.5 var(--text);
  vertical-align: 1px;
}
.action .detail {
  display: block;
}
.action .who .initial {
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent);
  font: 700 1rem/1 var(--display);
}
.invitepanel {
  margin-top: 4px;
}
.invitepanel .copyrow {
  margin: 16px 0 0;
}
.invitebox input {
  font-size: 0.9375rem;
  color: var(--ink-2);
}
.namefield {
  margin-top: 28px;
}
.namefield input {
  max-width: 360px;
  margin-bottom: 0;
}
.namefield .fieldnote {
  margin: 8px 0 0;
}
.thread {
  max-height: 320px;
  overflow: auto;
  display: grid;
  gap: 8px;
  margin: 8px 0 12px;
}
.thread p {
  margin: 0;
  padding: 10px 14px;
  border-radius: 14px;
  background: var(--surface-2);
  font-size: var(--t-small);
  line-height: 1.55;
}
.thread p.mine {
  margin-left: 32px;
  background: var(--accent-soft);
}
.thread p.theirs {
  margin-right: 32px;
}
#frWrite {
  margin: 0 0 16px;
  padding: 20px;
  border-radius: 16px;
  border: 1px solid var(--rule);
}
#frWrite h3.sub {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
#frText {
  margin: 6px 0 12px;
}

/* ------------------------------------------------------------------ bottles and the pal board
   A letter to whoever finds it, and Deckles whose people would like a pen
   pal (ADR-028). A stranger only ever sees a Deckle's card: its look, its
   name, what it's making and what its person likes. */
.bottle-icon {
  width: 36px;
  height: 48px;
  flex: none;
  color: var(--ink);
  fill: currentColor;
  shape-rendering: crispEdges;
}
/* A bottle's trip, and one on the shelf: a quiet well with the bottle in it. */
.trip {
  display: flex;
  gap: 16px;
  align-items: center;
  padding: 18px 20px;
  border-radius: var(--radius);
  background: var(--surface-2);
}
.trip > div {
  min-width: 0;
}
.trip b {
  display: block;
  font: 650 1.0625rem/1.3 var(--text);
  color: var(--ink);
}
.trip .detail {
  display: block;
  margin-top: 2px;
  color: var(--ink-2);
  font-size: var(--t-small);
  line-height: 1.5;
}
.trip .buttonrow {
  margin-top: 14px;
}
.trip.shelf {
  align-items: flex-start;
  margin: 0 0 20px;
}
.trip.shelf .bottle-icon {
  margin-top: 4px;
}
.bt-note {
  margin: -8px 0 18px;
}
/* Bottles are on, and Deckle needs an age band: asked at the top, kindly. */
.bt-ask {
  margin: 0 0 20px;
  padding: 18px 20px;
  border-radius: var(--radius);
  background: var(--accent-soft);
  color: var(--ink);
}
.bt-ask-words {
  margin: 0 0 14px;
  line-height: 1.55;
}
.bt-ask .seg {
  margin: 0;
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--rule);
}
.bt-ask .seg label:has(input:checked) {
  background: var(--ink);
  color: var(--paper);
  box-shadow: none;
}
.bt-ask .hint {
  margin: 12px 0 0;
  color: var(--ink-2);
}
.bt-asknote {
  margin: -8px 0 18px;
}
.bt-asknote:empty {
  display: none;
}
/* Thrown, drifting, found: a line that fills in, with a dot for each. */
.trip-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 18px;
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  font: 600 0.8125rem/1.3 var(--text);
  color: var(--ink-3);
}
.trip-steps li {
  position: relative;
  margin: 0;
  padding: 12px 0 0;
  border-top: 2px solid var(--rule);
}
.trip-steps li::before {
  content: "";
  position: absolute;
  top: -6px;
  left: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: inset 0 0 0 2px var(--rule-2);
}
.trip-steps li.done {
  color: var(--ink-2);
  border-top-color: var(--ink);
}
.trip-steps li.done::before {
  background: var(--ink);
  box-shadow: none;
}
.trip-steps li.now {
  color: var(--ink);
}
.trip-steps li.now::before {
  box-shadow: inset 0 0 0 2px var(--ink);
}
.bt-throwrow {
  margin-top: 20px;
}
#btThrowHint,
#btFailed {
  margin-bottom: 0;
}
#btStatus:empty {
  display: none;
}
/* Labels that sit over a group, a letter or a choice. */
.fieldlabel,
label.fieldlabel {
  display: block;
  margin: 18px 0 4px;
  font: 600 var(--t-body) / 1.5 var(--text);
  color: var(--ink);
}
.fieldlabel span {
  font-weight: 500;
  color: var(--ink-3);
}
#btCompose .fieldlabel {
  margin-top: 0;
}
textarea.letterbox {
  min-height: 180px;
  line-height: 1.55;
}
#writeText {
  min-height: 220px;
}
.bt-gorow {
  margin-top: 16px;
}
/* Why a bottle can't go yet, in plain words. */
.refused {
  margin: 10px 0 0;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--warn-soft);
  color: var(--ink);
  font-size: var(--t-small);
  line-height: 1.5;
}
.refused b {
  display: block;
  margin-bottom: 2px;
}
/* A Deckle's card: what a stranger sees. */
.palcard {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 18px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
}
.palcard .sprite {
  --s: 56px;
  flex: none;
}
.palcard > div {
  min-width: 0;
}
.palcard b {
  display: block;
  font: 650 1.0625rem/1.3 var(--text);
  color: var(--ink);
}
.palcard .detail {
  display: block;
  margin-top: 2px;
  color: var(--ink-2);
  font-size: var(--t-small);
}
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
}
.tags li {
  margin: 0;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-2);
  font: 600 0.8125rem/1.6 var(--text);
}
/* Interests to pick (three at most), and the board's filters. */
.tagpick {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 6px 0 4px;
}
.tagpick button[aria-pressed] {
  min-height: 0;
  padding: 6px 13px;
  border-radius: 999px;
  font: 600 0.875rem/1.2 var(--text);
}
.tagpick button[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
.bt-age {
  margin-bottom: 6px;
}
.bt-lang {
  margin-top: 16px;
}
.bt-lang select {
  margin-bottom: 0;
}
#btSaveStatus,
#pbSaveStatus {
  margin-top: 10px;
}
.bt-safety {
  margin-top: 14px;
}

/* ------------------------------------------------------------------ keepsakes (ADR-031)
   Letters to later: who, and when it opens, never a word until it has. The
   travelling notebook a bottle's way brought: each room's line by its
   Deckle's name, and the copies kept. */
.later-list {
  margin: 4px 0 18px;
}
.later-list[hidden] {
  display: none;
}
.action.later .who {
  align-items: flex-start;
}
.sealed-icon {
  width: 40px;
  height: 30px;
  flex: none;
  margin-top: 2px;
  color: var(--ink);
  fill: currentColor;
  shape-rendering: crispEdges;
}
.action.later .tag {
  white-space: nowrap;
}
.action.later .detail {
  display: block;
  margin-top: 2px;
  color: var(--ink-2);
  line-height: 1.5;
}
.later-read {
  grid-column: 1 / -1;
  margin: 2px 0 0;
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--ink);
  font-size: 1rem;
  line-height: 1.6;
  white-space: pre-wrap;
}
.lt-writerow {
  margin-top: 4px;
}
#ltStatus:empty {
  display: none;
}
.lt-to {
  margin: 0 0 16px;
}
#ltOpens {
  width: 100%;
  max-width: 260px;
  font: 400 1rem/1.45 var(--text);
  color: var(--ink);
  background-color: var(--field-bg);
  border: 1px solid var(--field);
  border-radius: 12px;
  padding: 11px 14px;
  min-height: 48px;
  margin: 0 0 4px;
  color-scheme: light dark;
}
#ltOpens:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.lt-when .hint {
  display: block;
  margin: 0 0 4px;
}
.lt-gorow {
  margin-top: 16px;
}
.notebook-icon {
  width: 36px;
  height: 42px;
}
/* On a phone its lines want the card's whole width: the notebook over them. */
@media (max-width: 600px) {
  .trip.nb-held {
    flex-direction: column;
    gap: 12px;
  }
  .trip.nb-held > div {
    width: 100%;
  }
}
.nb-held .fieldlabel {
  margin-top: 16px;
}
.nb-held input {
  margin-bottom: 0;
}
.nb-lines {
  display: grid;
  gap: 10px;
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
}
.nb-lines li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0 12px;
  margin: 0;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.nb-lines li.ours {
  box-shadow: inset 0 0 0 1.5px var(--ink);
}
.nb-room {
  grid-column: 1;
  font: 600 0.8125rem/1.4 var(--text);
  color: var(--ink-3);
}
.nb-text {
  grid-column: 1;
  color: var(--ink);
  line-height: 1.5;
}
.nb-report {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  font-size: 0.8125rem;
  color: var(--ink-3);
}
.nb-hint {
  margin-bottom: 0;
}
.nb-copies {
  margin-top: 18px;
}
.nb-copy + .nb-copy {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
}
.nb-copy-q {
  margin: 0;
  font: 650 1rem/1.4 var(--text);
  color: var(--ink);
}
.nb-copies .nb-lines li {
  background: var(--surface-2);
}
/* The knocker's card, in Friend requests: the whole width for it, and the
   answers under its words. */
.action.knock {
  grid-template-columns: minmax(0, 1fr);
}
.action.knock .who {
  align-items: flex-start;
}
.action.knock .rowbuttons {
  justify-content: flex-start;
  padding-left: 68px;
}
@media (max-width: 600px) {
  .action.knock .rowbuttons {
    padding-left: 0;
  }
}
.action.knock .who .sprite {
  --s: 56px;
}
.action .knock-line {
  margin-top: 4px;
  color: var(--ink-2);
}
.action .tags {
  margin-top: 8px;
}
.action .tags li {
  color: var(--ink-2);
}
/* The pal board. */
.page-title .pill.exp {
  margin-left: 0.4em;
  padding: 0.3em 0.8em;
  vertical-align: 0.55em;
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--rule-2);
  color: var(--ink-2);
  font: 600 0.8125rem/1.3 var(--text);
  letter-spacing: 0;
  white-space: nowrap;
}
.board-filters {
  margin: 0 0 20px;
}
.board-status:empty {
  display: none;
}
.board-status {
  margin: 0 0 16px;
}
.board-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px;
}
.board-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  padding: 22px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
}
.board-card .sprite {
  --s: 64px;
  margin-bottom: 8px;
}
.board-card .board-name {
  margin: 0;
  font: 700 1.25rem/1.2 var(--display);
  letter-spacing: -0.01em;
  color: var(--ink);
}
.board-card .detail {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--t-small);
}
.board-card .tags {
  margin: 8px 0 14px;
}
.board-card .buttonrow {
  margin-top: auto;
}
.board-card .sent {
  margin: 0;
  color: var(--ink-3);
  font: 600 var(--t-small) / 1.4 var(--text);
}
.board-card[tabindex="-1"]:focus {
  outline: none;
}
.board-empty {
  display: flex;
}
.board-empty p {
  margin-bottom: 0;
}
.board-empty button {
  margin-top: 14px;
}
.board-foot {
  margin-top: 28px;
  max-width: 760px;
}
.board-foot .palcard {
  max-width: 460px;
}
.board-hint {
  margin-top: 14px;
}
#pbAgeBox .fieldlabel {
  margin-top: 0;
}
/* Knocking on a door. */
.knock-look {
  margin: 0 0 6px;
}
.knock-hint {
  margin: 14px 0 0;
}
#knockStatus:empty {
  display: none;
}
/* Writing back on the phone: who it's to, their letter folded away. */
.write-head {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0 0 14px;
}
.write-head .sprite {
  --s: 56px;
  flex: none;
}
.write-head .initial {
  flex: none;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent);
  font: 700 1.5rem/1 var(--display);
}
.write-head > div {
  min-width: 0;
}
/* The title shares its line with the close button. */
.write-head h2 {
  margin: 0 40px 0 0;
}
.write-head .detail {
  display: block;
  color: var(--ink-2);
  font-size: var(--t-small);
}
.write-theirs {
  margin-bottom: 4px;
}
.write-theirs p {
  max-height: 40vh;
  overflow: auto;
  white-space: pre-line;
}
.write-hint {
  margin: 14px 0 0;
}
#writeStatus:empty {
  display: none;
}
/* Their photo, folded away with their letter: its print, pixel for pixel. */
.write-theirs-photo {
  display: block;
  width: 150px;
  max-width: 100%;
  height: auto;
  margin: 12px 0 2px;
  border: 1px solid var(--rule-2);
  background: #fff;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}
.write-theirs-photo[hidden] {
  display: none;
}

/* ------------------------------------------------------------------ a photo with a letter
   Added under the letter, and shown as the X3 it goes to will show it: the
   photo's own screen, drawn by the X3's renderer (functions/photos.mjs). */
.photo-pick {
  margin: 4px 0 14px;
}
.photo-pick[hidden],
.photo-chosen[hidden],
.photo-add[hidden] {
  display: none;
}
.photo-add {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.photo-add .icon {
  width: 18px;
  height: 18px;
}
.photo-chosen {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px 20px;
}
.photo-x3 {
  --w: var(--x3-sm);
}
.photo-words {
  flex: 1 1 220px;
  min-width: 0;
}
.photo-note {
  margin: 0 0 8px;
  color: var(--ink);
  font-size: var(--t-small);
  line-height: 1.5;
}
.photo-hint {
  margin: 0 0 12px;
}
.photo-pick .refused {
  margin-top: 12px;
}
.photo-pick .status:empty {
  display: none;
}
.photo-pick .status {
  margin: 8px 0 0;
}
/* In the thread: a photo went with this letter. */
.thread .thread-photo {
  display: block;
  margin-top: 4px;
  color: var(--ink-3);
  font-size: var(--t-tiny);
  font-style: italic;
}

/* ------------------------------------------------------------------ device */
.connstate {
  margin: 0 0 16px;
  padding: 14px 16px;
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--ink-2);
}
.connstate[data-ok="true"] {
  background: var(--accent-soft);
  color: var(--accent);
}
.connstate[data-ok="stale"],
.connstate[data-ok="late"] {
  background: var(--warn-soft);
  color: var(--warn);
}
.connhelp,
.ob-waithelp {
  margin: 0 0 16px;
  padding: 16px 18px;
  border-radius: 12px;
  border: 1px solid var(--rule);
  font-size: var(--t-small);
}
.connhelp p,
.ob-waithelp p {
  margin: 0 0 6px;
}
.connhelp ul,
.ob-waithelp ul {
  margin: 0;
  padding-left: 18px;
  display: grid;
  gap: 4px;
}
#connAnother {
  margin: 0 0 16px;
}
.devlist {
  display: grid;
  /* Three across at most, two on a phone. */
  grid-template-columns: repeat(auto-fill, minmax(max(140px, calc((100% - 48px) / 3)), 1fr));
  gap: 0 24px;
}
.devlist > div {
  padding: 14px 0;
  border-top: 1px solid var(--rule);
}
.devlist dt {
  color: var(--ink-3);
  font-size: var(--t-small);
}
.devlist dd {
  margin: 2px 0 0;
  color: var(--ink);
}
/* The numbers themselves, set large, with a word under them when needed. */
.devlist .stat {
  display: block;
  font: 700 1.75rem/1.15 var(--display);
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
}
.devlist .statnote {
  display: block;
  margin-top: 2px;
  color: var(--ink-3);
  font-size: var(--t-small);
  line-height: 1.4;
}
.devlist .statnote:empty {
  display: none;
}
.devlist .stat[data-kind="update"],
.devlist .stat[data-kind="low"] {
  color: var(--warn);
}
.devlist .stat[data-kind="ok"] {
  color: var(--accent);
}
.removebox {
  margin-top: 22px;
  padding-top: 20px;
  border-top: 1px solid var(--rule);
}
.removebox .hint {
  margin-top: 10px;
}
.dangerzone {
  border-color: var(--rule);
  box-shadow: none;
  background: transparent;
}
.wallet {
  display: grid;
  gap: 12px;
  margin: 0 0 14px;
}
.wallet-row {
  margin: 0;
  padding: 16px 16px 6px;
  border: 1px solid var(--rule);
  border-radius: 16px;
  min-width: 0;
}
.wallet-row .formrow + .formrow,
.wallet-row .formrow + .field {
  margin-top: 0;
}
.wallet-remove {
  font-size: var(--t-small);
  margin: 0 0 10px;
}
.qrbox {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 20px;
  align-items: center;
  margin-top: 18px;
  padding: 18px;
  border-radius: 16px;
  background: var(--surface-2);
}
.qrbox canvas {
  border-radius: 10px;
  image-rendering: pixelated;
  background: #fff;
}
.qrbox .hint {
  margin: 0;
}
@media (max-width: 600px) {
  .qrbox {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
  }
}

/* ------------------------------------------------------------------ dialogs */
dialog {
  color: var(--ink-2);
}
dialog::backdrop {
  background: rgba(18, 18, 16, 0.42);
}
#feedPicker {
  width: min(980px, calc(100vw - 32px));
  height: min(820px, calc(100vh - 32px));
  padding: 0;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 24px;
  box-shadow: var(--shadow-2);
}
#feedPicker[open] {
  display: flex;
  flex-direction: column;
}
.picker-head {
  padding: 22px 24px 14px;
  border-bottom: 1px solid var(--rule);
  display: grid;
  gap: 14px;
}
.picker-title {
  display: flex;
  align-items: center;
  gap: 12px;
}
.picker-title h2 {
  font: 700 1.5rem/1.15 var(--display);
  margin: 0 auto 0 0;
}
.picker-title .count {
  color: var(--accent);
  font-size: var(--t-small);
  font-weight: 600;
}
.picker-head input[type="search"] {
  margin: 0;
}
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.chips button {
  flex: none;
  min-height: 34px;
  padding: 0 13px;
  font-size: 0.8125rem;
  font-weight: 600;
}
.chips button[aria-pressed="true"] {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.picker-body {
  overflow: auto;
  padding: 18px 24px 24px;
  flex: 1;
}
.picker-body h3 {
  font: 600 var(--t-small) / 1.2 var(--text);
  color: var(--ink-3);
  margin: 22px 0 10px;
}
.picker-body h3:first-child {
  margin-top: 0;
}
.feedgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: 10px;
}
.feed {
  border: 1px solid var(--rule);
  border-radius: 16px;
  background: var(--surface);
}
.feed[data-on="true"] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}
.feed .pick {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 12px;
  align-items: start;
  width: 100%;
  padding: 12px 14px;
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: 16px;
  line-height: 1.4;
  white-space: normal;
  min-height: 0;
  font-weight: 400;
}
.feed .pick:hover:not(:disabled) {
  background: var(--surface-2);
}
.feed .name {
  display: block;
  color: var(--ink);
  font-weight: 600;
  font-size: 0.9375rem;
}
.feed .blurb {
  display: block;
  color: var(--ink-3);
  font-size: 0.8125rem;
  margin-top: 2px;
}
.feed .rate {
  display: block;
  color: var(--ink-3);
  font-size: 0.8125rem;
  margin-top: 4px;
}
.feed .rate.busy {
  color: var(--warn);
  font-weight: 500;
}
.feed .tick {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1.5px solid var(--field);
  display: grid;
  place-items: center;
  font: 700 13px/1 system-ui, sans-serif;
  color: transparent;
  margin-top: 3px;
}
.feed[data-on="true"] .tick {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
.feed .focus {
  padding: 0 14px 14px;
}
.feed .focus input {
  margin: 0;
  min-height: 42px;
  font-size: 0.9375rem;
}
.feed .focus p {
  margin: 6px 0 0;
  font-size: 0.8125rem;
  color: var(--ink-3);
  line-height: 1.45;
}
.feed .focus p.busy {
  color: var(--warn);
}
.picker-foot {
  padding: 14px 24px;
  border-top: 1px solid var(--rule);
  display: flex;
  align-items: center;
  gap: 16px;
}
.picker-foot .hint {
  margin: 0 auto 0 0;
}
.picker-foot .short {
  display: none;
}

.sheet {
  width: min(540px, calc(100vw - 32px));
  max-height: calc(100vh - 32px);
  padding: 0;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 24px;
  box-shadow: var(--shadow-2);
}
.sheet-body {
  position: relative;
  padding: 28px;
}
.sheet h2 {
  font: 700 1.75rem/1.1 var(--display);
  margin: 0 0 8px;
}
.sheet .card-lede {
  margin-bottom: 20px;
}
.sheet-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 40px;
  padding: 0;
  border-color: transparent;
}
.sheet-close .icon {
  width: 18px;
  height: 18px;
}
.more-list {
  display: grid;
  gap: 4px;
  margin: 0 0 8px;
}
.more-list a {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 14px;
  align-items: center;
  padding: 12px;
  border-radius: 16px;
  text-decoration: none;
  color: var(--ink-2);
}
.more-list a:hover,
.more-list a[aria-current="page"] {
  background: var(--surface-2);
}
.more-list .icon-wrap {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--surface-2);
  display: grid;
  place-items: center;
  color: var(--ink);
}
.more-list b {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 1.0625rem;
}
.more-list span span {
  display: block;
  font-size: var(--t-small);
  color: var(--ink-3);
}
/* a count in a heading of the sheet keeps its own look */
.more-list .badge {
  display: inline-grid;
  color: var(--paper);
  font-size: 0.75rem;
}

/* ------------------------------------------------------------------ onboarding
   A page of its own over the app: one question at a time, a big headline,
   and the X3 beside it showing what the answer changes. */
#onboard {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--paper);
  color: var(--ink-2);
  overflow: hidden;
}
#onboard[open] {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
}
#onboard::backdrop {
  background: var(--paper);
}
/* The page behind stays where it was while setup is open. */
html:has(#onboard[open]) {
  overflow: hidden;
}
.ob-top {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  min-height: 76px;
  padding: 14px max(clamp(16px, 4vw, 40px), env(safe-area-inset-right)) 14px max(clamp(16px, 4vw, 40px), env(safe-area-inset-left));
}
.ob-top .brand {
  justify-self: start;
  font-size: 1.5rem;
}
.ob-top .brand .sprite {
  --s: 26px;
}
#obSkip {
  justify-self: end;
}
.ob-dots {
  display: flex;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ob-dots li {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--rule-2);
  transition: width 0.3s var(--ease), background-color 0.3s ease;
}
.ob-dots li[data-state="done"] {
  background: var(--ink-3);
}
.ob-dots li[data-state="now"] {
  width: 28px;
  background: var(--ink);
}
.ob-stage {
  overflow-y: auto;
  overscroll-behavior: contain;
  display: grid;
  padding: 8px max(clamp(16px, 4vw, 40px), env(safe-area-inset-right)) 32px max(clamp(16px, 4vw, 40px), env(safe-area-inset-left));
}
/* Every step starts at the same place: the headline never jumps as the
   steps change, whatever their length. */
.ob-step {
  width: min(1120px, 100%);
  margin: 0 auto;
  padding-top: clamp(16px, 7vh, 80px);
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  gap: clamp(32px, 6vw, 104px);
  align-items: start;
}
.ob-step[hidden] {
  display: none;
}
@media (prefers-reduced-motion: no-preference) {
  .ob-step.enter .ob-copy,
  .ob-step.enter .ob-visual {
    animation: ob-in 0.42s var(--ease) both;
  }
  .ob-step.enter .ob-visual {
    animation-delay: 0.06s;
  }
  @keyframes ob-in {
    from {
      opacity: 0;
      transform: translateY(10px);
    }
  }
}
.ob-copy {
  min-width: 0;
  max-width: 34em;
}
.ob-copy h1,
.ob-copy h1 label {
  font: 700 clamp(2.4rem, 1.5rem + 3vw, 4.1rem) / 1.02 var(--display);
  letter-spacing: -0.026em;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
  cursor: default;
}
.ob-copy .lede {
  margin: 20px 0 0;
}
.ob-form {
  margin-top: 32px;
}
.ob-form label {
  font-size: 1rem;
}
.ob-form input[type="text"],
.ob-form textarea {
  font-size: 1.125rem;
  min-height: 56px;
  padding: 14px 16px;
  border-radius: 14px;
}
.ob-form textarea {
  min-height: 96px;
}
.ob-form .fieldnote {
  margin: -10px 0 16px;
}
.ob-form .seg.units {
  margin-top: 0;
}
.ob-note {
  margin: 4px 0 0;
  color: var(--ink-3);
  font-size: var(--t-small);
}
.ob-visual {
  display: grid;
  justify-items: center;
  align-content: start;
  min-width: 0;
}
.ob-visual .x3 {
  --w: var(--x3-sm);
}
.ob-hello {
  --s: clamp(160px, 22vw, 260px);
}
.codeinput {
  font: 700 clamp(2.1rem, 1.6rem + 2vw, 2.9rem) / 1 var(--text) !important;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  text-align: center;
  padding: 16px 12px 16px calc(12px + 0.34em) !important;
  min-height: 88px !important;
  font-variant-numeric: tabular-nums;
  border-radius: 18px !important;
}
.codeinput::placeholder {
  color: var(--ink-3);
  opacity: 0.4;
}
.ob-choices {
  display: grid;
  gap: 12px;
  margin-top: 32px;
}
/* Which one it is, an X3 or an X4 (in preview), on the step that shows it. */
.ob-model {
  margin-top: 28px;
}
.ob-model .seg {
  margin: 0;
}
.ob-model .fieldnote {
  margin: 10px 0 0;
}
.ob-model + .ob-choices {
  margin-top: 28px;
}
.choice {
  all: unset;
  box-sizing: border-box;
  cursor: pointer;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 16px;
  align-items: center;
  padding: 18px 20px;
  border-radius: 20px;
  border: 1.5px solid var(--rule);
  background: var(--surface);
  color: var(--ink-2);
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.choice:hover {
  border-color: var(--ink);
}
.choice:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.choice b {
  display: block;
  font: 650 1.125rem/1.3 var(--text);
  color: var(--ink);
}
.choice > span:nth-child(2) > span {
  display: block;
  color: var(--ink-3);
  font-size: var(--t-small);
  margin-top: 2px;
}
.choice .glyph {
  width: 44px;
  height: 44px;
  border-radius: 14px;
  background: var(--surface-2);
  display: grid;
  place-items: center;
  color: var(--ink);
}
.choice .go {
  color: var(--ink-3);
}
.choice[data-done="true"] {
  border-color: var(--accent);
}
.choice[data-done="true"] .go {
  color: var(--accent);
}
/* A choice that opens after setup: a box to tick. */
.choice .pick {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  border: 1.5px solid var(--field);
  display: grid;
  place-items: center;
}
.choice[aria-pressed="true"] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1.5px var(--ink);
}
.choice[aria-pressed="true"] .pick {
  background: var(--ink);
  border-color: var(--ink);
}
.choice[aria-pressed="true"] .pick::after {
  content: "";
  width: 10px;
  height: 5px;
  border-left: 2.5px solid var(--paper);
  border-bottom: 2.5px solid var(--paper);
  transform: translateY(-1px) rotate(-45deg);
}
.ob-steps {
  margin-top: 28px;
}
.ob-steps .btn {
  margin-top: 12px;
}
.ob-looks {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 8px;
  margin: 28px 0 22px;
}
.ob-looks button {
  padding: 10px 4px 8px;
  font-size: 0.8125rem;
  border-radius: 14px;
}
.ob-looks button .sprite {
  --s: 44px;
}
/* Paired, and waiting for it to say hello: a soft ring breathes around the
   X3; when it checks in, a tick. Both sit on a wrapper, because the drawn
   X3's own ::before and ::after are its side keys and Power key. */
.ob-badge {
  position: relative;
  width: fit-content;
  margin-inline: auto;
}
.ob-badge::before {
  content: "";
  position: absolute;
  inset: -16px;
  border-radius: 40px;
  border: 2px solid var(--accent);
  opacity: 0;
  pointer-events: none;
}
/* Six breaths, then a still ring: waiting shouldn't move forever. */
.ob-badge[data-wait="true"]::before {
  opacity: 0.4;
}
@media (prefers-reduced-motion: no-preference) {
  .ob-badge[data-wait="true"]::before {
    animation: hello-wait 2.6s ease-in-out 6;
  }
  @keyframes hello-wait {
    0% {
      opacity: 0;
      transform: scale(0.98);
    }
    50% {
      opacity: 0.5;
    }
    100% {
      opacity: 0;
      transform: scale(1.03);
    }
  }
}
.ob-badge[data-wait="still"]::before {
  opacity: 0.4;
}
.ob-badge::after {
  content: "";
  position: absolute;
  right: -12px;
  top: -12px;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 28px no-repeat;
  box-shadow: var(--shadow-2);
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 0.3s ease, transform 0.45s var(--ease);
  z-index: 2;
}
.ob-badge[data-on="true"]::after {
  opacity: 1;
  transform: scale(1);
}
.ob-waithelp {
  margin-top: 24px;
}
.ob-foot {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px max(clamp(16px, 4vw, 40px), env(safe-area-inset-right)) calc(18px + env(safe-area-inset-bottom)) max(clamp(16px, 4vw, 40px), env(safe-area-inset-left));
  border-top: 1px solid var(--rule);
  background: var(--paper);
}
.ob-foot .ob-status {
  flex: 1;
  margin: 0;
  text-align: right;
  font-size: var(--t-small);
  color: var(--ink-3);
}
.ob-foot .ob-status.bad {
  color: var(--danger);
  font-weight: 500;
}
.ob-foot .ob-status.ok {
  color: var(--accent);
}
.ob-foot #obNext {
  margin-left: auto;
}

/* ------------------------------------------------------------------ support
   The inbox of the person who runs Deckle: one card per message, folded to
   its first line, who wrote and when; open, the whole message and what to do
   with it. */
.tickets {
  display: grid;
  gap: 12px;
  max-width: 780px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.card.ticket {
  padding: 0;
}
.ticket > summary {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  gap: 4px 14px;
  padding: 18px 22px;
  border-radius: var(--radius);
  list-style: none;
  cursor: pointer;
}
.ticket > summary::-webkit-details-marker {
  display: none;
}
.ticket > summary:hover {
  background: var(--surface-2);
}
.ticket[open] > summary {
  border-radius: var(--radius) var(--radius) 0 0;
  border-bottom: 1px solid var(--rule);
}
.ticket-first {
  grid-column: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ticket-meta {
  grid-column: 2;
  color: var(--ink-3);
  font-size: var(--t-small);
}
.tstatus {
  grid-row: 1 / span 2;
  align-self: start;
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-2);
  font: 600 0.75rem/1 var(--text);
}
.tstatus.s-new {
  background: var(--accent-soft);
  color: var(--accent);
}
.tstatus.s-closed {
  color: var(--ink-3);
}
.ticket-text {
  margin: 0;
  padding: 18px 22px 0;
  color: var(--ink);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.ticket-reply {
  margin: 12px 22px 0;
  color: var(--ink-3);
  font-size: var(--t-small);
  overflow-wrap: anywhere;
}
.ticket .buttonrow {
  padding: 16px 22px 20px;
}
.tickets-empty {
  display: flex;
  max-width: 780px;
}
#viewSupport .page-actions .seg {
  margin: 0;
}
@media (max-width: 600px) {
  .ticket > summary {
    padding: 16px 18px;
  }
  .ticket-text {
    padding: 16px 18px 0;
  }
  .ticket-reply {
    margin: 12px 18px 0;
  }
  .ticket .buttonrow {
    padding: 14px 18px 18px;
  }
}

/* ------------------------------------------------------------------ responsive */
@media (max-width: 959.98px) {
  .page-head {
    margin-bottom: 24px;
  }
  .home-hero,
  .home-empty {
    grid-template-columns: minmax(0, 1fr);
    gap: 28px;
  }
  /* On a phone, what needs you comes first; the X3 follows it. */
  .home-hero .today {
    order: -1;
    padding-top: 0;
  }
  .desk {
    padding: 28px 16px 20px;
  }
  /* Home's X3 on a phone is the big one: 400px at 3x (its bezel cropped a
     little by the window on a phone). */
  .home-hero .desk .x3 {
    --w: var(--x3-ph);
  }
  .home-block {
    margin-top: 36px;
  }
  .banner {
    margin-top: -8px;
  }
  /* On a phone the X3 comes straight after the strip, the lines after it,
     and Publish waits just above the tab bar. The X3 scrolls with the page
     (only beside it does it stay in view). */
  .screens-layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 20px;
  }
  .screens-main {
    display: contents;
  }
  .screens-main > * + * {
    margin-top: 0;
  }
  /* Add to More stays first, as it is at every size. */
  .quickrows {
    order: -3;
  }
  .strip {
    order: -2;
  }
  .screens-side {
    order: -1;
  }
  /* On Advanced the X3 shows the live screen being written, so it follows
     that form, and the page starts with its own controls. */
  #paneLive {
    order: -2;
  }
  .pubbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
    z-index: 24;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 6px 12px;
    padding: 10px max(16px, env(safe-area-inset-right)) 10px max(16px, env(safe-area-inset-left));
    border-radius: 0;
    border-width: 1px 0 0;
    box-shadow: 0 -8px 20px -16px rgba(0, 0, 0, 0.25);
  }
  .pubbar #publish {
    width: auto;
    min-height: 44px;
    padding: 0 18px;
    font-size: 0.9375rem;
  }
  .pub-more {
    grid-column: 1 / -1;
    justify-content: flex-start;
  }
  .pubbar[data-state="clean"] .pub-words {
    grid-column: 1 / -1;
  }
  .pubbar[data-state="clean"] #publish {
    display: none;
  }
  /* Under the page's last line, room for Publish as tall as it is
     (--pub-h, measured by the app), so the last field and its status
     scroll clear of it; a toast sits just above it. */
  body[data-view="screens"] .main {
    padding-bottom: calc(var(--tabbar-h) + var(--pub-h, 110px) + 40px + env(safe-area-inset-bottom));
  }
  body[data-view="screens"] .toast {
    bottom: calc(var(--tabbar-h) + var(--pub-h, 96px) + 12px + env(safe-area-inset-bottom));
  }
  .settings > .side {
    top: calc(var(--topbar-h) + 8px);
  }
  /* On a phone each step reads top down: the question first, always at the
     same place, then the X3 showing what it changes. */
  .ob-step {
    grid-template-columns: minmax(0, 1fr);
    gap: 28px;
    align-content: start;
    padding-top: 8px;
  }
  /* Picking a look on a phone: the headline, then the X3, then the looks
     under it. On a tall phone the X3 stays in view while the looks scroll. */
  .ob-step[data-step="look"] {
    display: flex;
    flex-direction: column;
  }
  .ob-step[data-step="look"] .ob-copy {
    display: contents;
  }
  .ob-step[data-step="look"] .ob-copy > h1 {
    order: -3;
  }
  .ob-step[data-step="look"] .ob-copy > .lede {
    order: -2;
    margin-top: 0;
  }
  .ob-step[data-step="look"] .ob-visual {
    order: -1;
    z-index: 2;
    padding: 4px 0 12px;
    background: var(--paper);
  }
  .ob-step[data-step="look"] .ob-looks {
    margin-top: 4px;
  }
  .ob-hello {
    --s: 132px;
    margin-top: 12px;
  }
  .ob-copy h1,
  .ob-copy h1 label {
    font-size: clamp(2rem, 1.2rem + 4vw, 2.6rem);
  }
  .ob-copy .lede {
    font-size: 1.0625rem;
    margin-top: 14px;
  }
  .ob-form,
  .ob-choices {
    margin-top: 24px;
  }
  .ob-looks {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  .ob-top {
    padding-top: 12px;
    padding-bottom: 12px;
    grid-template-columns: auto 1fr auto;
  }
  .ob-top .brand span {
    display: none;
  }
  .ob-dots {
    justify-self: center;
  }
  .gate-main {
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
    padding-top: 16px;
  }
  /* The words, Sign in and what installing takes come first, on the first
     screen, and the picture after them (docs/reviews/onboarding: what it
     takes was said only after signing in, on whatever was to hand). */
  .gate-visual {
    order: 1;
  }
}
@media (max-width: 959.98px) and (min-height: 760px) and (min-resolution: 2.5dppx), (max-width: 959.98px) and (min-height: 760px) and (-webkit-min-device-pixel-ratio: 2.5) {
  .ob-step[data-step="look"] .ob-visual {
    position: sticky;
    top: -8px;
    box-shadow: 0 10px 12px -12px rgba(0, 0, 0, 0.18);
  }
}
@media (max-width: 600px) {
  input,
  textarea,
  select,
  .feed .focus input,
  .CodeMirror,
  .plain-editor {
    font-size: 16px !important;
  }
  .card {
    padding: 22px 18px;
    border-radius: 16px;
  }
  #cardStart {
    padding: 22px 18px 8px;
  }
  details.reference {
    padding: 18px;
  }
  .formrow,
  .imaprow {
    grid-template-columns: minmax(0, 1fr);
  }
  .formrow .wide {
    grid-column: auto;
  }
  #bOpensRow {
    grid-template-columns: minmax(0, 1fr);
  }
  .page-title {
    font-size: 2.15rem;
  }
  .page-lede {
    font-size: 1.0625rem;
  }
  .page-actions {
    width: 100%;
  }
  .invitebox {
    flex-wrap: wrap;
  }
  .invitebox input {
    flex: 1 1 100%;
  }
  .invitebox button {
    flex: 1 1 auto;
  }
  #zoom {
    display: none;
  }
  .home-hero .desk {
    margin-inline: calc(-1 * max(16px, env(safe-area-inset-left)));
    border-radius: 0;
    overflow-x: clip;
  }
  /* The builder's X3 on a phone is the big one (400px at 3x), edge to edge,
     its bezel cropped a little by the window: lines big enough to tap. */
  .preview {
    margin-inline: calc(-1 * max(16px, env(safe-area-inset-left)));
    padding-inline: 0;
    border-radius: 0;
    overflow-x: clip;
  }
  :root {
    --pv-w: var(--x3-ph);
  }
  .pv-editrow input {
    width: 150px;
  }
  /* ADR-038: a row's buttons stay beside its words on a phone, not under
     them: rows half as tall. Two buttons stack in their own column. */
  .action > div:last-child:not(:first-child),
  .action .rowbuttons {
    flex-direction: column;
    align-items: flex-end;
  }
  .says {
    grid-template-columns: auto minmax(0, 1fr);
    gap: 14px;
  }
  .says .sprite {
    --s: 48px;
  }
  .today-item {
    grid-template-columns: auto minmax(0, 1fr);
    padding: 14px;
  }
  .today-item > button {
    grid-column: 2;
    justify-self: start;
  }
  /* Three quick things as one simple list on a phone: a row each, with the
     words that say what it's for. */
  .quick {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow-1);
    overflow: hidden;
  }
  .quick-tile {
    gap: 14px;
    padding: 14px 16px;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  .quick-tile + .quick-tile {
    border-top: 1px solid var(--rule);
  }
  .quick-tile:hover {
    transform: none;
  }
  .quick-tile:focus-visible {
    outline-offset: -3px;
  }
  .quick-tile b {
    font-size: 1rem;
    margin-bottom: 2px;
  }
  .seg {
    display: flex;
  }
  .seg label {
    flex: 1 1 auto;
    text-align: center;
    padding-inline: 10px;
  }
  .seg.units {
    display: inline-flex;
  }
  button:not(.linkish) {
    min-height: 44px;
  }
  .rowmenu > summary {
    width: 44px;
    height: 44px;
  }
  .pv-key {
    min-height: 0 !important;
  }
  .chips {
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-bottom: 2px;
  }
  .chips button,
  .palette button {
    min-height: 40px;
  }
  .templates {
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  }
  #feedPicker {
    width: 100vw;
    height: 100vh;
    height: 100dvh;
    max-width: none;
    max-height: none;
    border-radius: 0;
    border: 0;
  }
  .picker-foot .long {
    display: none;
  }
  .picker-foot .short {
    display: inline;
  }
  .sheet {
    width: 100%;
    max-width: 100%;
    margin: auto 0 0;
    border-radius: 24px 24px 0 0;
  }
  .sheet-body {
    padding: 24px 18px calc(24px + env(safe-area-inset-bottom));
  }
  .emptystate {
    padding: 22px 18px;
    flex-direction: column;
    gap: 14px;
  }
  .emptystate .sprite {
    --s: 48px;
  }
  /* Setup's footer: a message gets its own line above the buttons rather
     than floating over the page. */
  .ob-foot {
    flex-wrap: wrap;
    gap: 10px 12px;
  }
  .ob-foot .ob-status {
    order: -1;
    flex: 1 0 100%;
    text-align: center;
  }
  .ob-foot .ob-status:empty {
    display: none;
  }
  .ob-foot .btn-lg {
    flex: 1;
  }
  .ob-foot #obBack {
    flex: none;
  }
  .addrow > button {
    flex: 1 1 100%;
  }
  /* The four moods on one row, their faces level however their words wrap. */
  .lookpreview {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    align-items: start;
    gap: 10px 6px;
    padding: 14px 10px;
  }
  .lookpreview figure {
    align-content: start;
  }
  .lookpreview .sprite {
    --s: 40px;
  }
  .lookpreview figcaption {
    text-align: center;
    line-height: 1.25;
  }
  .lookpreview .about {
    grid-column: 1 / -1;
  }
  /* Adding a line on a phone: a sheet along the bottom, over the tab bar. */
  .addpop {
    left: 0 !important;
    right: 0;
    top: auto !important;
    bottom: 0;
    width: 100%;
    max-height: 82vh;
    max-height: 82dvh;
    border-radius: 24px 24px 0 0;
    border-width: 1px 0 0;
    padding: 20px max(18px, env(safe-area-inset-right)) calc(18px + env(safe-area-inset-bottom)) max(18px, env(safe-area-inset-left));
  }
  .strip {
    gap: 12px;
  }
  .strip-row {
    gap: 4px;
  }
  .strip .thumb {
    width: 78px;
    padding: 6px 4px 7px;
  }
  .thumb-frame {
    width: 58px;
  }
  .today-facts > div {
    grid-template-columns: 76px minmax(0, 1fr);
  }
}
/* A phone that isn't tall: the words and the button before the picture, so
   Continue with Google is on the first screen. */
@media (max-height: 760px) and (max-width: 959.98px) {
  .gate-visual {
    order: 1;
  }
  .gate-main {
    padding-top: 8px;
  }
  .gate-copy h1 {
    font-size: clamp(2rem, 1.4rem + 3vw, 2.6rem);
  }
  .gate-copy .lede {
    margin: 16px 0 24px;
  }
}

/* Pointing a phone at the screen is for a computer: on a phone (or a
   tablet) it isn't offered. */
@media (max-width: 600px), (hover: none) and (pointer: coarse) {
  .not-on-phone,
  #sendQrBox {
    display: none !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

/* ADR-038: the Inbox's own list, as the X3 last listed it: content, not
   settings, so body size, and one line a row. */
#wlRows .action,
#wlAll .action {
  font-size: 1rem;
  padding: 12px 0;
}
#wlRows .action > div,
#wlAll .action > div {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#wlRows .action span,
#wlAll .action span {
  color: var(--ink-2);
}
/* The groups when it's all shown: small labels, like Today's, not rows. */
#wlAll .wl-group {
  font: 600 var(--t-tiny)/1.2 var(--text);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 24px 0 8px;
  padding: 0;
  border: 0;
}
#wlAll .wl-group:first-child {
  margin-top: 4px;
}
#wlAll .wl-group + .actions .action:first-child {
  border-top: 0;
}
/* A mailbox's address breaks where it can, on a phone. */
#srcList .action span {
  overflow-wrap: anywhere;
}
/* The feeds' own logos were the only saturated colour in the app. */
.feedlogo {
  filter: grayscale(1) contrast(1.1);
}

/* ADR-038: Deckle's page in tabs. The segmented control, as a tab list. */
.seg.tabs {
  margin: 28px 0 24px;
}
.seg.tabs button {
  margin: 0;
  padding: 9px 16px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font: 600 0.9375rem/1.2 var(--text);
  color: var(--ink-2);
  cursor: pointer;
  min-height: 0;
  box-shadow: none;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.seg.tabs button[aria-selected="true"] {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-1), inset 0 0 0 1px var(--rule);
}
.seg.tabs button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
/* The tab says what the group is: no heading repeating it. */
#viewDeckle #lifeGroup > .life-head,
#viewDeckle #lifeGroup > .life-lede,
#viewDeckle #aroundGroup > .life-head,
#viewDeckle #aroundGroup > .life-lede {
  display: none;
}
@media (max-width: 960px) {
  .seg.tabs {
    position: sticky;
    top: calc(var(--topbar-h) + 8px);
    z-index: 5;
    box-shadow: 0 0 0 8px var(--paper);
    flex-wrap: nowrap;
    max-width: 100%;
    overflow-x: auto;
  }
  .seg.tabs button {
    padding: 9px 12px;
    white-space: nowrap;
  }
}

/* ADR-038 review: every tab starts the same distance under the tab bar
   (a hidden panel no longer carries the old 56px section break), the
   facts list and a sub-heading under it share one rule, and the museum's
   line under a picture has its room. */
#viewDeckle .col > .seg.tabs {
  margin-bottom: 4px;
}
#viewDeckle .col > [role="tabpanel"] {
  margin-top: 20px;
}
.life-facts + .life-sub,
.life-facts + h4.life-sub {
  border-top: 0;
  padding-top: 0;
}
#lifeGallery .life-words {
  margin-top: 20px;
}
#wlAll .wl-group[hidden] + .actions .action:first-child {
  border-top: 1px solid var(--rule);
}

/* The tab already says Watching: no section heading under it, as on the
   others; and the Waiting for card's empty list doesn't draw two rules. */
#viewDeckle #watchGroup > .life-head,
#viewDeckle #watchGroup > .life-lede {
  display: none;
}
#cardWaits #waitsTold[hidden] + h3.sub {
  border-top: 0;
  padding-top: 0;
  margin-top: 20px;
}

/* ADR-038: a button that can't be pressed yet is a quiet outline, not a
   grey pill that looks like a broken one. */
#btThrow:disabled {
  opacity: 1;
  background: transparent;
  color: var(--ink-3);
  box-shadow: inset 0 0 0 1px var(--rule-2);
  border-color: transparent;
}

/* Proposed (round 040): the spare key card on Deckle's page (app-key.mjs). */
.keyart {
  display: flex;
  gap: 16px;
  align-items: center;
  margin: 4px 0 12px;
}
.keyart canvas {
  flex: none;
  color: currentColor;
  image-rendering: pixelated;
}
.keyart .card-lede {
  margin: 0;
}

/* ------------------------------------------------------------------ add a friend
   docs/social/REPLIES-AND-FRIENDS.md: the code large, the invite link a
   button, and a QR beside them (stacked on a phone). */
.fr-share {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 20px;
  align-items: center;
  margin-top: 16px;
  padding: 18px;
  border-radius: 16px;
  background: var(--surface-2);
}
.fr-codelabel {
  margin: 0;
  color: var(--ink-3);
  font-size: 0.9375rem;
}
.fr-code {
  margin: 4px 0 14px;
}
.fr-code .codeface {
  font-size: 1.75rem;
}
.fr-share .buttonrow {
  margin: 0;
}
.fr-qr {
  margin: 0;
  text-align: center;
}
.fr-qr canvas {
  display: block;
  margin: 0 auto 6px;
  border-radius: 10px;
  image-rendering: pixelated;
  background: #fff;
}
.fr-qr figcaption {
  margin: 0;
  max-width: 180px;
}
.fr-palshint,
.iconnote {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  align-items: baseline;
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--surface-2);
}
.fr-palshint p,
.iconnote p {
  margin: 0;
}
@media (max-width: 600px) {
  .fr-share {
    grid-template-columns: minmax(0, 1fr);
  }
}
