/* Theseus team — the brand's green, worn the way iOS 26 and iPadOS 26 dress
   an app: one wallpaper that stays put, and on it panes of "liquid glass" —
   translucent, blurred, with a lit upper edge. Controls are capsules and
   circles, corners are concentric, type is the system face (SF on Apple
   devices, Onest elsewhere, so Cyrillic and Latin match everywhere).
   Fonts are self-hosted; nothing is fetched from another server. */

@font-face {
  font-family: 'Joti One'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/joti-one-latin.woff2) format('woff2');
}
@font-face {
  font-family: 'Onest'; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url(fonts/onest-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Onest'; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url(fonts/onest-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'JetBrains Mono'; font-style: normal; font-display: swap; font-weight: 100 800;
  src: url(fonts/jetbrains-mono-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono'; font-style: normal; font-display: swap; font-weight: 100 800;
  src: url(fonts/jetbrains-mono-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

:root {
  --leaf: #cee6bb;                 /* the logo's lettering, and the tint */
  --edge-top: #5f8b61;             /* the wallpaper's colour along its top edge… */
  --edge-bottom: #0f1711;          /* …and along its bottom edge */

  --label: #ffffff;
  --label-2: rgba(241, 249, 235, 0.76);
  --label-3: rgba(241, 249, 235, 0.54);
  --sep: rgba(255, 255, 255, 0.14);
  --on-tint: #1b251b;
  --danger: #ff8478;

  /* liquid glass: a faint white wash over a dark veil, a lit top edge, a soft drop */
  --glass: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.05)), rgba(20, 30, 20, 0.30);
  --glass-hi: linear-gradient(180deg, rgba(255, 255, 255, 0.26), rgba(255, 255, 255, 0.12)), rgba(20, 30, 20, 0.22);
  --edge: inset 0 1px 0 rgba(255, 255, 255, 0.34), inset 0 0 0 1px rgba(255, 255, 255, 0.09);
  --drop: 0 14px 34px -16px rgba(0, 0, 0, 0.55);
  --blur: blur(28px) saturate(170%);
  --fill: rgba(8, 14, 8, 0.28);    /* text fields sit below the surface */

  --r-card: 26px; --r-field: 18px; --r-sheet: 34px;
  --spring: cubic-bezier(0.3, 1.5, 0.5, 1);

  --sans: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Onest', system-ui, 'Segoe UI', Roboto, sans-serif;
  --brand: 'Joti One', 'Onest', system-ui, sans-serif;
  --mono: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; }
::selection { background: rgba(206, 230, 187, 0.35); }

/* Safari on iOS paints the strips behind the status bar and the toolbar itself.
   It takes the colour from a solid element fixed to that edge of the page
   (the two .edge strips below) and, failing that, from this background
   colour. Images and gradients are ignored, so both are plain colours. */
html {
  background-color: var(--edge-top);
  -webkit-text-size-adjust: 100%;
}
/* Installed on the Home Screen there are no browser bars to tint, and iOS lays
   the page out a status bar short of the screen's bottom. What it paints in
   that strip is the document's colour — and there the BODY's colour wins over
   the root's. So in the installed app both take the wallpaper's bottom edge,
   and the strip reads as the wallpaper running on. boot.js sets the class
   before the first paint. Zooming is off there too, like in any app. */
html.standalone, html.standalone body { background-color: var(--edge-bottom); }
@media (display-mode: standalone) { html, body { background-color: var(--edge-bottom); } }
html.standalone, html.standalone body { touch-action: pan-x pan-y; }
/* The strip iOS leaves under the page cannot be drawn on: it only takes the
   colour above. So the wallpaper itself must END in exactly that colour — it
   settles into it over its last stretch, and the strip is its continuation.
   (Stretching the wallpaper downwards does not reach the strip; it only moves
   that last stretch out of sight and leaves a visible step.) */

/* In the installed app the page starts under the status bar, and iOS blurs
   whatever is there: the account's header and the About page start lower. */
html.standalone header.site { padding-top: calc(env(safe-area-inset-top, 0px) + 20px); }

body {
  margin: 0;
  min-height: 100vh; min-height: 100dvh;
  color: var(--label);
  font-family: var(--sans);
  font-size: 17px; line-height: 1.35; letter-spacing: -0.01em;
  -webkit-font-smoothing: antialiased;
  background-color: var(--edge-top);
  isolation: isolate;
}
/* the wallpaper: smooth, layered panes of green light, the way the system
   wallpapers are drawn. It is fixed, so the glass moves over it. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  /* the wallpaper settles into one flat colour at each edge, so the browser's
     bars continue it without a seam */
  background:
    linear-gradient(180deg, var(--edge-top), rgba(95, 139, 97, 0) 84px),
    linear-gradient(0deg, var(--edge-bottom) 0, var(--edge-bottom) 2px, rgba(15, 23, 17, 0.82) 70px, rgba(15, 23, 17, 0) 230px),
    #31442f url(wallpaper.svg) center / cover no-repeat;
}
#view { display: contents; }     /* what a page shows; app.js swaps it when pages change */
.edge { position: fixed; left: 0; right: 0; height: 4px; z-index: 90; }
.edge-top { top: 0; background-color: var(--edge-top); }
.edge-bottom { bottom: 0; background-color: var(--edge-bottom); }

p { margin: 0 0 16px; }

/* ---- Glass, shared ---- */

/* Panes that sit on the wallpaper do not blur it: the wallpaper is smooth, so
   a blur would change nothing on screen and only cost the phone work on
   every scrolled frame. The blur is kept for what really floats over content:
   the link sheet and the toast. */
.lang, .icon-btn, .btn, .toast, .qr-box, blockquote {
  background: var(--glass);
  box-shadow: var(--edge), var(--drop);
  border: 0;
}

/* ---- Controls: capsules and circles ---- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  width: 100%; min-height: 50px; padding: 0 20px;
  border-radius: 999px; color: var(--label);
  font-family: inherit; font-size: 17px; font-weight: 600; letter-spacing: -0.01em;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: transform 0.4s var(--spring), filter 0.2s, background 0.15s;
}
/* A press you can see: down at once under the finger, back on a spring.
   app.js sets .is-pressed on touch, so it does not wait for the browser's
   own slow :active. Hover exists only where there is a pointer to hover. */
.is-pressed { transform: scale(0.955); filter: brightness(0.9); transition-duration: 0.07s !important; transition-timing-function: ease-out !important; }
.lang a.is-pressed, .gate-foot > a.is-pressed, nav.site a.is-pressed, .brand.is-pressed, .store.is-pressed, .sheet-row.is-pressed, .faq summary.is-pressed { transform: scale(0.97); filter: none; opacity: 0.6; }
.tabbar button.is-pressed, .inbox-bar.is-pressed { transform: none; filter: brightness(1.25); }
@media (hover: hover) {
  .btn:hover { filter: brightness(1.12); }
  .icon-btn:hover, .store:hover { filter: brightness(1.15); }
}
.btn:focus-visible, .icon-btn:focus-visible, .store:focus-visible, .lang a:focus-visible {
  outline: 3px solid rgba(206, 230, 187, 0.75); outline-offset: 2px;
}
.btn svg { width: 17px; height: 17px; flex: 0 0 auto; }

/* the prominent, tinted button */
.btn.primary, body.gate .btn {
  background: linear-gradient(180deg, #e3f3d4, #c2dfac);
  color: var(--on-tint);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 12px 28px -14px rgba(0, 0, 0, 0.6);
}
.btn.danger { color: var(--danger); }
.btn.ghost { color: var(--label-2); }

.icon-btn {
  width: 44px; height: 44px; flex: 0 0 auto; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; color: var(--label);
  cursor: pointer; transition: transform 0.4s var(--spring), filter 0.2s;
}
.icon-btn.danger { color: var(--danger); }
.icon-btn svg { width: 19px; height: 19px; }
@keyframes spin { to { transform: rotate(360deg); } }

.text-input, .key-input {
  width: 100%; min-height: 50px; padding: 12px 18px;
  border: 0; border-radius: 999px;
  background: var(--fill); color: var(--label);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35), inset 0 0 0 1px rgba(255, 255, 255, 0.10);
  font-family: inherit; font-size: 17px; letter-spacing: -0.01em; text-align: left;
}
.key-input {
  border-radius: var(--r-field); padding: 12px 14px;
  font-family: var(--mono); font-size: 16px; letter-spacing: 0; font-variant-ligatures: none;
}
.text-input::placeholder, .key-input::placeholder { color: var(--label-3); }
.text-input:focus, .key-input:focus {
  outline: none;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35), 0 0 0 3px rgba(206, 230, 187, 0.55);
}

.inline-form { display: flex; margin: 0; }
.trap { text-align: left; margin: 0 0 18px; }
.trap label { display: block; font-size: 13px; color: var(--label-2); margin: 0 0 6px 4px; }
.trap input {
  width: 100%; min-height: 44px; padding: 10px 14px; border: 1px dashed rgba(255, 255, 255, 0.26); border-radius: var(--r-field);
  background: transparent; color: var(--label); font-family: inherit; font-size: 15px;
}
.trap.trap-off { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; margin: 0; }
.quiet-link { color: var(--leaf); text-decoration: none; }
.quiet-link:hover { text-decoration: underline; }
.form-error { color: var(--danger); font-size: 15px; min-height: 1.4em; margin: 12px 0 0; }

/* The wordmark is the logo itself, drawn from its own outlines; the heading
   text stays in the page for screen readers. */
.brand-mark {
  display: block; overflow: hidden; white-space: nowrap; text-indent: -200vw;
  font-size: 1px; line-height: 0; color: transparent;
  background: url(wordmark.svg) left center / contain no-repeat;
  aspect-ratio: 608.17 / 117.75; width: 132px; margin: 0;
}

/* the segmented control */
.lang {
  display: inline-flex; align-items: center; flex: 0 0 auto; gap: 0;
  height: 44px; padding: 4px; border-radius: 999px;
}
.lang a {
  min-width: 40px; height: 36px; padding: 0 10px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px; text-decoration: none;
  font-size: 14px; font-weight: 600; letter-spacing: 0; color: var(--label-2);
  transition: color 0.15s, background 0.2s, transform 0.4s var(--spring), opacity 0.2s;
}
.lang a:hover { color: var(--label); }
.lang a.on {
  background: var(--glass-hi); color: var(--label);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 3px 8px -3px rgba(0, 0, 0, 0.5);
}

/* ---- Sign-in ---- */

body.gate {
  display: flex; align-items: center; justify-content: center;
  padding: 24px 28px;            /* the controls stop short of the screen's edges */
}
.gate-main { width: 100%; max-width: 360px; }
/* The whole key (32 characters) must stay in view at 16px, the size below
   which iOS zooms the page. When the field is too narrow for that, the
   letters close up by exactly as much as is missing. */
body.gate .key-input {
  min-height: 48px; margin: 0 0 18px;
  letter-spacing: min(0px, calc((100vw - 394px) / 32));
}
body.gate .btn { min-height: 48px; }
/* the second way in, under the main button: quieter, glass like the rest */
body.gate .btn.passkey-enter {
  margin-top: 10px; background: var(--glass); color: var(--label); font-weight: 600;
  box-shadow: var(--edge), var(--drop);
}
.card { text-align: center; }

body.gate .brand-mark {
  background-image: url(logo.svg); background-position: center;
  aspect-ratio: 608.17 / 215.4; width: min(236px, 62vw); margin: 0 auto 34px;
}
/* The logo catches the light: a soft green tint and then a bright band glide
   across the letters, then rest. The outlines are a mask; only the two
   bands move, by transform alone, so the browser has nothing to repaint. */
@supports ((-webkit-mask-image: url(logo.svg)) or (mask-image: url(logo.svg))) {
  body.gate .brand-mark {
    position: relative;
    background: var(--leaf);
    -webkit-mask: url(logo.svg) center / contain no-repeat;
    mask: url(logo.svg) center / contain no-repeat;
  }
  body.gate .brand-mark::before, body.gate .brand-mark::after {
    content: ""; position: absolute; top: -10%; bottom: -10%; left: 0;
    transform: translateX(-130%); will-change: transform; pointer-events: none;
    animation: sheen 7s cubic-bezier(0.4, 0, 0.3, 1) infinite;
  }
  body.gate .brand-mark::before {
    width: 60%;
    background: linear-gradient(100deg, rgba(150, 210, 122, 0), rgba(150, 210, 122, 0.85) 50%, rgba(150, 210, 122, 0));
  }
  body.gate .brand-mark::after {
    width: 36%;
    background: linear-gradient(100deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.95) 50%, rgba(255, 255, 255, 0));
    animation-delay: 0.35s;
  }
}
@keyframes sheen {
  from { transform: translateX(-130%); }
  60%, to { transform: translateX(340%); }
}

/* the "not found" and "too many requests" cards say their piece here */
.card-lead { color: var(--label); font-size: 20px; font-weight: 600; letter-spacing: -0.02em; margin: 0 0 22px; }
.offline-text { color: var(--label-2); font-size: 15px; margin: 0 0 24px; }
.gate-foot { display: flex; flex-direction: column; align-items: center; gap: 14px; margin-top: 30px; }
.gate-foot > a { display: inline-block; color: var(--label-2); text-decoration: none; font-size: 15px; transition: transform 0.4s var(--spring), opacity 0.2s; }
.gate-foot > a:hover { color: var(--label); }

/* on an iPad or a desktop the form sits on its own pane of glass */
@media (min-width: 600px) {
  .gate-main { max-width: 420px; }
  body.gate .key-input { letter-spacing: 0; }
  body.gate .card {
    padding: 38px 32px 30px; border-radius: var(--r-sheet);
    background: var(--glass);
    box-shadow: var(--edge), var(--drop);
  }
}
@media (max-width: 420px) {
  .key-input { padding: 12px 9px; }
}
@media (max-width: 380px) {
  body.gate { padding-left: 22px; padding-right: 22px; }
  body.gate .key-input { letter-spacing: min(0px, calc((100vw - 382px) / 32)); }
}

/* ---- Account ---- */

/* The account is a dark screen of its own, laid out like a phone app: recent
   notifications in a pane at the very top, the person and the way out under
   it, one device at a time in the middle with its actions as round buttons,
   and a tab bar at the bottom. There is no wallpaper here: the page is the
   colour the wallpaper ends in, the one the browser's bars and the strip
   under an installed app continue. */
html.app-page, body.app-page { background-color: var(--edge-bottom); }
body.app-page { display: block; padding: 0; }
body.app-page::before { display: none; }
body.app-page .edge-top { background-color: #17211a; }

.app {
  --panel: #17211a; --raised: #222e25;
  max-width: 480px; margin: 0 auto; min-height: 100vh; min-height: 100dvh;
  padding: 0 16px calc(92px + env(safe-area-inset-bottom, 0px));
  display: flex; flex-direction: column; gap: 14px;
}
.pane { display: flex; flex-direction: column; gap: 14px; }
/* on a phone these two only group things for the computer's layout (see "The account on a computer") */
.hero, .side { display: contents; }
.deck-arrow, .device-list { display: none; }
.pane-title { margin: 8px 4px 0; font-size: 30px; font-weight: 800; letter-spacing: -0.03em; }
.panel { border-radius: 24px; padding: 18px; background: var(--panel); }
.hint { font-size: 14px; line-height: 1.4; color: var(--label-2); margin: 0; }
.chevron { width: 18px; height: 18px; flex: 0 0 auto; color: var(--label-3); }

/* The latest notification, always in sight. The pane has a grabber, like the
   one under the system's own panels: drag the pane down (it stretches with
   the finger) or tap it, and the whole list opens. */
.inbox-bar {
  --pull: 0px;
  position: relative; display: block; width: auto; margin: 0 -16px;
  padding: calc(env(safe-area-inset-top, 0px) + 16px + var(--pull)) 24px 34px;
  border: 0; border-radius: 0 0 32px 32px; background: var(--panel); color: var(--label);
  font: inherit; cursor: pointer; touch-action: pan-x;
  transition: padding-top 0.45s var(--spring), filter 0.2s;
}
.inbox-bar::after {                          /* the grabber */
  content: ""; position: absolute; left: 50%; bottom: 9px; width: 38px; height: 5px; margin-left: -19px;
  border-radius: 999px; background: rgba(255, 255, 255, 0.3);
}
.inbox-bar.pulling { transition: none; }
.inbox-line {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-size: 15px; font-weight: 500; color: var(--label-2);
}
.inbox-line svg { width: 18px; height: 18px; flex: 0 0 auto; }
.inbox-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app.unread .inbox-line { color: var(--label); }
.app.unread .inbox-line svg { color: var(--leaf); }
.app.unread .inbox-line::after { content: ""; flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: #b4f08c; box-shadow: 0 0 8px rgba(180, 240, 140, 0.8); }

/* Pulling the page down anywhere else refreshes it: a strip opens under the
   pane with a spinner in it, and stays while the fresh page is fetched. */
.refresher {
  --pull: 0px;
  height: var(--pull); margin: -14px 0 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  transition: height 0.4s var(--spring);
}
.refresher.pulling { transition: none; }
.refresher.busy { height: 52px; }
.spinner {
  width: 22px; height: 22px; flex: 0 0 auto; border-radius: 50%;
  border: 2.5px solid rgba(255, 255, 255, 0.16); border-top-color: var(--label-2);
}
.refresher.far .spinner, .refresher.busy .spinner { animation: spin 0.8s linear infinite; }

/* who is signed in (the settings are behind the face) and the way out */
.topbar { display: flex; align-items: center; gap: 12px; padding: 4px 0 0; }
.topbar .brand-mark { width: 116px; margin: 0 auto; }
.me { position: relative; flex: 0 0 auto; padding: 0; border: 0; background: none; cursor: pointer; transition: transform 0.4s var(--spring), filter 0.2s; }
.me-face {
  display: flex; align-items: center; justify-content: center; width: 46px; height: 46px; border-radius: 50%;
  background: linear-gradient(160deg, #e3f3d4, #b6d7a0); color: var(--on-tint);
  font-size: 19px; font-weight: 700; letter-spacing: 0;
}
.me-on { position: absolute; right: -2px; bottom: -2px; width: 15px; height: 15px; border-radius: 50%; background: #8fe35f; border: 3px solid var(--edge-bottom); display: none; }
.me-on.live { display: block; }
.me-big { display: flex; justify-content: center; margin: 0 0 12px; }
.me-big .me-face { width: 68px; height: 68px; font-size: 28px; }
.app .icon-btn { width: 46px; height: 46px; background: var(--raised); box-shadow: none; }

/* ---- Devices: one at a time, swiped sideways ---- */

/* Each device is a page of the row: its state, its name large, and a card
   that says what it is. The row is scrolled and snapped by the browser, so
   it follows the finger; app.js keeps the dots above it in step and points
   the round buttons under it at the device on screen. It never alters the
   pages themselves: the quiet refresh compares their markup with the server's. */
.deck-dots { display: flex; justify-content: center; margin: 4px 0 -6px; }
.deck-dots button {
  width: 18px; height: 22px; padding: 0; border: 0; background: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.deck-dots button::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.26);
  transition: background 0.25s ease, transform 0.35s var(--spring);
}
.deck-dots button[aria-current="true"]::before { background: #fff; transform: scale(1.15); }
.deck-dots button.plus::before { width: 9px; height: 9px; border-radius: 0; background: none; color: rgba(255, 255, 255, 0.4); content: "+"; font: 600 13px/9px var(--sans); text-align: center; }
.deck-dots button.plus[aria-current="true"]::before { background: none; color: #fff; }
.deck-dots button:focus-visible { outline: 3px solid rgba(206, 230, 187, 0.75); outline-offset: -2px; border-radius: 999px; }

.devices {
  list-style: none; margin: 0 -16px; padding: 0; display: flex;
  overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.devices::-webkit-scrollbar { display: none; }
/* The row starts one page in (a copy of the "add" page stands before the
   first device, so the row can go round); app.js puts it there and only then
   lets it be seen. */
.devices { visibility: hidden; }
.devices.ready { visibility: visible; }
.device {
  flex: 0 0 100%; min-width: 0; scroll-snap-align: center; scroll-snap-stop: always;
  display: flex; flex-direction: column; align-items: center; padding: 10px 24px 14px; text-align: center;
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .device { animation: device-page linear both; animation-timeline: view(inline); }
  }
}
@keyframes device-page {
  0%, 100% { opacity: 0.2; transform: scale(0.9); }
  50% { opacity: 1; transform: none; }
}
.device-state {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px 5px 10px; border-radius: 999px;
  background: var(--raised); font-size: 13px; font-weight: 600; color: var(--label-2);
}
.device-state::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--label-3); }
.device-state.plain::before { display: none; }
.device-state.plain { padding: 5px 12px; font-variant-numeric: tabular-nums; }
.device.live .device-state { background: rgba(160, 230, 120, 0.2); color: #dcf6ca; }
.device.live .device-state::before { background: #b4f08c; box-shadow: 0 0 8px rgba(180, 240, 140, 0.9); }
.device-name {
  max-width: 100%; margin: 12px 0 0; font-size: clamp(32px, 10.5vw, 44px); font-weight: 800; line-height: 1.08; letter-spacing: -0.035em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* ---- The device itself, as a chrome figure ---- */

/* Every device is shown as the same small figure of polished metal, a ball
   of chrome rings. It is a picture (assets/models): bright chrome when the
   device is online, dark chrome when it is away. Sizes are in em,
   so one font-size scales the whole stage. */
.device-meta { margin: 8px 0 0; min-height: 1.35em; font-size: 13px; line-height: 1.35; color: var(--label-2); }
.device-stage {
  position: relative; width: 100%; height: 19.5em; margin-top: 4px;
  display: flex; align-items: center; justify-content: center;
  font-size: clamp(7.6px, 2.5vw, 10px); perspective: 60em;
}
.device-stage::after {                     /* the shadow the figure casts on the floor */
  content: ""; position: absolute; left: 26%; right: 26%; bottom: 0; height: 2.6em; pointer-events: none;
  background: radial-gradient(50% 50% at 50% 50%, rgba(0, 0, 0, 0.66), rgba(0, 0, 0, 0));
}
.device.live .device-stage::after { background: radial-gradient(50% 50% at 50% 50%, rgba(255, 255, 255, 0.24), rgba(0, 0, 0, 0.3) 55%, rgba(0, 0, 0, 0)); }
.device-model {
  display: block; flex: 0 0 auto; width: 17em; height: 17em; margin-bottom: 1.6em;
  background: center / contain no-repeat;
  transform: rotateX(calc(var(--tx) * 0.7)) rotateY(calc(var(--ty) * 0.7));
  transition: transform 0.9s cubic-bezier(0.2, 1.7, 0.35, 1);
}
/* its picture lies in ::after, so that the white light it gives off when
   online (::before, a picture too) can lie behind the metal and breathe on
   its own */
.m-orb { position: relative; }
.m-orb::before, .m-orb::after { content: ""; position: absolute; pointer-events: none; background: center / contain no-repeat; }
.m-orb::after { inset: 0; background-image: url(models/orb-off.webp); }
.m-orb::before { inset: -25%; background-image: url(models/orb-glow.webp); opacity: 0; transition: opacity 0.5s; }
.device.live .m-orb::after { background-image: url(models/orb.webp); }
.device.live .m-orb::before { opacity: 0.85; }

/* the page that adds a device: a chrome plus, hanging like the rest */
.device-add { display: block; padding: 0; border: 0; background: none; font: inherit; cursor: pointer; }
.device-add:focus-visible { outline: 3px solid rgba(206, 230, 187, 0.75); outline-offset: 2px; border-radius: 2em; }
.m-plus { background-image: url(models/plus.webp); width: 14em; height: 14em; }
.device.plus .device-name { font-size: clamp(26px, 8.2vw, 34px); line-height: 1.38; }

/* It hangs in the air: it rises and settles, rocking a little, and its shadow
   on the floor shrinks as it rises. And it answers the finger: the place that is touched goes down, as a
   floating thing would (app.js sets the angles on the row), and on release
   it swings back. */
.devices { --tx: 0deg; --ty: 0deg; }
.devices.tilting .device-model { transition: transform 0.14s ease-out; }
@media (prefers-reduced-motion: no-preference) {
  .device-model { animation: card-float 5.6s ease-in-out infinite; }
  .device-stage::after { animation: card-floor 5.6s ease-in-out infinite; }
  .device.live .m-orb::before { animation: orb-light 3.8s ease-in-out infinite; }
}
@keyframes card-float {
  0%, 100% { translate: 0 0.4em; rotate: -0.9deg; }
  50% { translate: 0 -0.9em; rotate: 1.1deg; }
}
@keyframes card-floor {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(0.86); opacity: 0.62; }
}
@keyframes orb-light {
  0%, 100% { opacity: 0.5; scale: 0.97; }
  50% { opacity: 1; scale: 1.04; }
}

/* what can be done with the device on screen: round buttons, a row that scrolls */
.actions { display: flex; justify-content: center; gap: 12px; margin: 0; padding: 2px 0 6px; }
.actions > * { flex: 0 1 92px; }
.act-form { display: flex; margin: 0; }
.act {
  width: 100%; display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 0;
  border: 0; background: none; color: var(--label); cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 500; letter-spacing: -0.01em; white-space: nowrap;
  transition: transform 0.4s var(--spring), filter 0.2s, opacity 0.2s;
}
.act-ico { display: flex; align-items: center; justify-content: center; width: 60px; height: 60px; border-radius: 50%; background: var(--raised); }
.act-ico svg { width: 24px; height: 24px; }
.act.danger .act-ico { color: var(--danger); }
.act:disabled { opacity: 0.32; cursor: default; }
.act:focus-visible .act-ico, .me:focus-visible .me-face { outline: 3px solid rgba(206, 230, 187, 0.75); outline-offset: 2px; }

/* three figures in one pane */
.tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-radius: 24px; padding: 16px 4px; background: var(--panel); }
.tile { min-width: 0; padding: 0 6px; text-align: center; }
.tile + .tile { box-shadow: -1px 0 0 var(--sep); }
.tile .value { font-size: 24px; font-weight: 700; line-height: 1.15; letter-spacing: -0.03em; white-space: nowrap; }
.tile .value .of { font-size: 14px; font-weight: 500; letter-spacing: -0.01em; color: var(--label-3); }
.tile .label { margin-top: 3px; font-size: 13px; color: var(--label-2); }
.tile .label::first-letter { text-transform: uppercase; }
.tile.t-online.live .value { color: var(--leaf); }

/* a pane that leads somewhere */
.row-card {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 18px;
  border: 0; border-radius: 24px; background: var(--panel); color: var(--label);
  font: inherit; text-align: left; text-decoration: none; cursor: pointer;
  transition: transform 0.4s var(--spring), filter 0.2s;
}
.row-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.row-text strong { font-size: 17px; font-weight: 700; letter-spacing: -0.02em; }
.row-text span { font-size: 14px; color: var(--label-2); }

/* the "add to Home Screen" tip; app.js decides whether it is shown */
.install { display: flex; align-items: center; gap: 12px; padding: 14px 12px 14px 18px; border-radius: 24px; background: var(--panel); }
.install[hidden] { display: none; }
.install-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.install-text strong { font-size: 16px; font-weight: 600; }
.install-text span { font-size: 13px; color: var(--label-2); }
.install .icon-btn { width: 36px; height: 36px; }
.install .icon-btn svg { width: 15px; height: 15px; }

/* ---- The App and Help tabs ---- */

.lead-line { margin: 0 0 4px; font-size: 20px; letter-spacing: -0.02em; }
.store-list { display: flex; flex-direction: column; margin: 14px 0 -8px; }
.store {
  display: flex; align-items: center; justify-content: space-between; min-height: 54px;
  box-shadow: inset 0 1px 0 var(--sep);
  color: var(--label); text-decoration: none; font-size: 17px;
  transition: transform 0.4s var(--spring), opacity 0.2s;
}
.faq { padding: 2px 18px; }
.faq details + details { box-shadow: inset 0 1px 0 var(--sep); }
.faq summary { display: flex; align-items: center; gap: 10px; min-height: 58px; padding: 8px 0; cursor: pointer; list-style: none; font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }
.faq summary::-webkit-details-marker { display: none; }
.faq p { margin: 0 0 16px; font-size: 15px; line-height: 1.45; color: var(--label-2); }
.chev {
  width: 9px; height: 9px; flex: 0 0 auto; margin: 0 4px 0 auto;
  border-right: 2px solid var(--label-3); border-bottom: 2px solid var(--label-3);
  transform: rotate(45deg); transition: transform 0.25s var(--spring);
}
details[open] > summary .chev { transform: rotate(-135deg); }

/* ---- The tab bar ---- */

/* It is the page's own colour, not glass: in an installed app iOS leaves a
   strip under the page that only takes that colour, and the bar runs into it. */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--edge-bottom); box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.08);
}
.tabbar-in { max-width: 480px; margin: 0 auto; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tabbar button {
  display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 9px 0 7px;
  border: 0; background: none; color: var(--label-3); cursor: pointer;
  font-family: inherit; font-size: 11px; font-weight: 500; letter-spacing: 0;
  transition: transform 0.4s var(--spring), color 0.2s;
}
.tabbar svg { width: 26px; height: 26px; }
.tabbar button.on { color: var(--leaf); }

/* ---- The account sheet: Face ID, notifications, language ---- */

.prefs { text-align: left; border-radius: 22px; padding: 2px 16px; margin: 6px 0 16px; background: rgba(255, 255, 255, 0.07); }
.pref { display: flex; align-items: center; gap: 8px; min-height: 62px; padding: 9px 0; }
.pref:not([hidden]) ~ .pref { box-shadow: inset 0 1px 0 var(--sep); }      /* a line only under a row that is shown */
.pref-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pref-text strong { font-size: 16px; font-weight: 600; }
.pref-text span { font-size: 13px; color: var(--label-2); }
.pref .btn { width: auto; flex: 0 0 auto; min-height: 38px; padding: 0 14px; font-size: 15px; box-shadow: var(--edge); }
.pref .btn { padding: 0 12px; font-size: 14px; }
/* the system's switch: a real control, it changes the setting it shows */
.switch {
  position: relative; flex: 0 0 auto; width: 51px; height: 31px; padding: 0; border: 0; border-radius: 999px;
  background: rgba(120, 130, 120, 0.42); cursor: pointer;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.10);
  transition: background 0.25s ease;
}
.switch::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 27px; height: 27px; border-radius: 50%;
  background: #fff; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.35);
  transition: transform 0.3s var(--spring), width 0.2s ease;
}
.switch[aria-checked="true"] { background: #62c466; }
.switch[aria-checked="true"]::after { transform: translateX(20px); }
.switch.is-pressed { transform: none; filter: none; }
.switch.is-pressed::after { width: 32px; }
.switch[aria-checked="true"].is-pressed::after { transform: translateX(15px); }
.switch:disabled { opacity: 0.6; }
.switch:focus-visible { outline: 3px solid rgba(206, 230, 187, 0.75); outline-offset: 2px; }
.add-row { display: flex; flex-direction: column; gap: 10px; margin: 0 0 12px; }
.add-row + .hint { margin: 0 0 16px; text-align: center; }
.limit-note { text-align: center; margin: 4px 0 16px; font-size: 15px; color: var(--label-2); }
.qr-box .form-error { margin: 0 0 14px; text-align: center; }

/* ---- The list of notifications: a screen that comes down from the top ---- */

.modal[hidden] { display: none; }
.inbox { position: fixed; inset: 0; z-index: 95; display: flex; background: var(--edge-bottom); animation: inbox-down 0.4s cubic-bezier(0.2, 0.9, 0.25, 1); }
@keyframes inbox-down { from { transform: translateY(-100%); } }
.inbox-box {
  flex: 1; min-height: 0; max-width: 480px; margin: 0 auto; display: flex; flex-direction: column;
  padding: calc(env(safe-area-inset-top, 0px) + 18px) 16px calc(env(safe-area-inset-bottom, 0px) + 22px);
}
.inbox-title { margin: 4px 4px 14px; font-size: 30px; font-weight: 800; letter-spacing: -0.03em; }
.inbox-list { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 10px; }
.note { border-radius: 22px; padding: 14px 16px; background: #17211a; }
.note header { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.note strong { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; }
.note time { flex: 0 0 auto; font-size: 12px; color: var(--label-3); }
.note strong { flex: 1; min-width: 0; }
.note { transition: opacity 0.18s, transform 0.18s; }
.note.going { opacity: 0; transform: scale(0.96); pointer-events: none; }
.note-x {                                    /* takes this one off the list */
  position: relative; flex: 0 0 auto; align-self: center; width: 28px; height: 28px; margin: -4px -6px -4px -2px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.09); color: var(--label-2); cursor: pointer;
  transition: transform 0.4s var(--spring), filter 0.2s;
}
.note-x::after { content: ""; position: absolute; inset: -8px; }      /* a finger-sized target */
.note-x svg { width: 11px; height: 11px; }
.note-x.is-pressed { transform: scale(0.88); filter: brightness(1.4); }
.note p { margin: 4px 0 0; font-size: 15px; line-height: 1.4; color: var(--label-2); overflow-wrap: anywhere; }
.inbox-empty { margin: auto; display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 0 20px; text-align: center; }
.inbox-smile { font-size: 68px; line-height: 1.1; }
.inbox-empty strong { font-size: 28px; font-weight: 800; letter-spacing: -0.03em; }
.inbox-empty span:last-child { font-size: 16px; color: var(--label-2); }
.inbox-actions { display: flex; justify-content: center; gap: 10px; margin-top: 16px; }
.inbox-close { width: auto; min-height: 50px; padding: 0 24px; background: #222e25; box-shadow: none; }
.inbox-close svg { width: 16px; height: 16px; }

/* ---- The link sheet ---- */

.qr-modal {
  position: fixed; inset: 0; z-index: 95;
  background: rgba(6, 10, 6, 0.42);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  display: flex; align-items: flex-end; justify-content: center; padding: 0;
}
.qr-modal[hidden] { display: none; }
.qr-box {
  position: relative; width: 100%; max-width: 520px; text-align: center;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.06)), rgba(28, 40, 28, 0.78);
  -webkit-backdrop-filter: blur(40px) saturate(170%); backdrop-filter: blur(40px) saturate(170%);
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  padding: 30px 20px max(22px, env(safe-area-inset-bottom));
  max-height: 92vh; max-height: 92dvh; overflow-y: auto; overscroll-behavior: contain;
  animation: sheet-up 0.42s cubic-bezier(0.2, 0.9, 0.25, 1);
}
.qr-box::before {            /* the grabber */
  content: ""; position: absolute; top: 9px; left: 50%; width: 38px; height: 5px; margin-left: -19px;
  border-radius: 999px; background: rgba(255, 255, 255, 0.35);
}
@keyframes sheet-up { from { transform: translateY(40%); opacity: 0; } }
.qr-title { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; color: var(--label); margin: 0 0 16px; }
.qr-holder { background: #fff; padding: 12px; border-radius: 22px; max-width: 300px; margin: 0 auto; }
.qr-holder svg { display: block; width: 100%; height: auto; }
.qr-box .hint { margin: 14px 0 16px; text-align: center; font-size: 15px; }
.qr-actions { display: flex; gap: 8px; }
.qr-actions .btn { width: auto; flex: 1 1 0; padding: 0 10px; font-size: 16px; }

/* a sheet that offers a choice ("Share"): rows, as on the App tab */
.sheet-list, .info { margin: 0 0 16px; padding: 0 16px; border-radius: 22px; background: rgba(255, 255, 255, 0.07); text-align: left; }
.sheet-row {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; padding: 0;
  border: 0; background: none; color: var(--label); cursor: pointer;
  font: inherit; font-size: 17px; text-align: left;
  transition: transform 0.4s var(--spring), opacity 0.2s;
}
.sheet-row + .sheet-row, .info > div + div { box-shadow: inset 0 1px 0 var(--sep); }
.sheet-row > svg:first-child { width: 22px; height: 22px; flex: 0 0 auto; color: var(--leaf); }
.sheet-row > span { flex: 1; min-width: 0; }

/* what is known about a device ("Edit"): a name and a value on each line */
.info:empty { display: none; }
.info > div { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 13px 0; }
.info dt { flex: 0 0 auto; font-size: 15px; color: var(--label-2); }
.info dd { min-width: 0; margin: 0; font-size: 15px; font-weight: 600; text-align: right; overflow-wrap: anywhere; }
@media (min-width: 600px) {
  .qr-modal { align-items: center; padding: 24px; }
  .qr-box { max-width: 400px; border-radius: var(--r-sheet); padding: 30px 24px 24px; }
  .qr-box::before { display: none; }
  @keyframes sheet-up { from { transform: scale(0.94); opacity: 0; } }
}

/* ---- Feedback ---- */

.toast { -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur); }
.toast {
  position: fixed; left: 50%; bottom: max(26px, env(safe-area-inset-bottom));
  transform: translate(-50%, 14px);
  color: var(--label); font-size: 15px; font-weight: 500; padding: 12px 20px; border-radius: 999px;
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease, transform 0.35s var(--spring); z-index: 100;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast { width: max-content; max-width: calc(100vw - 32px); text-align: center; border-radius: 24px; }
body.app-page .toast { bottom: calc(92px + env(safe-area-inset-bottom, 0px)); }
.toast[hidden] { display: none; }

.progress {
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 96;
  background: var(--leaf);
  transform: scaleX(0); transform-origin: 0 50%; opacity: 0;
  transition: transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.25s ease;
  pointer-events: none;
}
.progress.run { opacity: 1; transform: scaleX(0.75); }
.progress.done { opacity: 0; transform: scaleX(1); transition: transform 0.2s ease, opacity 0.35s ease 0.1s; }

/* ---- The About page ---- */

.wrap { max-width: 720px; margin: 0 auto; padding: 0 20px; }
header.site {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: max(20px, env(safe-area-inset-top)) 0 0;
}
.brand {
  font-family: var(--brand); font-size: 26px; line-height: 1; letter-spacing: 0.05em;
  text-transform: uppercase; text-decoration: none; color: var(--leaf);
}
nav.site a {
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 16px; border-radius: 999px;
  background: var(--glass);
  box-shadow: var(--edge);
  font-size: 15px; font-weight: 600; color: var(--label); text-decoration: none; margin-left: 10px;
}
.wrap main { padding: 44px 0 72px; line-height: 1.5; }
.wrap h1 { font-size: 40px; font-weight: 800; line-height: 1.08; letter-spacing: -0.03em; margin: 0 0 12px; }
.wrap h2 { font-size: 22px; font-weight: 700; letter-spacing: -0.02em; margin: 40px 0 10px; }
.wrap p { max-width: 62ch; }
.lead { font-size: 21px; color: var(--label-2); }
.rule { border: none; border-top: 1px solid var(--sep); margin: 30px 0; }
blockquote { margin: 26px 0; padding: 18px 20px; border-radius: var(--r-card); color: var(--label); }
blockquote p:last-child { margin-bottom: 0; }
figure { margin: 34px 0; }
figure img { display: block; width: 100%; height: auto; border-radius: var(--r-card); box-shadow: var(--drop); }
figcaption { margin: 10px 6px 0; font-size: 13px; color: var(--label-2); }
footer.site {
  border-top: 1px solid var(--sep); padding: 20px 0 40px;
  font-size: 15px; color: var(--label-2);
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
}
footer.site a { color: var(--leaf); text-decoration: none; }
@media (max-width: 620px) {
  .wrap h1 { font-size: 34px; }
  .lead { font-size: 19px; }
}

@media (max-width: 380px) {
  .tile .value { font-size: 21px; }
  .act-ico { width: 56px; height: 56px; }
}

/* ---- Behaving like an app ---- */

/* Pages change in place (app.js). The old and the new one cross-fade, and
   the logo is carried from where it was to where it will be — from the launch
   screen up to the sign-in form, from there into the account's header. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }           /* for the rare real navigation */
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.3s; animation-timing-function: ease; }
  html[data-nav="refresh"]::view-transition-old(root), html[data-nav="refresh"]::view-transition-new(root) { animation-duration: 0.18s; }
  .brand-mark { view-transition-name: brand; }
  ::view-transition-group(brand) { animation-duration: 0.5s; animation-timing-function: cubic-bezier(0.2, 0.85, 0.25, 1); }
  ::view-transition-old(brand), ::view-transition-new(brand) { height: 100%; object-fit: contain; }
  /* browsers without view transitions: a plain fade */
  body.is-leaving #view > * { opacity: 0; transition: opacity 0.13s ease; }
  body.is-arriving #view > main, body.is-arriving #view > .wrap { animation: arrive 0.32s cubic-bezier(0.22, 0.9, 0.3, 1); }
}
@keyframes arrive { from { opacity: 0; transform: translateY(8px); } }
/* a refused key: the field shakes its head, the way a lock screen does */
.shake { animation: shake 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97); }
@keyframes shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-8px); }
  40%, 60% { transform: translateX(8px); }
}

/* the installed app on a phone turned on its side: iOS cannot lock a web
   app's rotation, so the page asks to be turned back instead of rearranging */
.turn-back { display: none; }
@media (orientation: landscape) and (max-height: 520px) {
  html.standalone .turn-back {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
    position: fixed; inset: 0; z-index: 300; padding: 24px; text-align: center;
    background: var(--edge-bottom) url(wallpaper.svg) center / cover no-repeat;
    font-size: 17px; font-weight: 600; color: var(--label);
  }
  html.standalone .turn-back svg { width: 44px; height: 44px; color: var(--leaf); transform: rotate(-90deg); animation: upright 2.2s ease-in-out infinite; }
}
@keyframes upright { 0%, 25% { transform: rotate(-90deg); } 60%, 100% { transform: rotate(0deg); } }

/* the hidden switch app.js flips to make an iPhone tick */
.haptic { position: fixed; left: -200px; top: 0; width: 1px; height: 1px; overflow: hidden; opacity: 0; pointer-events: none; }

/* no 300 ms wait and no double-tap zoom on anything that is pressed */
a, button, summary, input, .btn, .icon-btn { touch-action: manipulation; }

/* installed on the Home Screen: nothing gets selected or pops a link preview
   by accident, and the page does not rubber-band — the pull gesture is ours */
html.standalone body {
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
  overscroll-behavior-y: none;
}
html.standalone input, html.standalone .who { -webkit-user-select: text; user-select: text; }

@media (prefers-reduced-motion: reduce) {
  body.gate .brand-mark::before, body.gate .brand-mark::after { animation: none; }
  .btn, .icon-btn, .store, .chev, .lang a, .act, .me, .row-card, .tabbar button, .inbox-bar, .refresher, .device-model, .deck-dots button::before { transition: none; }
  .inbox { animation: none; }
  .is-pressed { transform: none; }
  .qr-box { animation: none; }
  .toast { transition: opacity 0.18s ease; transform: translate(-50%, 0); }
}
/* ---- The account on a computer ---- */

/* A wide window with a mouse gets its own arrangement of the same page: the
   tabs stand in a column on the left under the logo, the device is a large
   panel with arrows beside it, the list of devices and the three figures
   are a column on the right, and the notifications open as a panel from the
   right edge. A phone or a tablet never sees this, however wide: there the
   page is an app and stays one. */
@media (min-width: 900px) and (hover: hover) and (pointer: fine) {
  body.app-page { padding-left: 248px; }
  .app {
    max-width: 1120px; padding: 28px 40px 40px;
    display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "inbox top" "pane pane";
    align-content: start; gap: 24px 16px;
  }
  .refresher, .install, body.app-page .edge { display: none; }      /* no pull to refresh, no Home Screen tip, no strips for a phone's screen edges */

  /* the column on the left: the logo, then the tabs as a list */
  .tabbar {
    top: 0; right: auto; width: 248px; padding: 104px 16px 24px;
    box-shadow: 1px 0 0 rgba(255, 255, 255, 0.08);
  }
  .tabbar-in { max-width: none; margin: 0; display: flex; flex-direction: column; gap: 4px; }
  .tabbar button {
    flex-direction: row; justify-content: flex-start; gap: 12px; padding: 12px 14px; border-radius: 16px;
    font-size: 16px; font-weight: 600; letter-spacing: -0.01em; color: var(--label-2);
    transition: transform 0.4s var(--spring), color 0.2s, background 0.2s;
  }
  .tabbar svg { width: 22px; height: 22px; }
  .tabbar button:hover { background: rgba(255, 255, 255, 0.05); }
  .tabbar button.on { background: rgba(255, 255, 255, 0.08); color: var(--leaf); }
  .tabbar button:focus-visible { outline: 3px solid rgba(206, 230, 187, 0.75); outline-offset: -3px; }
  .topbar .brand-mark { position: fixed; left: 30px; top: 34px; z-index: 61; width: 138px; margin: 0; }

  /* the top row: the latest notification as a pill, the account and the way out at the right */
  .inbox-bar {
    grid-area: inbox; justify-self: start; margin: 0; padding: 0 22px 0 18px; height: 48px; min-width: 300px; max-width: 100%;
    border-radius: 999px; transition: filter 0.2s;
  }
  .inbox-bar::after { display: none; }
  .inbox-bar:hover { filter: brightness(1.2); }
  .inbox-line { justify-content: flex-start; }
  .topbar { grid-area: top; padding: 0; gap: 10px; }
  .me:hover, .act:not(:disabled):hover .act-ico { filter: brightness(1.15); }
  .pane { grid-area: pane; gap: 20px; }
  .pane-title { margin: 0 4px; }
  .pane[data-pane="app"], .pane[data-pane="help"] { max-width: 720px; }

  /* the home pane: the device large, a column beside it */
  .pane[data-pane="home"] { display: grid; grid-template-columns: minmax(0, 1fr) 340px; align-items: start; }
  .pane[data-pane="home"][hidden] { display: none; }
  .hero {
    position: relative; display: flex; flex-direction: column; justify-content: center; gap: 14px;
    min-height: 580px; padding: 26px 0 30px; border-radius: 32px; background: var(--panel); overflow: hidden;
  }
  .hero .devices { margin: 0; }
  .hero .device-name { font-size: 48px; }
  .hero .device-stage { font-size: 13px; margin-top: 10px; }
  .hero .act-ico { transition: filter 0.2s; }
  .deck-arrow {
    position: absolute; top: 50%; z-index: 3; width: 46px; height: 46px; margin-top: -40px; padding: 0;
    display: flex; align-items: center; justify-content: center;
    border: 0; border-radius: 50%; background: var(--raised); color: var(--label); cursor: pointer;
    transition: transform 0.4s var(--spring), filter 0.2s;
  }
  .deck-arrow.prev { left: 22px; }
  .deck-arrow.prev svg { transform: rotate(180deg); }
  .deck-arrow.next { right: 22px; }
  .deck-arrow svg { width: 20px; height: 20px; color: inherit; }
  .deck-arrow:hover { filter: brightness(1.2); }
  .deck-arrow:focus-visible, .device-row:focus-visible { outline: 3px solid rgba(206, 230, 187, 0.75); outline-offset: 2px; }

  .side { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
  .device-list { display: block; padding: 8px; border-radius: 24px; background: var(--panel); }
  .list-title { margin: 0; padding: 12px 12px 8px; font-size: 13px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--label-3); }
  .device-rows { display: flex; flex-direction: column; gap: 2px; }
  .device-row {
    display: flex; align-items: center; gap: 12px; width: 100%; min-height: 50px; padding: 0 12px;
    border: 0; border-radius: 16px; background: none; color: var(--label); cursor: pointer;
    font: inherit; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; text-align: left;
    transition: transform 0.4s var(--spring), background 0.2s;
  }
  .device-row:hover { background: rgba(255, 255, 255, 0.05); }
  .device-row[aria-current="true"] { background: rgba(255, 255, 255, 0.09); }
  .row-dot { flex: 0 0 auto; width: 8px; height: 8px; margin: 0 5px; border-radius: 50%; background: var(--label-3); }
  .device-row.live .row-dot { background: #b4f08c; box-shadow: 0 0 8px rgba(180, 240, 140, 0.9); }
  .row-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .row-state { flex: 0 0 auto; font-size: 13px; font-weight: 500; color: var(--label-3); }
  .device-row.live .row-state { color: #dcf6ca; }
  .device-row.add { color: var(--label-2); }
  .device-row.add > svg { flex: 0 0 auto; width: 18px; height: 18px; }
  .tiles { padding: 20px 4px; }

  /* the notifications: a panel from the right edge, the page dimmed behind it */
  .inbox { justify-content: flex-end; background: rgba(4, 8, 5, 0.55); animation: inbox-dim 0.25s ease; }
  .inbox-box {
    flex: 0 0 440px; max-width: 440px; margin: 0; padding: 28px 20px 24px;
    background: var(--edge-bottom); box-shadow: -1px 0 0 rgba(255, 255, 255, 0.08);
    animation: inbox-side 0.36s cubic-bezier(0.2, 0.9, 0.25, 1);
  }
  body.app-page .toast { bottom: 32px; }
}
@keyframes inbox-dim { from { opacity: 0; } }
@keyframes inbox-side { from { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .inbox-box { animation: none; } }

/* where the browser cannot blur what is behind, the glass turns a shade more solid */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  :root {
    --glass: linear-gradient(180deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0.03)), rgba(30, 42, 30, 0.86);
  }
}
