/*
 * The Finova kit, as CSS — the phone app's own design, not a web approximation of it.
 *
 * Every value here comes from the native app's `Theme.kt` and `Components.kt`: the palettes, Satoshi and its ramp, the
 * 56px pill, the 20px row card, the 24px settings group, the 72px tab bar with its 24px shoulders, the dark card face
 * with its accent glow and five contactless rings, and the two background fields (`softField`, `heroField`). Where a
 * number looks arbitrary it is the kit's. A person who uses the phone app and then opens this should not be able to
 * tell they changed programs.
 *
 * What is ours is the wide layout, because the phone app has none. The way X does it: under 700px it is the phone,
 * bottom bar and all; from 700px the bar becomes an icon rail; from 1100px a full rail with labels; from 1300px a
 * sidebar on the right. The content keeps a phone's measure in the middle at every width, and a sheet that rises from
 * the bottom on a phone opens as a dialog on a desk.
 */

@font-face { font-family: Satoshi; src: url('/assets/font/satoshi_regular.ttf') format('truetype'); font-weight: 400; font-display: swap; }
@font-face { font-family: Satoshi; src: url('/assets/font/satoshi_medium.ttf') format('truetype'); font-weight: 500; font-display: swap; }
@font-face { font-family: Satoshi; src: url('/assets/font/satoshi_bold.ttf') format('truetype'); font-weight: 700; font-display: swap; }

/* ── Tokens ─────────────────────────────────────────────── */
:root {
  --green: #a0e86f;
  --green-link: #037a3b;              /* text links: 4.5:1 on white (the brand green stays for fills) */
  --ink: #222222;
  --coral: #fd7b60;
  --yellow: #eec145;
  --hero-base: #d7e39b;
  --v3: #eec145; --v42: #a0e86f; --v43: #6fd3e8; --v44: #c7b0ff;
  --paper: #f2f7f6;

  /* LightPalette */
  --frame: #f2f7f6;
  --surface: #ffffff;
  --medallion: #f2f7f6;
  --text: #222222;
  --muted: rgba(34, 34, 34, 0.7);      /* 4.5:1 on the frame and on white */
  --divider: #f2f7f6;
  --scrim: rgba(34, 34, 34, 0.6);
  --field: #ffffff;
  --tab-bar: #ffffff;
  --tab-pill: #f2f7f6;
  --line: #e2eae7;                          /* the desktop column's edges; the phone has none */
  --float-shadow: 0 6px 20px rgba(34, 34, 34, 0.07), 0 2px 6px rgba(34, 34, 34, 0.04);
  --soft-green: rgba(160, 232, 111, 0.5);
  --soft-white: rgba(255, 255, 255, 0.55);
  --pill-glass: #ffffff;
  /* How strongly a network's colour shows (the network sweep: src/networks.js has the colours): the glow behind the active
     network's name, the ring of the one shown in the list, and the wash through the header and the top of the page —
     light enough that every word on them keeps AA. */
  --net-halo: 46%; --net-ring: 58%; --net-wash: 24%;
  color-scheme: light;

  --gutter: 20px;
  --tab-bar-height: 72px;
  --measure: 600px;
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --frame: #222222; --surface: #2f3136; --medallion: rgba(255, 255, 255, 0.1); --text: #ffffff;
    --muted: rgba(255, 255, 255, 0.6); --divider: rgba(255, 255, 255, 0.06); --scrim: rgba(0, 0, 0, 0.6);
    --field: #2f3136; --tab-bar: #2f3136; --tab-pill: rgba(255, 255, 255, 0.1); --line: rgba(255, 255, 255, 0.08);
    --float-shadow: none; --soft-green: rgba(160, 232, 111, 0.28); --soft-white: rgba(255, 255, 255, 0);
    --pill-glass: rgba(255, 255, 255, 0.12); color-scheme: dark; --green-link: #4fd88b; --coral-text: #fd7b60;
    --net-halo: 30%; --net-ring: 72%; --net-wash: 20%;
  }
}
:root[data-theme="dark"] {
  --frame: #222222; --surface: #2f3136; --medallion: rgba(255, 255, 255, 0.1); --text: #ffffff;
  --muted: rgba(255, 255, 255, 0.6); --divider: rgba(255, 255, 255, 0.06); --scrim: rgba(0, 0, 0, 0.6);
  --field: #2f3136; --tab-bar: #2f3136; --tab-pill: rgba(255, 255, 255, 0.1); --line: rgba(255, 255, 255, 0.08);
  --float-shadow: none; --soft-green: rgba(160, 232, 111, 0.28); --soft-white: rgba(255, 255, 255, 0);
  --pill-glass: rgba(255, 255, 255, 0.12); color-scheme: dark; --green-link: #4fd88b; --coral-text: #fd7b60;
  --net-halo: 30%; --net-ring: 72%; --net-wash: 20%;
}

/* ── Base ───────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
/* Page heights use svh (the viewport with the browser's bars showing), not dvh: dvh changes on every frame of a phone's
   address bar sliding in or out, which re-laid the whole page out mid-scroll and made the bottom bar and the scanner
   jump. Overlays, which must fit what is visible, keep dvh. No rubber band and no pull-to-refresh: this is an app. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; overscroll-behavior-y: none; }
/* While the scanner, a sheet or the loader is up, the page under it holds still: a thumb on the camera view must not
   scroll the page behind it (which on a phone slides the address bar and resizes the camera). */
html.locked, html.locked body { overflow: hidden; }
body {
  margin: 0; min-height: 100svh; background: var(--frame); color: var(--text);
  font: 400 16px/22px Satoshi, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-x: clip;
  -webkit-tap-highlight-color: transparent;
}
button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; }
button:disabled { cursor: default; }
a { color: var(--green-link); }
h1, h2, h3, p { margin: 0; font-weight: inherit; }
svg { display: block; flex: none; }
:focus-visible { outline: 2px solid var(--green-link); outline-offset: 2px; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* The kit's type ramp. */
.t-display { font-size: 48px; line-height: 52px; font-weight: 500; }
.t-hero    { font-size: 32px; line-height: 40px; font-weight: 500; }
.t-title   { font-size: 24px; line-height: 30px; font-weight: 500; }
.t-sheet   { font-size: 24px; line-height: 32px; font-weight: 700; }
.t-section { font-size: 18px; line-height: 24px; font-weight: 500; }
.t-body    { font-size: 16px; line-height: 22px; font-weight: 400; }
.t-bodym   { font-size: 16px; line-height: 22px; font-weight: 500; }
.t-label   { font-size: 14px; line-height: 19px; font-weight: 400; }
.t-labelm  { font-size: 14px; line-height: 19px; font-weight: 500; }
.t-caption { font-size: 12px; line-height: 16px; font-weight: 400; }
.t-captionm{ font-size: 12px; line-height: 16px; font-weight: 500; }
.t-tiny    { font-size: 10px; line-height: 14px; font-weight: 400; }
.muted { color: var(--muted); }
.coral { color: var(--coral-text, #c1432a); }         /* text: dark coral on light, the bright one on dark */
.link { color: var(--green-link); }
.center { text-align: center; }
.mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; }
.clip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

.stack { display: grid; gap: 16px; }
.stack-12 { display: grid; gap: 12px; }
.stack-8 { display: grid; gap: 8px; }
.row { display: flex; align-items: center; min-width: 0; }
.grow { flex: 1; min-width: 0; }
.gutter { padding-inline: var(--gutter); }

/* ── Shell ──────────────────────────────────────────────── */
.app { display: flex; justify-content: center; min-height: 100svh; }
.rail, .aside { display: none; }
.main {
  width: 100%; max-width: var(--measure); min-width: 0; min-height: 100svh; position: relative;
  padding-bottom: calc(var(--tab-bar-height) + 24px + env(safe-area-inset-bottom));
}
.main.page { padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
/* A screen is its own stacking context (so a background layer inside it can sit above its field and below all its
   content) and clips anything wider than itself, so no decoration can ever widen the page. */
.screen { padding-top: env(safe-area-inset-top); isolation: isolate; overflow-x: clip; }
/* A screen fills what is left of the viewport above the bar, and no more: a short screen does not scroll. */
.main > .screen { min-height: calc(100svh - var(--tab-bar-height) - 24px - env(safe-area-inset-bottom)); }
.main.page > .screen { min-height: calc(100svh - 24px - env(safe-area-inset-bottom)); }

/* Splash and the tap gate: the frame colour with green light coming in from the right (Modifier.softField). */
.soft {
  background:
    radial-gradient(circle min(95vw, 570px) at 102% 42%, var(--soft-green), transparent),
    radial-gradient(circle min(70vw, 420px) at 0% 10%, var(--soft-white), transparent),
    var(--frame);
}
/* The kit's #D7E39B hero with its four blurred ellipses (Modifier.heroField). */
.hero-field {
  background:
    radial-gradient(circle 470px at 9% 94%, #8cd484, transparent),
    radial-gradient(circle 280px at 11% 12%, #c5e38f, transparent),
    radial-gradient(circle 400px at 87% 32%, #e5e293, transparent),
    radial-gradient(circle 280px at 88% 95%, #a7d98d, transparent),
    var(--hero-base);
}

/* ── Top bar: round back button, centred 18 Medium title, an action (TopBar) ── */
.topbar {
  position: relative; height: 54px; margin: 10px var(--gutter) 12px;
  display: flex; align-items: center; justify-content: center;
}
.topbar .title { font-size: 18px; line-height: 24px; font-weight: 500; max-width: calc(100% - 136px); }
.topbar .start { position: absolute; left: 0; top: 50%; transform: translateY(-50%); }
.topbar .end { position: absolute; right: 0; top: 50%; transform: translateY(-50%); display: flex; gap: 8px; }

/* A page's actions, held at the bottom of the screen (PageFrame's bottom column). */
.bottom-bar {
  position: sticky; bottom: 0; z-index: 10; padding-top: 16px; padding-bottom: calc(16px + env(safe-area-inset-bottom));
  background: linear-gradient(to bottom, transparent, var(--frame) 22px);
}

/* ── Tab bar (TabBar / TabItem) ─────────────────────────── */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  height: calc(var(--tab-bar-height) + env(safe-area-inset-bottom));
  padding: 0 8px env(safe-area-inset-bottom); gap: 4px;
  /* Five equal targets keep Make centered. Labels stay visible, including on a 320 px phone. */
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); align-items: center; justify-items: center;
  background: var(--tab-bar); border-radius: 24px 24px 0 0;
  box-shadow: 0 -6px 24px rgba(34, 34, 34, 0.13);
}
.tab {
  display: inline-flex; flex-direction: column; justify-content: center; align-items: center; gap: 3px; height: 54px; width: 100%; min-width: 0; padding: 3px 2px;
  border: 0; background: transparent; border-radius: 16px; color: var(--text); text-decoration: none;
  transition: background-color 0.2s var(--ease);
}
.tab svg { width: 24px; height: 24px; }
.tab .name { display: block; font-size: 11px; line-height: 14px; font-weight: 500; white-space: nowrap; }
.tab[aria-current="page"] { background: var(--green); color: var(--ink); }      /* ink on the green pill: readable */
.make {
  width: 48px; height: 48px; border: 0; border-radius: 999px; background: var(--green); color: var(--ink);
  display: inline-grid; place-items: center; flex: none; text-decoration: none;
}
.make svg { width: 24px; height: 24px; }
.make .name { display: none; }
/* The Trading Post shares Market's tab; the switch at the top of Market opens it. */
.tabbar .make { display: flex; flex-direction: column; justify-content: center; gap: 2px; width: 48px; height: 54px; margin: 0; border-radius: 18px; }
.tabbar .make .name { display: block; font-size: 11px; line-height: 14px; font-weight: 700; }

/* ── Controls ───────────────────────────────────────────── */
.btn {
  height: 56px; border-radius: 999px; border: 0; width: 100%; padding: 0 20px;
  font-size: 18px; line-height: 24px; font-weight: 500; white-space: nowrap;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; text-decoration: none;
  background: var(--green); color: var(--ink); transition: transform 0.12s var(--ease), opacity 0.2s;
}
.btn:active:not(:disabled) { transform: scale(0.985); }
.btn:disabled { background: rgba(160, 232, 111, 0.45); color: rgba(34, 34, 34, 0.5); }
.btn.outline { background: transparent; color: var(--text); border: 1px solid var(--text); }
.btn.white { background: var(--surface); color: var(--text); font-size: 16px; line-height: 22px; }
.btn.white svg { width: 22px; height: 22px; }
.btn.danger { color: var(--coral); }
/* The confirm of something that cannot be taken back: coral, never the green that means "go on". */
.btn.destroy { background: var(--coral); color: var(--ink); }
.btns { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.btns.gap15 { gap: 15px; }

.circle {
  width: 54px; height: 54px; border-radius: 999px; border: 0; padding: 0; flex: none;
  display: inline-grid; place-items: center; background: var(--surface); color: var(--text); text-decoration: none;
}
.circle svg { width: 24px; height: 24px; }
.circle.s44 { width: 44px; height: 44px; }
.circle.s52 { width: 52px; height: 52px; }
.circle.s48 { width: 48px; height: 48px; }
.circle.s36 { width: 36px; height: 36px; }
.circle.s36 svg { width: 20px; height: 20px; }
.circle.green { background: var(--green); color: var(--ink); }
.circle.glass { background: rgba(255, 255, 255, 0.7); }
:root[data-theme="dark"] .circle.glass { background: rgba(47, 49, 54, 0.12); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .circle.glass { background: rgba(47, 49, 54, 0.12); } }
.circle.medal { background: var(--medallion); }
.mirror svg { transform: scaleX(-1); }

/* A hero action: 56 high white pill, 20px icon over a 10px label (ActionPill). */
.pills { display: flex; gap: 8px; justify-content: center; }
.pill-action {
  flex: 1; max-width: 50%; height: 56px; border: 0; border-radius: 999px; background: #fff; color: var(--ink);
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font-size: 10px; line-height: 14px;
}
.pills.many .pill-action { max-width: none; }
.pill-action svg { width: 20px; height: 20px; }

.small-pill {
  border: 0; border-radius: 999px; padding: 9px 16px; font-size: 12px; line-height: 16px;
  background: var(--pill-glass); color: var(--text); box-shadow: 0 4px 12px rgba(34, 34, 34, 0.14);
}

/* ── Rows and cards ─────────────────────────────────────── */
.medal {
  width: 48px; height: 48px; border-radius: 999px; background: var(--medallion); color: var(--text);
  display: inline-grid; place-items: center; flex: none;
}
.medal svg { width: 24px; height: 24px; }
.medal.s42 { width: 42px; height: 42px; } .medal.s42 svg { width: 20px; height: 20px; }
.medal.s64 { width: 64px; height: 64px; } .medal.s64 svg { width: 28px; height: 28px; }
.medal.s74 { width: 74px; height: 74px; } .medal.s74 svg { width: 30px; height: 30px; }
.medal.s76 { width: 76px; height: 76px; } .medal.s76 svg { width: 34px; height: 34px; }
.medal.green { background: var(--green); color: var(--ink); }
.medal.coral { background: var(--coral); color: var(--ink); }
.medal.coral-soft { background: rgba(253, 123, 96, 0.16); color: var(--coral); }
.medal.white { background: #fff; color: var(--ink); }
.medal.surface { background: var(--surface); }
.medal.card-avatar { background: var(--ink); color: var(--green); }
.medal.card-avatar svg { width: 46%; height: 46%; }

.rowcard {
  display: flex; align-items: center; width: 100%; padding: 12px; border: 0; text-align: left;
  border-radius: 20px; background: var(--surface); color: var(--text); text-decoration: none; min-width: 0;
}
.rowcard .body { flex: 1; min-width: 0; padding: 0 8px 0 11px; display: grid; gap: 4px; }
.rowcard .body > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rowcard.selected { box-shadow: inset 0 0 0 1.5px var(--green); }
button.rowcard:active, a.rowcard:active { transform: scale(0.992); }
.chev { width: 22px; height: 22px; transform: scaleX(-1); flex: none; }

.radio {
  width: 22px; height: 22px; border-radius: 999px; margin-right: 4px; flex: none;
  box-shadow: inset 0 0 0 1.5px var(--muted); display: grid; place-items: center;
}
.selected .radio { box-shadow: inset 0 0 0 1.5px var(--green); }
.selected .radio::after { content: ''; width: 12px; height: 12px; border-radius: 999px; background: var(--green); }

.where { width: 28px; height: 28px; border-radius: 999px; background: var(--medallion); display: grid; place-items: center; }
.where svg { width: 15px; height: 15px; }

.float { border-radius: 24px; background: var(--surface); padding: 16px; box-shadow: var(--float-shadow); color: var(--text); text-align: left; border: 0; width: 100%; display: block; text-decoration: none; }
.float .row > .grow { padding-left: 11px; display: grid; gap: 4px; }
.panel { border-radius: 24px; background: var(--surface); padding: 16px; }

.group { border-radius: 24px; background: var(--surface); overflow: hidden; }
.srow {
  display: flex; align-items: center; width: 100%; height: 80px; padding: 0 16px; border: 0; gap: 16px;
  background: transparent; color: var(--text); text-align: left; text-decoration: none;
}
.srow + .srow { box-shadow: inset 0 1px 0 var(--divider); }
.srow .label { flex: 1; min-width: 0; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.srow .value { font-size: 12px; line-height: 16px; color: var(--muted); padding-right: 8px; white-space: nowrap; max-width: 45%; overflow: hidden; text-overflow: ellipsis; }
.srow.danger { color: var(--coral); }
.srow.danger .medal { color: var(--coral); }
.srow:disabled { opacity: 0.55; }

.switch {
  width: 44px; height: 24px; border-radius: 999px; padding: 2px; border: 0; flex: none;
  background: rgba(34, 34, 34, 0.18); display: flex; transition: background-color 0.2s var(--ease);
}
:root[data-theme="dark"] .switch { background: rgba(255, 255, 255, 0.18); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .switch { background: rgba(255, 255, 255, 0.18); } }
.switch::after { content: ''; width: 20px; height: 20px; border-radius: 999px; background: #fff; transition: transform 0.2s var(--ease); }
.switch[aria-checked="true"], [aria-checked="true"] > .switch { background: var(--green) !important; }
.switch[aria-checked="true"]::after, [aria-checked="true"] > .switch::after { transform: translateX(20px); }

.segmented { display: flex; height: 54px; padding: 4px; border-radius: 16px; background: var(--surface); }
.segmented button {
  flex: 1; border: 0; border-radius: 12px; background: transparent; color: var(--muted);
  font-size: 14px; line-height: 19px; padding: 0 6px; white-space: nowrap;
}
.segmented button[aria-pressed="true"] { background: var(--medallion); color: var(--text); font-weight: 500; }

.section-head { display: flex; align-items: center; justify-content: space-between; }
.section-head .link { background: none; border: 0; padding: 4px 2px; font-size: 14px; line-height: 19px; color: var(--green-link); }

/* Label / value rows (InfoRows, DetailRows). */
.info { border-radius: 24px; background: var(--surface); padding: 0 16px; }
.info .irow { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 16px 0; }
.info .irow + .irow { box-shadow: inset 0 1px 0 var(--divider); }
.info .irow .k { color: var(--muted); font-size: 14px; line-height: 19px; }
.info .irow .v { font-size: 14px; line-height: 19px; font-weight: 500; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.info.detail .irow { padding: 14px 0; }
.info.detail .irow .k { color: var(--text); }
.info.detail .irow .note { display: block; color: var(--muted); font-size: 12px; line-height: 16px; margin-top: 2px; }

/* The kit's green receipt (DetailCard). */
.receipt { border-radius: 24px; background: var(--green); padding: 16px; color: var(--ink); }
.receipt .irow { display: flex; justify-content: space-between; gap: 16px; padding-bottom: 12px; margin-bottom: 12px; box-shadow: 0 1px 0 rgba(34, 34, 34, 0.15); font-size: 14px; line-height: 19px; }
.receipt .irow .v { font-weight: 500; text-align: right; }
.receipt .note { font-size: 12px; line-height: 16px; color: rgba(34, 34, 34, 0.75); text-align: center; margin-top: 4px; }

/* Fields (PillField / Field). */
.field { display: grid; gap: 6px; }
.field .fhead { display: flex; justify-content: space-between; padding: 0 4px; font-size: 14px; line-height: 19px; font-weight: 500; }
.field .count { font-size: 12px; font-weight: 400; color: var(--muted); }
.field .count.full { color: var(--coral); }
.pill-input {
  width: 100%; height: 56px; padding: 0 20px; border-radius: 999px; border: 0; outline: 0;
  background: var(--field); color: var(--text); box-shadow: inset 0 0 0 1.5px transparent; font-size: 16px;
}
textarea.pill-input { height: auto; min-height: 116px; padding: 16px 20px; border-radius: 24px; resize: vertical; line-height: 22px; }
.pill-input::placeholder { color: var(--muted); font-size: 14px; }
.pill-input:focus { box-shadow: inset 0 0 0 1.5px var(--green); }
.pill-input.error { box-shadow: inset 0 0 0 1.5px var(--coral); }
.pill-input:disabled { opacity: 0.55; }
/* On a white surface a white field would vanish: inside a sheet or a card it takes the frame colour instead. */
.sheet .pill-input, .panel .pill-input, .float .pill-input, .scanner .pill-input { background: var(--frame); }
.field .help { padding: 0 4px; font-size: 12px; line-height: 16px; color: var(--muted); }
.field .help.error { color: var(--coral); }

/* ── The Cryft Card (CardFace) ──────────────────────────── */
.face-box { container-type: inline-size; width: 100%; max-width: 520px; margin-inline: auto; }
.face {
  --accent: var(--green);
  --u: calc(100cqw / 350);                 /* one kit dp, at the card's own width */
  position: relative; width: 100%; aspect-ratio: 1000 / 631; overflow: hidden; isolation: isolate;
  border-radius: calc(var(--u) * 24); color: var(--paper);
  background:
    radial-gradient(circle calc(var(--u) * 217) at 86% 8%, color-mix(in srgb, var(--accent) 50%, transparent), transparent 100%),
    radial-gradient(circle calc(var(--u) * 175) at 5% 100%, rgba(238, 193, 69, 0.2), transparent 100%),
    linear-gradient(135deg, #2b2e31, #1d1f21 50%, #121314);
  box-shadow: 0 calc(var(--u) * 10) calc(var(--u) * 30) rgba(34, 34, 34, 0.3), inset 0 0 0 1px rgba(255, 255, 255, 0.14);
  font-family: Satoshi, sans-serif;
}
.face[data-format] { box-shadow: 0 calc(var(--u) * 10) calc(var(--u) * 30) rgba(34, 34, 34, 0.3), inset 0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent); }
.face[data-format="3"] { --accent: var(--v3); }
.face[data-format="4"] { --accent: var(--v42); }
.face[data-format="43"] { --accent: var(--v43); }
.face[data-format="44"] { --accent: var(--v44); }
.face .rings { position: absolute; inset: 0; width: 100%; height: 100%; z-index: -1; color: var(--accent); }
.face .tl { position: absolute; left: calc(var(--u) * 22); top: calc(var(--u) * 22); font-size: calc(var(--u) * 20); line-height: 1.2; }
.face .tl b { font-weight: 700; }
.face .tl span { opacity: 0.72; }
.face .tr { position: absolute; right: calc(var(--u) * 22); top: calc(var(--u) * 22); display: grid; justify-items: end; gap: calc(var(--u) * 4); }
.face .tr svg { width: calc(var(--u) * 30); height: calc(var(--u) * 30); }
.face .tag { font-weight: 700; font-size: calc(var(--u) * 8); letter-spacing: calc(var(--u) * 1.4); line-height: 1.2; }
.face .mid { position: absolute; left: calc(var(--u) * 22); top: 50%; transform: translateY(calc(var(--u) * -9)); }
.face .cap { font-weight: 700; font-size: calc(var(--u) * 9); letter-spacing: calc(var(--u) * 1.6); opacity: 0.5; line-height: 1.3; }
.face .cap.lost { color: var(--coral); opacity: 1; }
.face .big { font-weight: 500; font-size: calc(var(--u) * 28); line-height: 1.15; }
.face .num { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-weight: 700; font-size: calc(var(--u) * 18); letter-spacing: calc(var(--u) * 1); line-height: 1.35; }
.face .bl { position: absolute; left: calc(var(--u) * 22); bottom: calc(var(--u) * 22); width: 50%; }
.face .holds { font-weight: 500; font-size: calc(var(--u) * 15); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.face .br { position: absolute; right: calc(var(--u) * 22); bottom: calc(var(--u) * 22); display: grid; justify-items: end; }
.face .net { display: flex; align-items: center; gap: calc(var(--u) * 6); font-weight: 700; font-size: calc(var(--u) * 13); line-height: 1.3; }
.face .net i { width: calc(var(--u) * 7); height: calc(var(--u) * 7); border-radius: 999px; background: var(--accent); }
.face .chain { font-weight: 700; font-size: calc(var(--u) * 9); letter-spacing: calc(var(--u) * 1.2); color: var(--accent); line-height: 1.4; }
.face .patent { font-weight: 700; font-size: calc(var(--u) * 7); letter-spacing: calc(var(--u) * 1.4); opacity: 0.45; line-height: 1.4; }

/* Vendor identity is decorative: all normal card controls stay outside the face. */
.vendor-face {
  color: #fff3d6;
  background: radial-gradient(ellipse at 80% 40%, #344638 0%, transparent 65%), linear-gradient(135deg, #222e27, #101817 65%, #29291e);
  box-shadow: 0 14px 35px #152b252b, inset 0 0 0 1px #d9b972a6;
  animation: vendor-reveal 800ms cubic-bezier(.2,.7,.2,1) both;
}
.vendor-face::after { content: ''; position: absolute; inset: calc(var(--u)*8); border: 1px solid #dcc18a30; border-radius: calc(var(--u)*18); pointer-events: none; }
.vendor-face .tl span { font-size: calc(var(--u)*8); letter-spacing: calc(var(--u)*2); color: var(--green); opacity: 1; }
.vendor-emblem { position: absolute; width: 32%; height: auto; right: 4%; top: 23%; filter: drop-shadow(0 7px 12px #0005); }
.vendor-title { position: absolute; left: calc(var(--u)*22); top: calc(var(--u)*64); max-width: 56%; font-weight: 700; line-height: 1.1; }
.vendor-eyebrow { font-size: calc(var(--u)*17); font-weight: 500; margin-bottom: calc(var(--u)*6); }
.vendor-rewards { width: fit-content; padding: 0 calc(var(--u)*7) calc(var(--u)*3); margin-left: calc(var(--u)*-1); border: calc(var(--u)*1.4) solid var(--green); border-radius: calc(var(--u)*4); font-size: calc(var(--u)*30); }
.vendor-tapline { margin-top: calc(var(--u)*6); font-size: calc(var(--u)*11); font-weight: 500; }
.vendor-tagline { position: absolute; left: calc(var(--u)*22); right: calc(var(--u)*22); top: calc(var(--u)*157); color: #dce7d4; font-size: calc(var(--u)*8.5); font-weight: 500; line-height: 1.4; white-space: nowrap; }
.vendor-face .bl, .vendor-face .br { bottom: calc(var(--u)*17); }
.vendor-face .num { font-size: calc(var(--u)*12); }
.vendor-face .cap { color: #e3c58b; opacity: 1; font-size: calc(var(--u)*7); margin-bottom: calc(var(--u)*4); }
.vendor-kind { font-size: calc(var(--u)*9); line-height: 1.3; }
.vendor-edition { font-size: calc(var(--u)*7); line-height: 1.3; color: #bbcbba; margin-top: calc(var(--u)*4); }
.vendor-caption { display: grid; gap: 4px; text-align: center; font-size: 12px; color: var(--muted); margin: 14px 0 0; }
.vendor-caption strong { font-size: 14px; color: var(--text); font-weight: 700; }
.vendor-foil { pointer-events: none; position: absolute; inset: -60%; z-index: 2; opacity: 0; background: linear-gradient(112deg, transparent 35%, #fff4c52b 49%, transparent 62%); transform: translateX(-70%); animation: vendor-foil 1500ms 250ms ease-out both; }
@keyframes vendor-reveal { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes vendor-foil { 0% { opacity: 0; transform: translateX(-65%); } 35% { opacity: 1; } 100% { opacity: 0; transform: translateX(65%); } }
@media (prefers-reduced-motion: reduce) { .vendor-face, .vendor-foil { animation: none; } .vendor-foil { display: none; } }

/* The tap gate: the card tilted, with two slow waves behind it while the app listens.
   The waves are a background layer, never part of the page: clipped to the screen's width, behind everything else on
   it, and moved by transform alone. (They were animating their WIDTH up to 140% of the card area — wider and taller
   than the page every 2.4 s — so a phone re-fitted its viewport on every wave, bouncing the tab bar and the scanner.) */
.gate { position: relative; padding: 0 14px; }
.gate .face-box { transform: rotate(-6deg); }
.gate .waves {                  /* the screen's full width, centred on the card; the screen clips what it would not hold */
  position: absolute; z-index: -1; pointer-events: none; overflow: hidden; contain: strict;
  left: 50%; width: 100vw; transform: translateX(-50%); top: -45%; bottom: -45%;
}
.gate .wave {                   /* sized from the card (the layer's height follows it), not from the window */
  position: absolute; left: 50%; top: 50%; height: 128%; width: auto; aspect-ratio: 1; border-radius: 999px;
  border: 2px solid var(--green); opacity: 0; will-change: transform, opacity;
  transform: translate(-50%, -50%) scale(0.4); animation: wave 2.4s linear infinite;
}
.gate .wave + .wave { animation-delay: -1.2s; }
.gate.sensing .wave { border-width: 4px; animation-duration: 1.2s; }
@keyframes wave { from { transform: translate(-50%, -50%) scale(0.4); opacity: 0.55; } to { transform: translate(-50%, -50%) scale(1); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {    /* still listening, shown by one still ring instead of moving ones */
  .gate .wave { animation: none; opacity: 0.3; transform: translate(-50%, -50%) scale(0.62); }
  .gate .wave + .wave { display: none; }
}

/* ── Stats (Stat) ───────────────────────────────────────── */
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.stat { border-radius: 18px; background: var(--surface); padding: 14px 8px; text-align: center; min-width: 0; }
.stat .n { font-size: 24px; line-height: 30px; font-weight: 500; }
.stat .k { font-size: 12px; line-height: 16px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }

/* ── Wordmark and mark (CryftMark / Wordmark) ───────────── */
.mark { display: inline-grid; place-items: center; background: var(--green); color: var(--ink); flex: none; }
/* The brand mark (src/brand.js) draws its own squircle, so its box only holds and shapes it. */
.mark.brand { background: transparent; overflow: hidden; }
.mark.brand svg, .xmark .mark.brand svg { width: 100%; height: 100%; display: block; }
.xmark .mark.brand { border-radius: 30% !important; }
.wordmark { display: inline-flex; align-items: center; gap: 12px; font-weight: 700; color: var(--text); text-decoration: none; white-space: nowrap; }

/* ── Empty state ────────────────────────────────────────── */
.empty { display: grid; justify-items: center; text-align: center; padding: 56px 24px 0; gap: 0; }
.empty .medal { margin-bottom: 16px; }
.empty h2 { margin-bottom: 8px; }

/* ── Gifts inside a card (GiftTileCompact) ──────────────── */
.tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.tile { border-radius: 20px; background: var(--surface); overflow: hidden; border: 0; padding: 0; text-align: left; color: var(--text); box-shadow: inset 0 0 0 1px rgba(34, 34, 34, 0.06); }
.tile .art { aspect-ratio: 1; display: grid; place-items: center; position: relative; }
.tile .art .medal { width: 56px; height: 56px; background: rgba(255, 255, 255, 0.75); color: var(--ink); }
.tile .art .medal svg { width: 26px; height: 26px; }
.tile .art .private { position: absolute; top: 8px; right: 8px; border-radius: 999px; background: rgba(34, 34, 34, 0.7); color: #fff; font-size: 12px; line-height: 16px; padding: 3px 8px; }
.tile .words { padding: 12px; display: grid; gap: 0; }
.tile .words > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kind-greeting { background: #ffe3b3; } .kind-postcard { background: #cfe8ff; } .kind-business { background: #e6e0f8; } .kind-empty { background: #e5efe2; }

/* ── Format line and cards (FormatLine / FormatsPage) ───── */
.fline { display: flex; align-items: center; gap: 10px; border-radius: 16px; padding: 10px 14px; }
.fline .dot, .fcard .dot { width: 10px; height: 10px; border-radius: 999px; flex: none; }
.fcard { border-radius: 24px; background: var(--surface); overflow: hidden; }
.fcard .strip { height: 6px; }
.fcard .inner { padding: 20px; display: grid; gap: 10px; }
.fcard .info { background: var(--frame); }

/* ── Step dots (StepDot) ────────────────────────────────── */
.steps { display: flex; align-items: center; justify-content: center; gap: 8px; }
.stepdot { width: 22px; height: 22px; border-radius: 999px; background: var(--medallion); display: grid; place-items: center; font-size: 12px; line-height: 1; }
.stepdot.done { background: var(--green); color: var(--ink); }
.stepdot svg { width: 12px; height: 12px; }

/* ── Sheets (Sheet / SheetShell / ConfirmSheet) ─────────── */
.scrim {
  position: fixed; inset: 0; z-index: 60; background: var(--scrim); touch-action: none; overscroll-behavior: none;
  display: flex; align-items: flex-end; justify-content: center; animation: fade 0.2s var(--ease);
}
.sheet {
  width: 100%; max-height: 92dvh; overflow: auto; overscroll-behavior: contain;
  background: var(--surface); border-radius: 28px 28px 0 0; color: var(--text);
  padding: 12px var(--gutter) calc(28px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; align-items: stretch; text-align: center;
  animation: rise 0.3s var(--ease); touch-action: pan-y;
}
.sheet .handle { width: 56px; height: 4px; border-radius: 999px; background: var(--muted); margin: 0 auto 24px; flex: none; }
.sheet { position: relative; }
.sheet .sheet-close { position: absolute; top: 10px; right: 10px; z-index: 1; }
.sheet .sheet-close .circle { background: var(--medallion); }
.sheet .sheet-close + h2 { margin-inline: 48px; }
.sheet > .medal { align-self: center; }
.sheet .rule { height: 0.5px; background: var(--muted); margin: 12px 0; }
.scrim.closing { animation: fade 0.2s var(--ease) reverse forwards; }
.scrim.closing .sheet { animation: rise 0.2s var(--ease) reverse forwards; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes rise { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes pop { from { transform: translateY(12px) scale(0.97); opacity: 0; } to { transform: none; opacity: 1; } }

.qr { background: #fff; border-radius: 16px; padding: 12px; margin-inline: auto; }
.qr svg { width: 100%; height: 100%; }
/* While the page is hidden — another tab, another app, the app switcher taking its picture — no QR code and no link that
   carries a code is drawn (review SL-35): a pairing, a gift's or a set-up card's claim code, a transfer code. */
.hide-secrets .qr, .hide-secrets [data-secret] { visibility: hidden; }

/* A pulse around a medallion (WaitingSheet / TapNextSheet). */
.pulse { position: relative; display: grid; place-items: center; margin-inline: auto; }
.pulse .ring {
  position: absolute; left: 50%; top: 50%; aspect-ratio: 1; border-radius: 999px; border: 2px solid var(--green);
  transform: translate(-50%, -50%); animation: pulse 1.6s linear infinite; pointer-events: none;
}
.pulse .ring + .ring { animation-delay: -0.8s; }
@keyframes pulse { from { width: 72%; opacity: 0.7; } to { width: 115%; opacity: 0; } }

/* ── The loading overlay (LoadingSheet) ─────────────────── */
.loading { position: fixed; inset: 0; z-index: 70; display: grid; place-items: center; animation: fade 0.2s var(--ease); }
.loading .milestone {
  position: absolute; top: calc(18px + env(safe-area-inset-top)); left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; border-radius: 999px; background: var(--surface);
  padding: 10px 16px; font-size: 14px; line-height: 19px; font-weight: 500; white-space: nowrap;
  animation: drop 0.42s var(--ease);
}
.loading .milestone i { width: 10px; height: 10px; border-radius: 999px; background: var(--green); animation: blink 1.4s linear infinite; }
.loading .core { display: grid; justify-items: center; gap: 20px; }
.loading .loader { position: relative; width: 150px; height: 150px; display: grid; place-items: center; }
.loading .loader .ring {
  position: absolute; left: 50%; top: 50%; aspect-ratio: 1; border-radius: 999px; border: 1.5px solid var(--green);
  transform: translate(-50%, -50%); animation: load 1.4s linear infinite;
}
.loading .loader .ring:nth-child(2) { animation-delay: -0.47s; }
.loading .loader .ring:nth-child(3) { animation-delay: -0.93s; }
.loading .lifted { display: inline-flex; align-items: center; gap: 8px; border-radius: 999px; background: var(--green); color: var(--ink); padding: 8px 14px; font-size: 14px; font-weight: 500; }
.loading .core { padding: 0 var(--gutter); max-width: 460px; }
.loading .loading-note { min-height: 19px; max-width: 34ch; }
.loading .loading-note:empty { display: none; }
.loading .loading-stop { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
@keyframes load { from { width: 56%; opacity: 0.6; border-width: 3px; } to { width: 116%; opacity: 0; border-width: 1.5px; } }
@keyframes drop { from { transform: translate(-50%, -200%); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }

/* ── Toast ──────────────────────────────────────────────── */
.toast {
  position: fixed; top: calc(8px + env(safe-area-inset-top)); left: 50%; z-index: 90; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px; max-width: calc(100% - 32px);
  background: var(--ink); color: #fff; border-radius: 999px; padding: 12px 18px;
  font-size: 14px; line-height: 19px; font-weight: 500; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  animation: drop-toast 0.3s var(--ease);
}
.toast svg { width: 16px; height: 16px; color: var(--green); }
.toast .text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@keyframes drop-toast { from { transform: translate(-50%, -140%); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }

/* ── The laser (EdgeGlow): a trace running round the screen while the app works ── */
.edge {
  position: fixed; inset: 0; z-index: 95; pointer-events: none; opacity: 0; visibility: hidden; contain: strict;
  transition: opacity 0.7s var(--ease), visibility 0s linear 0.7s;    /* fades out, then stops being drawn at all */
}
.edge.on { opacity: 1; visibility: visible; transition: opacity 0.22s var(--ease), visibility 0s; }
.edge rect { fill: none; stroke: var(--green); stroke-linecap: round; animation: lap 2.6s linear infinite; }
.edge .halo { stroke-width: 10; opacity: 0.2; }
.edge .core { stroke-width: 2.5; opacity: 0.92; }
@keyframes lap { from { stroke-dashoffset: 0; } to { stroke-dashoffset: calc(-1 * var(--p)); } }

/* ── The scanner (ScanOverlay) ──────────────────────────── */
.scanner {
  position: fixed; inset: 0; z-index: 80; background: #121314; color: #fff; display: grid; place-items: center; animation: fade 0.2s;
  touch-action: none; overscroll-behavior: none;              /* a thumb on the camera view moves nothing */
}
.scanner video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.scanner .frame { position: relative; width: min(72vw, 300px); aspect-ratio: 1; border-radius: 28px; box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.5); }
.scanner .frame::before { content: ''; position: absolute; inset: 0; border-radius: 28px; border: 3px solid var(--green); }
.scanner .prompt { position: absolute; left: 24px; right: 24px; bottom: calc(40px + env(safe-area-inset-bottom)); text-align: center; display: grid; gap: 12px; justify-items: center; }
.scanner .prompt p { font-size: 16px; line-height: 22px; font-weight: 500; max-width: 34ch; }
.scanner .back { position: absolute; top: calc(16px + env(safe-area-inset-top)); left: 16px; }
.scanner .paste { width: min(100%, 420px); }

/* ── Onboarding (Onboarding) ────────────────────────────── */
.onboard { min-height: 100svh; display: flex; flex-direction: column; align-items: center; padding: env(safe-area-inset-top) var(--gutter) calc(24px + env(safe-area-inset-bottom)); max-width: 520px; margin: 0 auto; }
.onboard .skip { align-self: flex-end; height: 54px; margin-top: 10px; background: none; border: 0; color: var(--muted); font-size: 14px; }
.onboard .stage { flex: 1; display: grid; place-items: center; width: 100%; padding: 0 12px; }
.onboard .dots { display: flex; gap: 6px; margin: 22px 0 40px; }
.onboard .dots i { width: 8px; height: 8px; border-radius: 999px; background: var(--surface); transition: width 0.25s var(--ease), background-color 0.25s; }
.onboard .dots i.on { width: 24px; background: var(--green); }

/* ── Desktop (the X layout) ─────────────────────────────── */
.rail-item {
  display: flex; align-items: center; gap: 16px; height: 52px; padding: 0 16px; border-radius: 999px;
  color: var(--text); text-decoration: none; font-size: 18px; line-height: 24px; font-weight: 500; border: 0; background: transparent; width: max-content;
}
.rail-item svg { width: 26px; height: 26px; }
.rail-item:hover { background: var(--tab-pill); }
.rail-item[aria-current="page"] { background: var(--tab-pill); color: var(--green-link); }
.rail-item[aria-current="page"] svg { color: var(--green-link); }

@media (min-width: 700px) {
  .app { justify-content: center; }
  .rail {
    display: flex; flex-direction: column; gap: 6px; flex: none; position: sticky; top: 0; align-self: flex-start;
    height: 100dvh; width: 88px; padding: 16px 12px; align-items: center;
  }
  .rail .wordmark .words, .rail .rail-item .name, .rail .make .name, .rail .who .words { display: none; }
  .rail .rail-item { width: 52px; padding: 0; justify-content: center; }
  .rail .make { width: 52px; height: 52px; margin-top: 12px; }
  .rail .spacer { flex: 1; }
  .rail .who { display: flex; align-items: center; gap: 10px; border-radius: 999px; padding: 6px; border: 0; background: transparent; color: var(--text); text-decoration: none; }
  .rail .who:hover { background: var(--tab-pill); }
  .tabbar { display: none; }
  .home-top .wordmark { display: none; }       /* the rail carries it once */
  .main { border-left: 1px solid var(--line); border-right: 1px solid var(--line); padding-bottom: 48px; }
  .main.page { padding-bottom: 48px; }
  .topbar.sticky {
    position: sticky; top: 0; z-index: 20; margin: 0; padding: 10px var(--gutter) 12px; height: 76px;
    background: color-mix(in srgb, var(--frame) 82%, transparent); backdrop-filter: saturate(1.4) blur(14px); -webkit-backdrop-filter: saturate(1.4) blur(14px);
  }
  .topbar.sticky .start { left: var(--gutter); }
  .topbar.sticky .end { right: var(--gutter); }
  .scrim { align-items: center; padding: 24px; }
  .sheet { max-width: 480px; border-radius: 28px; padding-bottom: 28px; animation: pop 0.24s var(--ease); max-height: min(88dvh, 820px); }
  .sheet .handle { display: none; }
  .scrim.closing .sheet { animation: pop 0.18s var(--ease) reverse forwards; }
  .toast { top: 20px; }
}
@media (min-width: 1100px) {
  .rail { width: 260px; align-items: stretch; padding: 16px 20px; }
  .rail .wordmark { padding: 6px 12px 18px; }
  .rail .wordmark .words, .rail .rail-item .name, .rail .make .name, .rail .who .words { display: inline; }
  .rail .rail-item { width: max-content; padding: 0 20px 0 16px; justify-content: flex-start; }
  .rail .make { width: 100%; height: 56px; display: flex; align-items: center; justify-content: center; gap: 10px; font-size: 18px; font-weight: 500; margin-top: 16px; }
  .rail .who { padding: 10px 12px; }
  .rail .who .words { display: grid; text-align: left; min-width: 0; }
}
/* Tablet rails need readable destinations too: an icon alone hid the Trading Post in plain sight. The rail keeps its 88 px
   and draws its sides in to 8 px, so a 72 px place sits inside it ("Trading Post" and "Make a card" are about 62 px at
   11 px Satoshi, measured on cryft.app). */
@media (min-width: 700px) and (max-width: 1099px) {
  .rail { padding-left: 8px; padding-right: 8px; }
  .rail .rail-item { width: 72px; height: 60px; flex-direction: column; gap: 3px; border-radius: 16px; }
  .rail .make { display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 3px; width: 72px; height: 60px; border-radius: 16px; }
  .rail .rail-item .name, .rail .make .name { display: block; font-size: 11px; line-height: 14px; white-space: nowrap; }
}
@media (min-width: 1300px) {
  .aside { display: grid; align-content: start; gap: 16px; width: 350px; flex: none; position: sticky; top: 0; align-self: flex-start; padding: 16px 20px; max-height: 100dvh; overflow: auto; }
}

@media (hover: hover) {
  .rowcard[href]:hover, button.rowcard:hover, .srow[href]:hover, button.srow:hover:not(:disabled), .tile:hover, a.float:hover, button.float:hover { filter: brightness(0.985); }
  :root[data-theme="dark"] .rowcard[href]:hover, :root[data-theme="dark"] button.rowcard:hover, :root[data-theme="dark"] button.srow:hover:not(:disabled), :root[data-theme="dark"] .srow[href]:hover { filter: brightness(1.08); }
  .btn:hover:not(:disabled) { filter: brightness(0.97); }
  .circle:hover { filter: brightness(0.97); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001s !important; animation-iteration-count: 1 !important; transition-duration: 0.001s !important; }
  .gate .wave { opacity: 0.2; width: 90%; }
  .edge rect { stroke-dasharray: none; }
}

/* ── Signing in: the door (SignInScreen) ───────────────── */
.signin { min-height: 100svh; display: grid; justify-items: center; align-content: start; padding: 0 var(--gutter); }
.signin-hero { display: none; }
.signin-form { width: 100%; max-width: 460px; display: grid; justify-items: center; text-align: center; padding: 44px 0 32px; }
.signin-form > .btn, .signin-form > .stack-8 { width: 100%; }
.gate-loading { display: grid; justify-items: center; gap: 18px; padding: 28px 0 8px; }
.gate-loading .loader { position: relative; width: 132px; height: 132px; display: grid; place-items: center; }
.gate-loading .loader .ring {
  position: absolute; left: 50%; top: 50%; aspect-ratio: 1; border-radius: 999px; border: 1.5px solid var(--green);
  transform: translate(-50%, -50%); animation: load 1.4s linear infinite;
}
.gate-loading .loader .ring:nth-child(2) { animation-delay: -0.47s; }
.gate-loading .loader .ring:nth-child(3) { animation-delay: -0.93s; }
@media (min-width: 900px) {
  .signin { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: center; align-content: center; gap: 72px; max-width: 1180px; margin: 0 auto; padding: 40px 56px; }
  .signin-hero { display: grid; gap: 16px; justify-items: start; }
  .signin-hero .t-hero { font-size: 52px; line-height: 1.05; }
  .signin-hero .t-label { max-width: 440px; }
  .signin-card { width: 100%; max-width: 480px; transform: rotate(-6deg); margin: 0 0 36px 12px; filter: drop-shadow(0 30px 40px rgba(34, 34, 34, 0.18)); }
  .signin-form { padding: 0; justify-self: center; }
}

/* ── A voucher inside a card ───────────────────────────── */
.voucher {
  display: grid; gap: 12px; border-radius: 24px; padding: 18px; text-align: left;
  background: linear-gradient(135deg, color-mix(in srgb, var(--green) 26%, var(--surface)), var(--surface) 70%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--green) 55%, transparent);
}
.voucher.settled { background: var(--surface); box-shadow: inset 0 0 0 1px rgba(34, 34, 34, 0.06); }

/* ── A recovery under way: the wallet that holds the card is told, in red, with the one thing that stops it ── */
.recovery-alert { display: grid; gap: 8px; text-align: left; border-radius: 20px; padding: 14px 16px;
  background: color-mix(in srgb, var(--coral) 16%, var(--surface)); box-shadow: inset 0 0 0 1.5px var(--coral); }

/* ── Signing in: the way used last time, and steps to follow ── */
.last-way { color: var(--text); background: color-mix(in srgb, var(--yellow) 22%, var(--surface)); border-radius: 14px; padding: 10px 12px; text-align: left; }
.steps-list { padding-left: 22px; margin: 0; display: grid; gap: 4px; }

/* ── Status dots and pills ─────────────────────────────── */
.status-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--muted); display: inline-block; flex: none; }
.status-dot.on { background: var(--green); box-shadow: 0 0 0 3px color-mix(in srgb, var(--green) 30%, transparent); }
.pill-status { display: inline-flex; align-items: center; gap: 8px; border-radius: 999px; padding: 7px 12px; background: var(--surface); font-size: 13px; line-height: 17px; font-weight: 500; color: var(--text); }

/* ── Kota (KotaPage) ───────────────────────────────────── */
.kota-page { min-height: 100dvh; display: flex; flex-direction: column; }
.kota-head {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 12px; padding: 10px var(--gutter);
  background: color-mix(in srgb, var(--frame) 86%, transparent); backdrop-filter: saturate(1.4) blur(14px); -webkit-backdrop-filter: saturate(1.4) blur(14px);
}
.kota-avatar { display: grid; place-items: center; flex: none; border-radius: 999px; background: color-mix(in srgb, var(--green) 45%, var(--surface)); color: var(--ink); animation: breathe 3.2s var(--ease) infinite; }
@keyframes breathe { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--green) 40%, transparent); } 50% { box-shadow: 0 0 0 6px transparent; } }
.kota-log { flex: 1; display: grid; align-content: start; gap: 10px; padding-top: 8px; padding-bottom: 12px; }
.kbubble { display: flex; align-items: flex-end; gap: 8px; }
.kbubble.kota { padding-right: 36px; }
.kbubble.me { justify-content: flex-end; padding-left: 48px; }
.kbubble .text { border-radius: 20px; padding: 12px 16px; font-size: 16px; line-height: 22px; max-width: 100%; overflow-wrap: anywhere; }
.kbubble.kota .text { background: var(--surface); border-bottom-left-radius: 6px; }
.kbubble.me .text { background: var(--green); color: var(--ink); border-bottom-right-radius: 6px; white-space: pre-wrap; }
.kbubble .text p + p, .kbubble .text p + ul, .kbubble .text ul + p, .kbubble .text p + ol, .kbubble .text ol + p { margin-top: 8px; }
.kbubble .text ul, .kbubble .text ol { padding-left: 20px; display: grid; gap: 4px; }
.kbubble .text code { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 14px; background: var(--frame); border-radius: 6px; padding: 1px 5px; }
.kbubble .text a { color: var(--green-link); text-decoration: underline; }
.kbubble .text.dots { display: flex; gap: 5px; padding: 16px; }
.kbubble .text.dots i { width: 7px; height: 7px; border-radius: 999px; background: var(--muted); animation: blink 0.9s linear infinite; }
.kbubble .text.dots i:nth-child(2) { animation-delay: -0.6s; }
.kbubble .text.dots i:nth-child(3) { animation-delay: -0.3s; }
/* Suggestions wrap onto more lines rather than scrolling sideways past a hidden edge. */
.kota-chips { display: flex; flex-wrap: wrap; gap: 8px; padding-top: 4px; padding-bottom: 4px; }
.kchip {
  flex: 0 1 auto; max-width: 100%; min-height: 44px; border-radius: 22px; padding: 8px 14px; font-size: 13px; line-height: 17px; font-weight: 500;
  white-space: normal; text-align: left; overflow-wrap: anywhere;
  border: 1px solid color-mix(in srgb, var(--green) 60%, transparent); background: color-mix(in srgb, var(--green) 8%, transparent); color: var(--green-link);
}
/* A failure is the app's notice, not a Kota bubble. */
.knotice { display: flex; align-items: center; justify-content: space-between; gap: 12px; border-radius: 16px; padding: 10px 10px 10px 16px;
  background: color-mix(in srgb, var(--coral) 12%, var(--surface)); }
.knotice .small-pill { flex: none; min-height: 44px; }
.kota-banner { padding-top: 4px; padding-bottom: 8px; }
.kchip:disabled { opacity: 0.5; }
.kota-composer { position: sticky; bottom: 0; padding-top: 8px; padding-bottom: calc(10px + env(safe-area-inset-bottom)); background: var(--frame); }
.kota-composer .pill-input { min-width: 0; }
.kota-composer .circle:disabled { background: var(--surface); color: var(--muted); }
.kota-launcher {
  position: fixed; right: var(--gutter); bottom: calc(var(--tab-bar-height) + 16px + env(safe-area-inset-bottom)); z-index: 30;
  width: 56px; height: 56px; border-radius: 999px; display: grid; place-items: center; background: var(--green); color: var(--ink);
  box-shadow: 0 10px 24px rgba(34, 34, 34, 0.22);
}
@media (min-width: 700px) { .kota-launcher { bottom: 24px; } }

/* ── A phone as another screen's reader (/pair) ────────── */
.reader { min-height: 100svh; }
.reader-inner { max-width: 520px; margin: 0 auto; display: grid; justify-items: center; padding-top: 14px; padding-bottom: 32px; }
.reader-inner > .btn { width: 100%; }
.reader-inner .gate { width: 100%; }

/* ── The desk's door: X's logged-out layout ─────────────── */
.xsplash { min-height: 100dvh; display: grid; place-items: center; animation: fade 0.3s var(--ease); }
.xsplash .mark { animation: breathe 2.4s var(--ease) infinite; }
.xlogin { min-height: 100dvh; display: flex; flex-direction: column; }
.xmain { flex: 1; display: flex; align-items: stretch; }
.xmark { flex: 1 1 50%; display: grid; place-items: center; padding: 32px; }
.xmark .mark { width: min(380px, 62%) !important; height: auto !important; aspect-ratio: 1; border-radius: 28% !important; box-shadow: 0 40px 80px rgba(34, 34, 34, 0.12); }
.xmark .mark svg { width: 62%; height: 62%; }
.xdoor { flex: 1 1 50%; display: flex; flex-direction: column; justify-content: center; padding: 16px 48px 16px 16px; max-width: 760px; }
.xhero { font-size: 64px; line-height: 76px; font-weight: 700; letter-spacing: -1.2px; margin: 36px 0 44px; }
.xsub { font-size: 31px; line-height: 36px; font-weight: 700; margin-bottom: 28px; }
.xactions { width: 300px; display: grid; gap: 10px; }
.xactions .btn, .xdialog .btn { height: 44px; font-size: 15px; line-height: 20px; font-weight: 700; padding: 0 16px; }
.xactions .btn.white { box-shadow: inset 0 0 0 1px var(--line); }
.xactions .btn.white svg { width: 18px; height: 18px; }
.xactions .btn:disabled { opacity: 0.5; }
.xor { display: flex; align-items: center; gap: 8px; margin: 2px 0; }
.xor span { flex: 1; height: 1px; background: var(--line); }
.xor b { font-weight: 400; font-size: 15px; line-height: 20px; }
.xsmall { font-size: 11px; line-height: 14px; color: var(--muted); }
.xsmall a, .xfoot a:hover { color: var(--green-link); }
.xhave { font-size: 17px; line-height: 20px; font-weight: 700; margin: 34px 0 6px; }
.xerror, .xpending { width: 300px; margin-top: 16px; }
.xfoot { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 16px; padding: 12px 16px 16px; font-size: 13px; line-height: 16px; color: var(--muted); }
.xfoot a { color: var(--muted); text-decoration: none; }
/* The sign-in popup, in the app's own look: a sheet's surface, corners and green pill over the app's scrim, the soft
   green light behind the mark — not X's grey-blue backdrop and black pill. */
.xscrim { align-items: center; padding: 24px; background: var(--scrim); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.xdialog {
  width: 460px; max-width: 100%; max-height: min(640px, 90dvh); border-radius: 28px; color: var(--text);
  background: radial-gradient(circle 320px at 104% 0%, var(--soft-green), transparent), var(--surface);
  display: flex; flex-direction: column; overflow: auto; overscroll-behavior: contain; animation: pop 0.24s var(--ease);
  box-shadow: 0 24px 60px rgba(34, 34, 34, 0.28), inset 0 0 0 1px var(--line);
}
.xdhead { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; min-height: 64px; padding: 10px 14px 0; }
.xdhead > :first-child { justify-self: start; }
.xdbody { flex: 1; display: flex; flex-direction: column; gap: 12px; width: 100%; max-width: 380px; margin: 0 auto; padding: 8px 24px 28px; text-align: left; }
.xdtitle { font-size: 24px; line-height: 32px; font-weight: 700; margin: 12px 0 0; }
.xdialog .btn { height: 56px; font-size: 18px; line-height: 24px; font-weight: 500; }
.xgrow { flex: 1; min-height: 12px; }
.linkish { border: 0; background: none; padding: 6px 10px; border-radius: 999px; color: var(--green-link); font: inherit; font-size: 14px; line-height: 19px; font-weight: 500; }
.linkish:hover { background: var(--tab-pill); }
.btn.ink { background: var(--text); color: var(--frame); }
.btn.ink:disabled { background: var(--text); color: var(--frame); opacity: 0.5; }
@media (max-width: 1279px) { .xhero { font-size: 56px; line-height: 64px; } .xmark .mark { width: min(300px, 60%) !important; } }

/* ── Layout safety (2026-09-23 review): nothing clips, overlaps or hides, from 320 px to 1920 px ── */
/* A grid column never grows past its screen: long content wraps inside it instead of being cut. */
.stack, .stack-8, .stack-12, .fcard .inner { grid-template-columns: minmax(0, 1fr); }
/* Long unbroken text — addresses, card IDs, URLs, emails — wraps rather than running off the edge. */
h1, h2, h3, p, .t-hero, .t-title, .t-sheet, .t-body, .t-bodym, .t-label, .t-labelm, .t-caption { overflow-wrap: anywhere; }
.info .irow .v { white-space: normal; overflow-wrap: anywhere; }
/* A focused control is never left under the tab bar (or, on a desk, under the sticky top bar). */
html { scroll-padding-bottom: calc(var(--tab-bar-height) + env(safe-area-inset-bottom) + 16px); }
@media (min-width: 700px) { html { scroll-padding-top: 76px; scroll-padding-bottom: 16px; } }
/* Focus rings inside a rounded group are drawn inside it, where its clipping cannot hide them. */
.group .srow:focus-visible { outline-offset: -3px; }
/* Big text (200%): buttons and rows grow to hold their words instead of cutting them. */
.btn { white-space: normal; height: auto; min-height: 56px; padding-block: 8px; }
.srow { height: auto; min-height: 80px; }
/* Touch targets: 44 px at least. */
.tab { min-height: 44px; }
/* Landscape phones: the scanner's frame fits between the top and the prompt. */
.scanner .frame { width: min(72vw, 300px, 55svh); }
/* The floating Kota button never sits on the last thing on a tab screen. */
.app:has(.kota-launcher) .main:not(.page) { padding-bottom: calc(var(--tab-bar-height) + 100px + env(safe-area-inset-bottom)); }
/* A short desk window: the rail scrolls rather than squashing its items. */
@media (min-width: 700px) { .rail > * { flex: none; } .rail { overflow-y: auto; } }
/* Left and right safe areas (a landscape phone's notch). */
.gutter { padding-inline: max(var(--gutter), env(safe-area-inset-left)) max(var(--gutter), env(safe-area-inset-right)); }
.linkish { min-height: 44px; }

/* ── 2026-09-23 UI review, second pass ─────────────────── */
/* Focus: a solid 2 px ring in the dark green (4.5:1 on white; the light green in dark mode) on everything, fields
   included — their old ring was the brand green at 1.5 px, 1.5:1 on white, which nobody could see. */
:focus-visible { outline: 2px solid var(--green-link); outline-offset: 2px; }
.pill-input:focus { box-shadow: inset 0 0 0 2px var(--green-link); }
.pill-input.error:focus { box-shadow: inset 0 0 0 2px var(--coral); }
.page-layer[inert] { user-select: none; }
/* Touch targets: 44 px for the small ones too. */
.section-head .link { min-height: 44px; padding: 0 10px; margin-right: -10px; border-radius: 999px; }
.small-pill { min-height: 36px; }
/* Two buttons side by side only while both fit: at 200% text or a 320 px screen they stack. */
.btns { grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); }
/* Nothing on a narrow screen cuts a card's ID or a label: rows wrap their words instead of eliding them. */
.rowcard .body > * { white-space: normal; overflow-wrap: anywhere; }
.rowcard.card-row .body > .t-bodym { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; letter-spacing: 0.02em; }
.srow .label { white-space: normal; overflow-wrap: anywhere; min-width: 38%; }
.srow .value { text-align: right; max-width: 42%; }
.info .irow .k { flex: 0 1 auto; min-width: 34%; }
.info .irow .v { flex: 1 1 auto; }
.card-status { overflow-wrap: anywhere; }
@media (max-width: 360px) {
  .srow .value { white-space: normal; overflow-wrap: anywhere; }
  .srow { gap: 10px; padding: 0 12px; }
  .srow .medal { width: 36px; height: 36px; }
  .srow .medal svg { width: 20px; height: 20px; }
}
/* 200% text on a phone is a viewport under 240 px: the rows' icons step aside so their words keep the room. */
@media (max-width: 240px) {
  .srow .medal { display: none; }
  .srow .label { min-width: 55%; }
}
/* Gift tiles are links, not underlined text. */
a.tile { text-decoration: none; }
/* Onboarding: the dots that are not current are still visible on the light field. */
.onboard .dots i { background: color-mix(in srgb, var(--text) 22%, transparent); }
.onboard .dots i.on { background: var(--green); }
/* Landscape phone: the card on the left, the words and Next on the right — Next never below the fold. */
@media (orientation: landscape) and (max-height: 540px) {
  .onboard { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto auto auto auto 1fr; column-gap: 28px;
    align-content: center; max-width: 900px; min-height: 100svh; padding-top: max(12px, env(safe-area-inset-top)); padding-bottom: max(12px, env(safe-area-inset-bottom)); }
  .onboard > .skip, .onboard > span:first-child { grid-column: 2; grid-row: 1; height: 44px; margin-top: 0; justify-self: end; }
  .onboard .stage { grid-column: 1; grid-row: 1 / span 5; align-self: center; padding: 0 28px; }
  .onboard .stage > div { max-width: min(340px, 60svh * 1.58) !important; }
  .onboard h1, .onboard > p, .onboard .dots, .onboard > .btn { grid-column: 2; }
  .onboard .t-hero { font-size: 26px; line-height: 32px; }
  .onboard .dots { margin: 14px 0; }
  .onboard > .btn { align-self: start; }
}
/* Dark mode: the hero pills take the surface (they stayed pure white), and the glass circle — the Bell — stays visible. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pill-action { background: var(--surface); color: var(--text); }
  :root:not([data-theme="light"]) .circle.glass { background: rgba(255, 255, 255, 0.12); }
}
:root[data-theme="dark"] .pill-action { background: var(--surface); color: var(--text); }
:root[data-theme="dark"] .circle.glass { background: rgba(255, 255, 255, 0.12); }
/* The toast rises at the bottom, above the tab bar, not over the title; on a desk it sits under the content column. */
.toast { top: auto; bottom: calc(var(--tab-bar-height) + 16px + env(safe-area-inset-bottom)); animation: rise-toast 0.3s var(--ease); }
@keyframes rise-toast { from { transform: translate(-50%, 140%); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }
@media (min-width: 700px) {
  .toast { top: auto; bottom: 24px; left: calc(50% + var(--column-shift, 0px)); }
  html:has(.app .rail) { --column-shift: 44px; }             /* the 88 px rail on the left: the column is 44 px right of centre */
}
@media (min-width: 1100px) { html:has(.app .rail) { --column-shift: 130px; } }   /* the 260 px rail */
@media (min-width: 1300px) { html:has(.app .rail) { --column-shift: -45px; } }   /* ...and the 350 px sidebar on the right */


/* ── The launch: plans, credits, the wallet, a card set up from its bag, vouchers elsewhere, offline ─ */
.plan-card { display: grid; gap: 10px; border-radius: 24px; padding: 18px; background: var(--surface); text-align: left; }
.plan-card.current { box-shadow: inset 0 0 0 2px var(--green); }
.plan-card h3 { margin: 0; }
.plan-price { margin: 0; display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap; }
.plan-price s { margin-left: 6px; }
.perks { margin: 0; padding-left: 18px; display: grid; gap: 4px; color: var(--muted); }
.badge { display: inline-flex; align-items: center; border-radius: 999px; padding: 4px 10px; font-size: 12px; line-height: 16px; font-weight: 500;
  background: var(--medallion); color: var(--text); white-space: nowrap; }
.badge.promo { background: var(--coral); color: var(--ink); }
.load-row { display: flex; flex-wrap: wrap; gap: 8px; }
.entry { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.entry > :first-child { min-width: 0; overflow-wrap: anywhere; }
.chain-row { display: flex; align-items: center; gap: 12px; border-radius: 20px; padding: 14px 16px; background: var(--surface); }
.as-of { margin: 0; }
.legal a, .legal span { color: inherit; }
.setup-status { margin: 0; }
.setup-way { display: grid; gap: 10px; margin-top: 16px; padding-top: 14px; box-shadow: inset 0 1px 0 var(--divider); text-align: left; }
.where-choices .where-choice { text-align: left; width: 100%; }
.where-choice .body > * { white-space: normal; }
.medal.gift-art { overflow: hidden; padding: 0; position: relative; }
.medal.gift-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
/* A new version is ready (src/update.js): a small pill where the toast rises, left of Kota's launcher. It is part of the
   page, so a sheet, the loader or the scanner covers it; Reload runs only when it is tapped. */
.update-bar {
  position: fixed; left: var(--gutter); bottom: calc(var(--tab-bar-height) + 16px + env(safe-area-inset-bottom)); z-index: 40;
  display: flex; align-items: center; gap: 4px; max-width: calc(100% - 2 * var(--gutter) - 68px);
  background: var(--ink); color: #fff; border-radius: 999px; padding: 2px 2px 2px 16px;
  font-size: 14px; line-height: 19px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25); animation: fade 0.3s var(--ease);
}
.update-bar .linkish { color: var(--green); font-weight: 600; }
.update-bar .linkish:hover { background: rgba(255, 255, 255, 0.12); }
@media (min-width: 700px) {
  .update-bar { left: calc(50% + var(--column-shift, 0px)); bottom: 24px; transform: translateX(-50%); max-width: calc(100% - 32px); }
}
.offline-banner { margin: 10px var(--gutter) 0; border-radius: 16px; padding: 12px 14px; font-size: 14px; line-height: 19px;
  background: color-mix(in srgb, var(--yellow) 30%, var(--surface)); color: var(--text); }
/* Offline: what needs the network is dimmed, and says why when pressed (net.js). */
[data-offline] { opacity: 0.45; }
/* Swap & bridge: a mode of Home, switched at the top of both. */
.mode-toggle { margin-top: 12px; }
.mode-toggle .segmented { height: 48px; }
.voucher-badge { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--green) 55%, transparent); }
.entry.holding { width: 100%; border: 0; background: transparent; color: inherit; font: inherit; padding: 8px 4px; border-radius: 12px; cursor: pointer; text-align: left; }
.entry.holding:hover, .entry.holding:focus-visible { background: var(--medallion); }
.pill-input.pill-select, .panel .pill-input.pill-select { appearance: none; -webkit-appearance: none; padding-right: 44px; cursor: pointer; text-overflow: ellipsis;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 26px) 50%, calc(100% - 20px) 50%; background-size: 6px 6px, 6px 6px; background-repeat: no-repeat; }
.panel .pill-input.pill-select { background-color: var(--frame); }
/* The in-context plan choice (a card's set-up page, the plan-choice sheet): its plan cards sit on the frame colour inside
   the white panel or sheet, their white buttons back on white; a link to the full Plans page under them. */
.plan-choice .plan-card { background: var(--frame); padding: 14px 16px; gap: 8px; }
.plan-choice .plan-card .btn.white { background: var(--surface); }
.plan-choice .perks { color: var(--text); }
a.linkish { display: inline-flex; align-items: center; justify-self: start; text-decoration: none; }
/* After the first gift: the card is ready to give (green, like a voucher inside). */
.ready-to-give { background: linear-gradient(135deg, color-mix(in srgb, var(--green) 24%, var(--surface)), var(--surface) 70%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--green) 55%, transparent); }
/* ...and before that, its wait (card/setup.js): it opens for its recipient from a time. */
.setup-waiting { background: linear-gradient(135deg, color-mix(in srgb, var(--yellow) 22%, var(--surface)), var(--surface) 70%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--yellow) 55%, transparent); }
/* A chip read before set-up was asked for, on a card nobody has opened: the giver's way, before the call to scan. */
.setup-way.lead { margin: 0 0 16px; padding: 14px 16px; border-radius: 18px; box-shadow: none; text-align: left;
  background: color-mix(in srgb, var(--coral) 12%, var(--surface)); }


/* ── How it works (/how): the slides a bag's QR opens ──────────────────────────────────────────────────────────────
   Anyone's, on any phone. The page fits a phone's screen without scrolling where it can: the scene is sized from the
   screen's height, the words take what is left, and the controls sit at the foot. The scenes (src/ui/how.js) are inline
   SVG, and move by transform and opacity alone: each piece stands where it is drawn — the still frame — and `.moving`
   plays its keyframes over that. */
:root {
  --how-phone: #2b2e31; --how-screen: #ffffff; --how-row: #f2f7f6; --how-screen-ink: rgba(34, 34, 34, 0.16);
  --how-camera: #1d1f21; --how-line: rgba(34, 34, 34, 0.42); --how-shadow: rgba(34, 34, 34, 0.1);
  --how-card-edge: rgba(255, 255, 255, 0.1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --how-phone: #4a4d53; --how-screen: #2f3136; --how-row: #3a3d42; --how-screen-ink: rgba(255, 255, 255, 0.22);
    --how-camera: #141517; --how-line: rgba(255, 255, 255, 0.5); --how-shadow: rgba(0, 0, 0, 0.35);
    --how-card-edge: rgba(255, 255, 255, 0.26);
  }
}
:root[data-theme="dark"] {
  --how-phone: #4a4d53; --how-screen: #2f3136; --how-row: #3a3d42; --how-screen-ink: rgba(255, 255, 255, 0.22);
  --how-camera: #141517; --how-line: rgba(255, 255, 255, 0.5); --how-shadow: rgba(0, 0, 0, 0.35);
  --how-card-edge: rgba(255, 255, 255, 0.26);
}

.how-page { min-height: 100svh; }
.how {
  min-height: 100svh; max-width: 560px; margin: 0 auto; display: flex; flex-direction: column;
  padding: env(safe-area-inset-top) max(var(--gutter), env(safe-area-inset-right)) calc(14px + env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left));
}
.how-top { flex: none; display: flex; align-items: center; gap: 10px; height: 54px; margin-top: 6px; }
.how-h1 { flex: 1; min-width: 0; font-size: 16px; line-height: 22px; font-weight: 500; }
.how-skip { display: inline-flex; align-items: center; min-height: 44px; padding: 0 12px; margin-right: -12px; border-radius: 999px;
  color: var(--muted); font-size: 14px; line-height: 19px; font-weight: 500; text-decoration: none; }
button.how-skip { border: 0; background: none; font-family: inherit; cursor: pointer; }
.how-skip-space { width: 44px; }
/* The bag's two labels, as the bag prints them (retail_print.py bag_back, line art since 2026-09-25): capitals, spaced,
   bold, in the ink — "Giving it" outlined in green, the heavier line (the print's 1.6 to 1.2, green reading fainter);
   "Got one?" outlined in the ink. Nothing filled. The question's two answers, the way back to it on every slide, and the
   other answer at the end of each: buttons whose words carry their contrast, the focus ring kept clear of the outline. */
.how-label { text-transform: uppercase; letter-spacing: 0.14em; font-weight: 700; }
.how-choice, .how-path, .how-other { display: inline-flex; align-items: center; justify-content: center; gap: 6px; border: 0; border-radius: 999px;
  font-family: inherit; cursor: pointer; background: transparent; color: var(--text); }
.how-choice.green, .how-path.green, .how-other.green { box-shadow: inset 0 0 0 3px var(--green); }
.how-choice.ink, .how-path.ink, .how-other.ink { box-shadow: inset 0 0 0 2px var(--text); }
.how-choice:focus-visible, .how-path:focus-visible, .how-other:focus-visible { outline-offset: 3px; }
.how-choices { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.how-choice { min-height: 60px; padding: 0 12px; font-size: 16px; line-height: 20px; }
.how-path-row { flex: none; display: flex; }
.how-path { min-height: 44px; padding: 0 16px 0 10px; font-size: 12px; line-height: 16px; }
.how-path svg { width: 16px; height: 16px; }
.how-other { min-height: 44px; padding: 0 20px; font-size: 13px; line-height: 17px; }
.how-deck { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.how-slides { flex: 1; display: flex; flex-direction: column; min-height: 0; }
/* A slide comes in from the side it was asked for (none, the first time); a finger drags it, and it settles back. */
.how-slide { flex: 1; display: flex; flex-direction: column; min-height: 0; touch-action: pan-y;
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease); animation: how-in 0.3s var(--ease) backwards; }
.how-slide[data-dir="1"] { animation-name: how-in-next; }
.how-slide[data-dir="-1"] { animation-name: how-in-prev; }
@keyframes how-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes how-in-next { from { transform: translateX(28px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes how-in-prev { from { transform: translateX(-28px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
/* The scene takes what the header, the longest words and the controls leave of the screen: 640 px tall still fits. A
   path's slides give its label's row (the way back to the question) its height. */
.how-stage { flex: none; position: relative; height: clamp(170px, calc(100svh - 400px), 420px); }
.how-path-row + .how-deck .how-stage { height: clamp(150px, calc(100svh - 444px), 400px); }
/* The picture fits the stage whatever its shape: the SVG fills it, and its viewBox keeps the drawing whole and centred. */
.how-scene { position: absolute; inset: 0; }
.how-art { display: block; width: 100%; height: 100%; overflow: visible; }
.how-words { flex: 1; display: grid; align-content: start; justify-items: center; gap: 8px; text-align: center; padding-top: 8px; }
.how-title { font-size: 30px; line-height: 36px; font-weight: 500; max-width: 17ch; text-wrap: balance; }
.how-body { font-size: 16px; line-height: 22px; color: var(--muted); max-width: 34ch; text-wrap: balance; }
.how-note { max-width: 38ch; border-radius: 14px; padding: 7px 12px; background: var(--surface); color: var(--text);
  font-size: 13px; line-height: 17px; font-weight: 500; text-wrap: balance; }
.how-controls { flex: none; display: grid; gap: 8px; padding-top: 10px; margin-top: auto; }
.how-progress { display: flex; align-items: center; justify-content: space-between; }
.how-play { background: var(--surface); }
.how-play svg { width: 20px; height: 20px; }
.how-balance { width: 44px; flex: none; }
.how-dots { display: flex; align-items: center; }
.how-dot { width: 22px; height: 44px; padding: 0; border: 0; border-radius: 999px; background: none; display: grid; place-items: center; }
.how-dot[aria-current="true"] { width: 44px; }
.how-pip { position: relative; display: block; width: 8px; height: 8px; border-radius: 999px; overflow: hidden;
  background: color-mix(in srgb, var(--text) 22%, transparent); }
.how-dot[aria-current="true"] .how-pip { width: 32px; }
/* The current dot fills while its slide counts down to the next; paused, it is simply full. */
.how-fill { position: absolute; inset: 0; border-radius: inherit; background: var(--green); transform-origin: 0 50%; }
.how-fill.run { animation: how-fill 6s linear both; }
@keyframes how-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.how-buttons { display: flex; align-items: center; gap: 12px; }
.how-buttons .btn { flex: 1; width: auto; }
.how-prev:disabled { opacity: 0.35; }
.how-pair { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
@media (hover: hover) {
  .how-skip:hover { background: var(--tab-pill); color: var(--text); }
  .how-choice:hover, .how-path:hover, .how-other:hover { background: var(--tab-pill); }
  .how-dot:hover .how-pip { background: color-mix(in srgb, var(--text) 42%, transparent); }
  .how-dot[aria-current="true"]:hover .how-pip { background: color-mix(in srgb, var(--text) 22%, transparent); }
}
/* A landscape phone: the scene beside the words, and the controls in one row under both (the pair under the button). */
@media (orientation: landscape) and (max-height: 540px) {
  .how { max-width: 920px; }
  .how-top { height: 44px; margin-top: 4px; }
  .how-slide { flex-direction: row; align-items: center; gap: 24px; }
  .how-stage { flex: 1 1 50%; align-self: stretch; height: auto; min-height: 170px; }
  .how-words { flex: 1 1 50%; align-content: center; padding-top: 0; }
  .how-title { font-size: 26px; line-height: 32px; }
  .how-controls { grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 24px; padding-top: 6px; }
  .how-pair { grid-column: 2; }
}

/* The scenes' pieces, in both themes. */
.how-art .hw-face { fill: #222222; stroke: var(--how-card-edge); stroke-width: 1.5px; vector-effect: non-scaling-stroke; }
.how-art .hw-paper { fill: #f2f7f6; stroke: rgba(34, 34, 34, 0.14); stroke-width: 1.5px; vector-effect: non-scaling-stroke; }
.how-art .hw-phone { fill: var(--how-phone); }
.how-art .hw-screen { fill: var(--how-screen); }
.how-art .hw-row { fill: var(--how-row); }
.how-art .hw-sink { fill: var(--how-screen-ink); }
.how-art .hw-stext, .how-art .hw-text { fill: var(--text); }
.how-art .hw-sglyph { color: var(--text); }
.how-art .hw-camera { fill: var(--how-camera); }
.how-art .hw-kraft { fill: #c49a6c; }
.how-art .hw-seal { fill: #b1865a; }
.how-art .hw-shadow { fill: var(--how-shadow); }
.how-art .hw-line { stroke: var(--how-line); }
.how-art .hw-corner-white { stroke: #ffffff; }
.how-art .hw-corner-green { stroke: var(--green); }

/* How a piece moves: about its own middle, over its scene's loop, forever — while the scene moves. The question's scene
   is the exception: each of the bag's labels lights once, in turn, and then everything rests. */
.how-art .a { transform-box: fill-box; transform-origin: 50% 50%; }
.how-art .s4-give { transform-origin: 0% 50%; }
.how-art .s4-take { transform-origin: 100% 50%; }
.how-art .sr-strip { transform-origin: 100% 100%; }
.how-scene.moving .a { animation-duration: var(--loop, 4s); animation-timing-function: ease-in-out; animation-iteration-count: infinite; animation-fill-mode: both; }
.how-scene[data-scene="ask"].moving .a { animation-iteration-count: 1; }
.how-scene .move-only { opacity: 0; }
.how-scene.moving .still-only, .how-scene:not(.moving) .move-only { display: none; }
.how-scene[data-scene="ask"] { --loop: 3.2s; }
.how-scene[data-scene="scratch"] { --loop: 4.6s; }
.how-scene[data-scene="scan-it"] { --loop: 4.8s; }
.how-scene[data-scene="fill"] { --loop: 4.8s; }
.how-scene[data-scene="give"] { --loop: 4.2s; }
.how-scene[data-scene="tear"] { --loop: 4.4s; }
.how-scene[data-scene="hold"] { --loop: 3.6s; }
.how-scene[data-scene="scan-card"] { --loop: 4.8s; }

/* The question: the back of the bag, close up; "Giving it" lights, then "Got one?", once. */
.sq-hi1, .sq-hi2 { opacity: 0; }
.how-scene.moving .sq-give { animation-name: sq-give; }
@keyframes sq-give { 0%, 10% { transform: scale(1); } 22% { transform: scale(1.08); } 34%, 100% { transform: scale(1); } }
.how-scene.moving .sq-hi1 { animation-name: sq-hi1; }
@keyframes sq-hi1 { 0%, 8% { opacity: 0; } 20%, 30% { opacity: 1; } 42%, 100% { opacity: 0; } }
.how-scene.moving .sq-got { animation-name: sq-got; }
@keyframes sq-got { 0%, 46% { transform: scale(1); } 58% { transform: scale(1.08); } 70%, 100% { transform: scale(1); } }
.how-scene.moving .sq-hi2 { animation-name: sq-hi2; }
@keyframes sq-hi2 { 0%, 44% { opacity: 0; } 56%, 66% { opacity: 1; } 78%, 100% { opacity: 0; } }

/* Giving it: Scratch off the set-up code. A coin scratches the silver panel away, back and forth, and the code
   shows under it, framed in green once it is all there; the lock stays on its seal. At rest: the coin on the panel, the
   code showing through. */
.sx-hi { opacity: 0; }
.how-scene.moving .sx-coin { animation-name: sx-coin; }
@keyframes sx-coin {
  0% { transform: translate(40px, 30px); opacity: 0; }
  8% { transform: translate(4px, 2px); opacity: 1; }
  18% { transform: translate(-62px, -58px); opacity: 1; }
  28% { transform: translate(-8px, -44px); opacity: 1; }
  38% { transform: translate(-64px, -22px); opacity: 1; }
  48% { transform: translate(-6px, -12px); opacity: 1; }
  58% { transform: translate(-58px, 4px); opacity: 1; }
  66% { transform: translate(0px, 0px); opacity: 1; }
  72%, 100% { transform: translate(34px, 26px); opacity: 0; }
}
.how-scene.moving .sx-panel { animation-name: sx-panel; }
@keyframes sx-panel { 0%, 8% { opacity: 1; } 20% { opacity: 0.8; } 36% { opacity: 0.5; } 52% { opacity: 0.22; } 64%, 92% { opacity: 0; } 100% { opacity: 1; } }
.how-scene.moving .sx-hi { animation-name: sx-hi; }
@keyframes sx-hi { 0%, 64% { opacity: 0; } 70%, 86% { opacity: 1; } 92%, 100% { opacity: 0; } }
.how-scene.moving .sx-lock { animation-name: sx-lock; }
@keyframes sx-lock { 0%, 70% { transform: scale(1); } 76% { transform: scale(1.22); } 84%, 100% { transform: scale(1); } }

/* Giving it: Scan it — the set-up code, its panel scratched off. The phone scans it on the bag's back; the lock stays on
   its seal. */
.s2-cw, .s2-ready { opacity: 0; }
.how-scene.moving .s2-phone { animation-name: s2-phone; }
@keyframes s2-phone { 0% { transform: translate(26px, 0px); opacity: 0; } 10%, 92% { transform: translate(0px, 0px); opacity: 1; } 100% { transform: translate(0px, 0px); opacity: 0; } }
.how-scene.moving .s2-beam { animation-name: s2-beam; }
@keyframes s2-beam { 0%, 12% { opacity: 0; } 18%, 46% { opacity: 1; } 54%, 100% { opacity: 0; } }
.how-scene.moving .s2-scan { animation-name: s2-scan; }
@keyframes s2-scan {
  0%, 16% { transform: translate(0px, 0px); opacity: 0; }
  18% { transform: translate(0px, 0px); opacity: 1; animation-timing-function: linear; }
  44% { transform: translate(0px, 56px); opacity: 1; }
  46%, 100% { transform: translate(0px, 56px); opacity: 0; }
}
.how-scene.moving .s2-cw { animation-name: s2-cw; }
@keyframes s2-cw { 0%, 44% { opacity: 1; } 48%, 100% { opacity: 0; } }
.how-scene.moving .s2-cg { animation-name: s2-cg; }
@keyframes s2-cg { 0%, 44% { opacity: 0; } 48%, 100% { opacity: 1; } }
.how-scene.moving .s2-hi { animation-name: s2-hi; }
@keyframes s2-hi { 0%, 40% { opacity: 0; } 48%, 58% { opacity: 1; } 68%, 100% { opacity: 0; } }
.how-scene.moving .s2-cam { animation-name: s2-cam; }
@keyframes s2-cam { 0%, 54% { opacity: 1; } 60%, 100% { opacity: 0; } }
.how-scene.moving .s2-ready { animation-name: s2-ready; }
@keyframes s2-ready { 0%, 54% { opacity: 0; } 60%, 100% { opacity: 1; } }
.how-scene.moving .s2-check { animation-name: s2-check; }
@keyframes s2-check { 0%, 56% { transform: scale(0.4); } 64% { transform: scale(1.12); } 70%, 100% { transform: scale(1); } }
.how-scene.moving .s2-lock { animation-name: s2-lock; }
@keyframes s2-lock { 0%, 62% { transform: scale(1); } 68% { transform: scale(1.22); } 76%, 100% { transform: scale(1); } }

/* Giving it: Add gifts in the app. Two gifts and a voucher, one after another, along one arc into the card; it counts them. */
.s3-fly1 { transform: translate(-56px, -121px) scale(1); }
.s3-fly2 { transform: translate(-113px, -162px) scale(1); }
.s3-fly3 { transform: translate(-170px, -123px) scale(1); }
.s3-count { opacity: 0; }
.how-scene.moving .s3-fly1 { animation-name: s3-fly1; }
@keyframes s3-fly1 {
  0%, 4% { transform: translate(-231px, -39px) scale(0.4); opacity: 0; }
  7% { transform: translate(-231px, -39px) scale(1); opacity: 1; animation-timing-function: linear; }
  12% { transform: translate(-171px, -136px) scale(1); opacity: 1; animation-timing-function: linear; }
  17% { transform: translate(-113px, -162px) scale(1); opacity: 1; animation-timing-function: linear; }
  22% { transform: translate(-56px, -117px) scale(0.9); opacity: 1; animation-timing-function: linear; }
  27% { transform: translate(0px, 0px) scale(0.6); opacity: 1; }
  30%, 100% { transform: translate(0px, 0px) scale(0.2); opacity: 0; }
}
.how-scene.moving .s3-fly2 { animation-name: s3-fly2; }
@keyframes s3-fly2 {
  0%, 30% { transform: translate(-227px, -5px) scale(0.4); opacity: 0; }
  33% { transform: translate(-227px, -5px) scale(1); opacity: 1; animation-timing-function: linear; }
  38% { transform: translate(-170px, -123px) scale(1); opacity: 1; animation-timing-function: linear; }
  43% { transform: translate(-113px, -162px) scale(1); opacity: 1; animation-timing-function: linear; }
  48% { transform: translate(-56px, -121px) scale(0.9); opacity: 1; animation-timing-function: linear; }
  53% { transform: translate(0px, 0px) scale(0.6); opacity: 1; }
  56%, 100% { transform: translate(0px, 0px) scale(0.2); opacity: 0; }
}
.how-scene.moving .s3-fly3 { animation-name: s3-fly3; }
@keyframes s3-fly3 {
  0%, 56% { transform: translate(-224px, 29px) scale(0.4); opacity: 0; }
  59% { transform: translate(-224px, 29px) scale(1); opacity: 1; animation-timing-function: linear; }
  64% { transform: translate(-169px, -111px) scale(1); opacity: 1; animation-timing-function: linear; }
  69% { transform: translate(-113px, -162px) scale(1); opacity: 1; animation-timing-function: linear; }
  74% { transform: translate(-57px, -125px) scale(0.9); opacity: 1; animation-timing-function: linear; }
  79% { transform: translate(0px, 0px) scale(0.6); opacity: 1; }
  82%, 100% { transform: translate(0px, 0px) scale(0.2); opacity: 0; }
}
.how-scene.moving .s3-pulse { animation-name: s3-pulse; }
@keyframes s3-pulse {
  0%, 27% { transform: scale(0.7); opacity: 0; } 29% { transform: scale(0.75); opacity: 0.85; } 38% { transform: scale(1.4); opacity: 0; }
  53% { transform: scale(0.7); opacity: 0; } 55% { transform: scale(0.75); opacity: 0.85; } 64% { transform: scale(1.4); opacity: 0; }
  79% { transform: scale(0.7); opacity: 0; } 81% { transform: scale(0.75); opacity: 0.85; } 90%, 100% { transform: scale(1.4); opacity: 0; }
}
.how-scene.moving .s3-count { animation-name: s3-count; }
@keyframes s3-count {
  0%, 27% { transform: scale(0.5); opacity: 0; } 31% { transform: scale(1.12); opacity: 1; } 35%, 54% { transform: scale(1); opacity: 1; }
  57% { transform: scale(1.1); opacity: 1; } 61%, 80% { transform: scale(1); opacity: 1; } 83% { transform: scale(1.1); opacity: 1; }
  87%, 94% { transform: scale(1); opacity: 1; } 99%, 100% { transform: scale(1); opacity: 0; }
}
.how-scene.moving .s3-n1 { animation-name: s3-n1; }
@keyframes s3-n1 { 0%, 29% { opacity: 0; } 30%, 55% { opacity: 1; } 56%, 100% { opacity: 0; } }
.how-scene.moving .s3-n2 { animation-name: s3-n2; }
@keyframes s3-n2 { 0%, 55% { opacity: 0; } 56%, 81% { opacity: 1; } 82%, 100% { opacity: 0; } }
.how-scene.moving .s3-n3 { animation-name: s3-n3; }
@keyframes s3-n3 { 0%, 81% { opacity: 0; } 82%, 100% { opacity: 1; } }

/* Giving it: Give it, still sealed. One person holds the bag out, both hold it, the other takes it — its lock still on its seal. */
.s4-give { transform: rotate(5deg); }
.s4-take { transform: rotate(-5deg); }
.how-scene.moving .s4-bag { animation-name: s4-bag; }
@keyframes s4-bag {
  0% { transform: translate(-48px, 26px) rotate(-6deg); opacity: 0; }
  10% { transform: translate(-48px, 26px) rotate(-6deg); opacity: 1; }
  40%, 56% { transform: translate(0px, 0px) rotate(0deg); opacity: 1; }
  80%, 92% { transform: translate(48px, 26px) rotate(6deg); opacity: 1; }
  100% { transform: translate(48px, 26px) rotate(6deg); opacity: 0; }
}
.how-scene.moving .s4-give { animation-name: s4-give; }
@keyframes s4-give {
  0% { transform: rotate(19deg); opacity: 0; } 10% { transform: rotate(19deg); opacity: 1; }
  40%, 56% { transform: rotate(5deg); opacity: 1; } 72%, 100% { transform: rotate(16deg); opacity: 0; }
}
.how-scene.moving .s4-take { animation-name: s4-take; }
@keyframes s4-take {
  0%, 24% { transform: rotate(-25deg); opacity: 0; } 40%, 56% { transform: rotate(-5deg); opacity: 1; }
  80%, 92% { transform: rotate(-19deg); opacity: 1; } 100% { transform: rotate(-19deg); opacity: 0; }
}
.how-scene.moving .s4-heart { animation-name: s4-heart; }
@keyframes s4-heart {
  0%, 80% { transform: translate(0px, 6px) scale(0.3); opacity: 0; } 86% { transform: translate(0px, 0px) scale(1.15); opacity: 1; }
  90%, 94% { transform: translate(0px, -3px) scale(1); opacity: 1; } 100% { transform: translate(0px, -6px) scale(1); opacity: 0; }
}

/* Got one?: Tear open the bag. The top tears off along its dotted line, hinged at the far notch, and the card comes up
   out of the bag. At rest: the strip lifted and the card half out. */
.sr-strip { transform: translate(4px, -30px) rotate(12deg); }
.how-scene.moving .sr-strip { animation-name: sr-strip; }
@keyframes sr-strip {
  0% { transform: translate(0px, 0px) rotate(0deg); opacity: 0; }
  6%, 14% { transform: translate(0px, 0px) rotate(0deg); opacity: 1; }
  30% { transform: translate(4px, -30px) rotate(12deg); opacity: 1; }
  44% { transform: translate(14px, -46px) rotate(20deg); opacity: 0; }
  100% { transform: translate(14px, -46px) rotate(20deg); opacity: 0; }
}
.how-scene.moving .sr-card { animation-name: sr-card; }
@keyframes sr-card {
  0%, 36% { transform: translate(0px, 60px); opacity: 1; }
  64%, 90% { transform: translate(0px, 0px); opacity: 1; }
  100% { transform: translate(0px, 0px); opacity: 0; }
}

/* Got one?: Hold the card to your phone. The card comes to the top of the phone, its chip is read, a tick; it goes. */
.sh-t1 { opacity: 0; }
.how-scene.moving .sh-card { animation-name: sh-card; }
@keyframes sh-card {
  0%, 6% { transform: translate(-130px, 80px) rotate(-10deg); }
  28%, 64% { transform: translate(0px, 0px) rotate(0deg); }
  86%, 100% { transform: translate(-130px, 80px) rotate(-10deg); }
}
.how-scene.moving .sh-w { animation-name: sh-w; }
.how-scene.moving .sh-w2 { animation-delay: 0.12s; }
.how-scene.moving .sh-w3 { animation-delay: 0.24s; }
@keyframes sh-w { 0%, 28% { opacity: 0; } 32% { opacity: 1; } 38% { opacity: 0.2; } 44% { opacity: 1; } 50% { opacity: 0.2; } 56% { opacity: 1; } 62%, 100% { opacity: 0; } }
.how-scene.moving .sh-read { animation-name: sh-read; }
@keyframes sh-read { 0%, 36% { transform: scale(0.4); opacity: 0; } 42% { transform: scale(1.1); opacity: 1; } 48%, 76% { transform: scale(1); opacity: 1; } 84%, 100% { transform: scale(1); opacity: 0; } }
.how-scene.moving .sh-t1 { animation-name: sh-t1; }
@keyframes sh-t1 { 0%, 36% { opacity: 1; } 40%, 80% { opacity: 0; } 86%, 100% { opacity: 1; } }
.how-scene.moving .sh-t2 { animation-name: sh-t2; }
@keyframes sh-t2 { 0%, 36% { opacity: 0; } 40%, 80% { opacity: 1; } 86%, 100% { opacity: 0; } }

/* Got one?: Scan the code on the card. The camera finds the card's own code, then the gifts come up on the phone, yours.
   At rest: the gifts, the scan's beam still on the card. */
.sc-l2, .sc-cw, .sc-scan { opacity: 0; }
.how-scene.moving .sc-l2 { animation-name: sc-l2; }
@keyframes sc-l2 { 0%, 50% { opacity: 1; } 56%, 100% { opacity: 0; } }
.how-scene.moving .sc-l3 { animation-name: sc-l3; }
@keyframes sc-l3 { 0%, 50% { opacity: 0; } 56%, 96% { opacity: 1; } 100% { opacity: 0; } }
.how-scene.moving .sc-beam { animation-name: sc-beam; }
@keyframes sc-beam { 0%, 8% { opacity: 0; } 14%, 46% { opacity: 1; } 54%, 100% { opacity: 0; } }
.how-scene.moving .sc-scan { animation-name: sc-scan; }
@keyframes sc-scan {
  0%, 12% { transform: translate(0px, 0px); opacity: 0; }
  14% { transform: translate(0px, 0px); opacity: 1; animation-timing-function: linear; }
  42% { transform: translate(0px, 58px); opacity: 1; }
  44%, 100% { transform: translate(0px, 58px); opacity: 0; }
}
.how-scene.moving .sc-cw { animation-name: sc-cw; }
@keyframes sc-cw { 0%, 42% { opacity: 1; } 45%, 100% { opacity: 0; } }
.how-scene.moving .sc-cg { animation-name: sc-cg; }
@keyframes sc-cg { 0%, 42% { opacity: 0; } 45%, 100% { opacity: 1; } }
.how-scene.moving .sc-t1 { animation-name: sc-t1; }
@keyframes sc-t1 { 0%, 56% { transform: scale(0.4); opacity: 0; } 60% { transform: scale(1.1); opacity: 1; } 63%, 100% { transform: scale(1); opacity: 1; } }
.how-scene.moving .sc-t2 { animation-name: sc-t2; }
@keyframes sc-t2 { 0%, 60% { transform: scale(0.4); opacity: 0; } 64% { transform: scale(1.1); opacity: 1; } 67%, 100% { transform: scale(1); opacity: 1; } }
.how-scene.moving .sc-t3 { animation-name: sc-t3; }
@keyframes sc-t3 { 0%, 64% { transform: scale(0.4); opacity: 0; } 68% { transform: scale(1.1); opacity: 1; } 71%, 100% { transform: scale(1); opacity: 1; } }
.how-scene.moving .sc-yours { animation-name: sc-yours; }
@keyframes sc-yours { 0%, 70% { transform: scale(0.5); opacity: 0; } 75% { transform: scale(1.08); opacity: 1; } 78%, 100% { transform: scale(1); opacity: 1; } }

/* Less motion: the still frames, and nothing slides in, fills or drags. */
@media (prefers-reduced-motion: reduce) {
  .how-scene .a, .how-slide, .how-fill.run { animation: none !important; }
  .how-slide { transition: none; }
  .how-scene.moving .still-only { display: inline; }
  .how-scene .move-only { display: none; }
}
/* ── How it works: end ── */


/* ── Chains (/chains, /chains/<id>): the chain encyclopedia ─────────────────────────────────────────────────────────
   Reference pages anyone may read, signed out and offline: src/ui/chains.js draws them, src/content/chains.js holds the
   words. Every colour here is one of the kit's tokens, so light and dark are the tokens' own. A chain is shown by two
   letters in the kit's medallion, never by its logo. The table scrolls sideways inside its own box — never the page —
   with each chain's name held at its left edge. */
.chain-mono {
  width: 44px; height: 44px; border-radius: 999px; flex: none; display: inline-grid; place-items: center;
  background: var(--medallion); color: var(--text); font-size: 15px; line-height: 1; font-weight: 700; letter-spacing: 0.02em;
}
.chain-mono.large { width: 64px; height: 64px; font-size: 22px; }
.chain-mono.home { background: var(--green); color: var(--ink); }

/* Where a chain stands in Cryft Cards: Live in the kit's green, Coming soon in its yellow, Planned plain. */
.badge.chain-status.live { background: var(--green); color: var(--ink); }
.badge.chain-status.soon { background: color-mix(in srgb, var(--yellow) 38%, var(--surface)); color: var(--text); }
.badge.chain-status.planned { background: var(--medallion); color: var(--text); box-shadow: inset 0 0 0 1px var(--line); }
.chain-legend { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 16px; }
.chain-legend li { display: inline-flex; align-items: center; gap: 6px; }
.chain-card .chain-status { margin: 0 4px 0 8px; }

/* The comparison: a real table in a box of its own that scrolls sideways; the chain's name stays at the left. */
.chain-table-wrap { overflow-x: auto; overscroll-behavior-x: contain; border-radius: 24px; background: var(--surface); }
.chain-table { border-collapse: separate; border-spacing: 0; width: 100%; min-width: 820px; font-size: 14px; line-height: 19px; text-align: left; }
.chain-table caption { caption-side: top; text-align: left; padding: 16px 16px 8px; font-size: 16px; line-height: 22px; font-weight: 500; }
.chain-table th, .chain-table td { padding: 12px 14px; vertical-align: top; box-shadow: inset 0 1px 0 var(--divider); }
.chain-table thead th { box-shadow: none; font-size: 12px; line-height: 16px; font-weight: 500; color: var(--muted); white-space: nowrap; }
.chain-table th[scope="row"], .chain-table thead th:first-child { position: sticky; left: 0; z-index: 1; background: var(--surface); }
.chain-table th[scope="row"] { min-width: 120px; font-weight: 500; box-shadow: inset 0 1px 0 var(--divider), inset -1px 0 0 var(--line); }
.chain-table th[scope="row"] a { color: var(--green-link); text-decoration: none; }
.chain-table th[scope="row"] a:hover { text-decoration: underline; }
.chain-table td { min-width: 132px; }

/* One chain's page. */
.chain-hero { display: flex; align-items: center; gap: 14px; }
.chain-hero-words { display: grid; gap: 2px; }
.chain-points { list-style: none; margin: 0; padding: 4px 16px; border-radius: 24px; background: var(--surface); display: grid; }
.chain-points li { display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; font-size: 15px; line-height: 21px; }
.chain-points li + li { box-shadow: inset 0 1px 0 var(--divider); }
.chain-points li > span:last-child { min-width: 0; overflow-wrap: anywhere; }
.chain-sign { flex: none; width: 22px; height: 22px; border-radius: 999px; display: inline-grid; place-items: center; font-size: 15px; line-height: 1; font-weight: 700; }
.chain-points.pros .chain-sign { background: var(--green); color: var(--ink); }
.chain-points.cons .chain-sign { background: var(--coral); color: var(--ink); }
.chain-cryft { display: grid; gap: 10px; border-radius: 24px; padding: 16px; background: var(--surface); }
.chain-cryft-head { gap: 8px; }
.chain-cryft.live { background: linear-gradient(135deg, color-mix(in srgb, var(--green) 26%, var(--surface)), var(--surface) 70%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--green) 55%, transparent); }
.chain-cryft.soon { background: linear-gradient(135deg, color-mix(in srgb, var(--yellow) 22%, var(--surface)), var(--surface) 70%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--yellow) 55%, transparent); }
.chain-know { display: grid; gap: 12px; border-radius: 24px; padding: 16px; background: color-mix(in srgb, var(--yellow) 12%, var(--surface));
  box-shadow: inset 0 0 0 1px var(--line); }
.chain-know dl { margin: 0; display: grid; gap: 12px; }
.chain-know dl > div { display: grid; gap: 2px; }
.chain-know dt { font-size: 12px; line-height: 16px; font-weight: 500; color: var(--muted); }
.chain-know dd { margin: 0; font-size: 14px; line-height: 19px; overflow-wrap: anywhere; }
.chain-nav { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
.chain-step { display: grid; gap: 2px; align-content: center; min-height: 56px; border-radius: 20px; padding: 10px 16px;
  background: var(--surface); color: var(--text); text-decoration: none; }
.chain-step.next { text-align: right; }
.chain-step.none { background: transparent; }
a.linkish.chain-all { justify-self: center; }
.chain-foot { display: grid; gap: 2px; text-align: center; }

/* The small "i" beside a chain wherever one is picked: a 44 px target that takes no more room than the words beside it. */
.chain-named { display: inline-flex; align-items: center; gap: 2px; min-width: 0; }
.chain-info { display: inline-grid; place-items: center; flex: none; width: 44px; height: 44px; margin: -12px -10px -12px -4px;
  border-radius: 999px; color: var(--muted); text-decoration: none; }
.chain-info svg { width: 18px; height: 18px; }
.chain-info:hover { background: var(--tab-pill); color: var(--text); }
/* ── Chains: end ── */

/* ── The Market and the Trading Post (/market, /gallery/…; /trading-post) ─────────────────────────────────────────────
   The Market's galleries and the Trading Post's listings, each on "All networks" first: a switch between the two at the
   top (one tab on a phone's bar; a desk's rail names each, so there it goes), their networks in the header (the sweep,
   the section after this one), tiles two across (three where the column is wider) for listings, collections and items —
   each with its network's badge over the picture, a dot of its network's colour in it — an item's picture as wide as
   the column with its icon under it, and the rows of what the wallet and its cards hold (the Pocket's too). Every colour
   is one of the kit's tokens, or a network's own from src/networks.js (`--net`, on the tile), so dark mode follows the
   app. */
.markets-switch { margin-top: 0; }
@media (min-width: 1100px) { .markets-switch { display: none; } }
.tile .art.market-art, .tile .art.gallery-art { background: var(--medallion); overflow: hidden; }
.art.market-art img, .art.gallery-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.art .art-badges { position: absolute; top: 8px; left: 8px; right: 8px; display: flex; flex-wrap: wrap; gap: 4px; pointer-events: none; }
.badge.network { background: var(--surface); color: var(--text); padding: 2px 8px; box-shadow: 0 0 0 1px color-mix(in srgb, var(--net, var(--line)) 34%, var(--line)); gap: 5px; }
.badge.network::before { content: ''; width: 6px; height: 6px; border-radius: 999px; flex: none;
  background: linear-gradient(135deg, var(--net-a, var(--net, var(--muted))), var(--net-b, var(--net, var(--muted)))); }
.badge.test { background: var(--yellow); color: var(--ink); }
.partial-failed { gap: 10px; }
.market-tile .words > *, .gallery-tile .words > * { white-space: normal; overflow-wrap: anywhere; }
.market-tile .words .t-labelm { margin-top: 2px; }
.market-hero .art { aspect-ratio: 1; border-radius: 24px; display: grid; place-items: center; position: relative; overflow: hidden; background: var(--surface); }
.market-hero .art .medal { width: 76px; height: 76px; }
.gallery-hero { aspect-ratio: 1; border-radius: 24px; background: var(--surface); position: relative; overflow: hidden; display: grid; place-items: center; }
.gallery-hero img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
/* Bitcoin's and Litecoin's inscriptions: pixel art (a 24 × 24 punk, a 28 × 28 monkey) drawn crisp at every size, never
   smoothed into a blur — an inscription the service says is pixel art, and any gallery picture that came that small (a
   pixel-art collection's cover); an inscription the app doesn't draw (a page, a 3D model, text) shows its collection's
   cover, with a small note over its foot of where the inscription itself is shown — smaller on a 320 px phone, and on an
   item's page a link there, a finger's size; and its page's way out: "See it on …" a button on the medallion colour, so
   it reads as one on the white panel, the other sites in a row that wraps. */
.art.pixel img, .gallery-hero.pixel img, .medal.thumb.pixel img, img[data-crisp] { image-rendering: crisp-edges; image-rendering: pixelated; }
.art-note { position: absolute; left: 50%; bottom: 8px; transform: translateX(-50%); width: max-content; max-width: calc(100% - 16px);
  border-radius: 12px; background: var(--surface); color: var(--text); box-shadow: 0 0 0 1px var(--line); padding: 3px 8px;
  font-size: 12px; line-height: 16px; font-weight: 500; text-align: center; overflow-wrap: anywhere; pointer-events: none; }
@media (max-width: 359px) { .tile .art-note { bottom: 6px; max-width: calc(100% - 8px); padding: 2px 5px; font-size: 11px; line-height: 14px; } }
.gallery-hero .art-note { bottom: 12px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; border-radius: 999px;
  padding: 0 16px; font-size: 14px; line-height: 19px; pointer-events: auto; }
a.art-note { color: var(--green-link); text-decoration: underline; }
.panel.view-only .btn.white { background: var(--medallion); }
.link-outs { display: flex; flex-wrap: wrap; gap: 4px 8px; }
.medal.thumb { position: relative; overflow: hidden; }
.medal.thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.traits { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 140px), 1fr)); gap: 8px; }
.trait { border-radius: 16px; background: var(--surface); padding: 10px 12px; display: grid; gap: 2px; min-width: 0; }
.trait > * { overflow-wrap: anywhere; }
.held { border-radius: 20px; background: var(--surface); padding: 12px; display: grid; gap: 10px; min-width: 0; }
.held .t-bodym, .held .t-caption { overflow-wrap: anywhere; }
.held-acts { display: flex; flex-wrap: wrap; gap: 8px; }
.card-block .card-head { color: var(--text); text-decoration: none; }
.card-block .card-head .mono { letter-spacing: 0.02em; }
.price-range { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 130px), 1fr)); gap: 12px; }
.filters-toggle { justify-self: start; }
.lots { display: flex; align-items: center; justify-content: center; gap: 20px; }
.lots .circle { background: var(--frame); }
.market-steps { text-align: left; margin: 6px 0 0; padding-left: 20px; display: grid; gap: 4px; }
.attribution a { color: inherit; text-decoration: underline; }
.want .small-pill[aria-pressed="true"] { background: var(--green); color: var(--ink); }
@media (min-width: 560px) { .gallery-grid, .market-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* ── The Market and the Trading Post: end ── */

/* ── The network sweep (ui/sweep.js; src/sweep.js moves it) ───────────────────────────────────────────────────────────
   The Market's, the Trading Post's and the Pocket's networks, in the header in place of the page's title (Chad,
   2026-09-25): the active network's name alone, in a row of names that scrolls sideways inside itself and snaps one to
   the middle, so a swipe slides the next one in, softly at the edges; small chevrons either side (on a desk, buttons),
   and under the name a dot a network, the active one in its colour. Each network's colour is src/networks.js's, never
   this file's: `--net` (and `--net-a`, `--net-b` for a two-tone glow) on each name, dot and layer. The glow is a wash of
   the active network's colour at the top of the page, which the header's own glow joins on a desk (where the header is
   sticky and keeps it as the page scrolls under), and a soft glow behind the name. Every network's layers are drawn at
   once and shown by opacity alone — `--pos`, the place among the networks while something moves them (src/sweep.js),
   or else `--chosen`, the page's own — so a sweep lays nothing out and paints no filter, and the washes are layers of
   their own only while they move (`--net-wc`). The words keep the text colour on the glow. Less motion: nothing glides
   or fades; the name jumps and the glow changes at once. */
/* The wash reaches the very top: the top bar's margin stays inside the screen (flow-root), where it was drawn all along. */
.screen:has(.net-wash) { position: relative; display: flow-root; }
.net-bar .net-live { display: contents; }
.net-sweep { display: grid; grid-template-columns: 28px minmax(0, 1fr) 28px; align-items: center; width: calc(100% - 112px); max-width: 320px; }
.net-view { min-width: 0; display: grid; justify-items: center; gap: 2px; }
.net-track { position: relative; isolation: isolate; width: 100%; display: flex; overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain;
  scroll-snap-type: var(--snap, x mandatory); padding-block: 2px;
  -webkit-mask-image: linear-gradient(90deg, transparent, black 8px, black calc(100% - 8px), transparent); mask-image: linear-gradient(90deg, transparent, black 8px, black calc(100% - 8px), transparent); }
.net-track::-webkit-scrollbar { display: none; }
.net-name { position: relative; flex: 0 0 100%; min-width: 0; height: 36px; padding: 0 8px; border: 0; background: none; color: var(--text); cursor: pointer;
  font-size: 18px; line-height: 36px; font-weight: 500; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  scroll-snap-align: center; scroll-snap-stop: always; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.net-name::after { content: ''; position: absolute; inset: 0 14%; z-index: -1; pointer-events: none;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--net) var(--net-halo), transparent), transparent);
  opacity: max(0, calc(1 - max(var(--pos, var(--chosen)) - var(--i), var(--i) - var(--pos, var(--chosen)))));
  transition: opacity var(--net-t, 0.45s) var(--ease); }
.net-dots { display: flex; align-items: center; gap: 5px; height: 6px; }
.net-dots > i { position: relative; width: 5px; height: 5px; border-radius: 999px; background: color-mix(in srgb, var(--text) 24%, transparent); }
.net-dots > i::after { content: ''; position: absolute; inset: 0; border-radius: inherit; background: linear-gradient(135deg, var(--net-a, var(--net)), var(--net-b, var(--net)));
  opacity: max(0, calc(1 - max(var(--pos, var(--chosen)) - var(--i), var(--i) - var(--pos, var(--chosen)))));
  transform: scale(calc(1 + 0.5 * max(0, calc(1 - max(var(--pos, var(--chosen)) - var(--i), var(--i) - var(--pos, var(--chosen)))))));
  transition: opacity var(--net-t, 0.45s) var(--ease), transform var(--net-t, 0.45s) var(--ease); }
.net-step { display: inline-grid; place-items: center; width: 28px; height: 40px; padding: 0; border: 0; border-radius: 999px; background: none; color: var(--muted); }
.net-step.next svg { transform: scaleX(-1); }
.net-step:disabled { opacity: 0.3; cursor: default; }
@media (hover: hover) { .net-step:not(:disabled):hover { color: var(--text); } }
/* The glows: the page's wash, and the header's own; each network a layer, its two colours left and right. */
.net-wash { position: absolute; inset: 0 0 auto; height: 400px; z-index: -1; pointer-events: none; overflow: hidden; }
.net-wash > .net-live { position: absolute; inset: 0; will-change: var(--net-wc, auto); }
.net-glow > i { position: absolute; left: 0; right: 0; top: 0; height: 400px;
  background:
    radial-gradient(62% 78% at 14% 0%, color-mix(in srgb, var(--net-a, var(--net)) var(--net-wash), transparent), transparent),
    radial-gradient(62% 78% at 86% 0%, color-mix(in srgb, var(--net-b, var(--net)) var(--net-wash), transparent), transparent);
  opacity: max(0, calc(1 - max(var(--pos, var(--chosen)) - var(--i), var(--i) - var(--pos, var(--chosen)))));
  transition: opacity var(--net-t, 0.6s) var(--ease); }
.net-bar-glow { display: none; }
.net-hint { justify-self: center; display: inline-flex; align-items: center; gap: 2px; padding: 2px 2px 2px 14px; border-radius: 999px; max-width: 100%;
  background: var(--surface); color: var(--muted); font-size: 13px; line-height: 18px; box-shadow: var(--float-shadow); }
.net-hint-close { flex: none; display: inline-grid; place-items: center; width: 32px; height: 32px; border: 0; border-radius: 999px; background: transparent; color: var(--muted); }
/* The list of them all (a sheet): each network a row, its colour a dot, the one shown ringed and ticked. */
.sheet .net-pick::before { content: ''; flex: none; width: 12px; height: 12px; margin: 0 4px 0 6px; border-radius: 999px;
  background: linear-gradient(135deg, var(--net-a, var(--net)), var(--net) 50%, var(--net-b, var(--net))); }
.sheet .net-pick { box-shadow: inset 0 0 0 1px var(--line); }
.sheet .rowcard.pick.net-pick.selected { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--net) var(--net-ring), transparent); }
.net-pick-on { flex: none; color: var(--text); }
/* The narrowest phones: the name a little more room and two points smaller, so "All networks" fits whole at 320 px, clear
   of the row's 8 px fade, between the 54 px back button and the page's action; the chevrons still 24 px. */
@media (max-width: 359px) {
  .net-sweep { grid-template-columns: 24px minmax(0, 1fr) 24px; }
  .net-step { width: 24px; }
  .net-name { padding: 0 4px; font-size: 16px; }
}
/* A desk: the header is sticky, and keeps its own glow as the page scrolls under it; the chevrons are buttons. */
@media (min-width: 700px) {
  .net-bar-glow { display: block; position: absolute; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; will-change: var(--net-wc, auto); }
  .net-sweep { grid-template-columns: 36px minmax(0, 1fr) 36px; gap: 6px; }
  .net-step { width: 36px; height: 36px; background: var(--surface); color: var(--text); }
}
@media (prefers-reduced-motion: reduce) {
  .net-name::after, .net-dots > i::after, .net-glow > i { transition: none; }
}
/* ── The network sweep: end ── */

/* ── The Pocket (/pocket, /pocket/wallet) ─────────────────────────────────────────────────────────────────────────────
   Everything a member has, in two halves under one switch that stays on a desk too (the rail names the Pocket once): its
   cards, and what its wallet holds, drawn as the Dakota account's things are (.held, from the Market's section above) —
   an NFT's row a link to its item, its picture beside it, and each thing's network as a badge by its name. In the kit's
   tokens alone, so dark mode follows the app, and nothing wider than a phone: the chips scroll inside themselves. */
.pocket-switch { margin-top: 0; }
.held-link { color: var(--text); text-decoration: none; min-width: 0; }
.held-link:active { transform: scale(0.992); }
.held .held-name .badge { vertical-align: 1px; }
/* A voucher made into a card: its sheets set what they are about, and what is open yet, on the medallion colour, and
   each choice (a test asset, where it goes) with a hairline, green once chosen. */
.sheet .voucher-item, .sheet .voucher-soon, .sheet .voucher-dev { background: var(--medallion); }
.sheet .rowcard.pick { box-shadow: inset 0 0 0 1px var(--line); }
.sheet .rowcard.pick.selected { box-shadow: inset 0 0 0 1.5px var(--green); }
.sheet .t-sheet .badge { vertical-align: 3px; }
/* ── The Pocket: end ── */
/* Vendor profile and totals: the same readable layout on phone and desktop. */
.vendor-details { display: grid; gap: 12px; }
.vendor-registration { border: 1px solid var(--muted); border-radius: 16px; padding: 14px; }
.vendor-registration summary { cursor: pointer; font-size: 14px; font-weight: 500; }
.vendor-registration-item { margin-top: 14px; overflow-wrap: anywhere; }
.vendor-stat-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.vendor-stat { display: flex; flex-direction: column; gap: 6px; padding: 16px; border-radius: 16px; background: var(--frame); border: 1px solid var(--muted); }
.vendor-stat strong { font-size: 24px; overflow-wrap: anywhere; }
.vendor-stat span { font-size: 12px; color: var(--muted); }
.vendor-details .irow .v { overflow-wrap: anywhere; min-width: 0; }

/* Website invitation stays in document flow and never covers a card or confirmation. */
.install-notice { position: relative; margin: 8px auto; max-width: 640px; padding: 12px 52px 12px 16px; background: var(--surface, #eff6ed); color: var(--text, #182619); border: 1px solid var(--line, #cad5c7); border-radius: 14px; font-size: 14px; }
.install-notice summary { cursor: pointer; font-weight: 600; min-height: 24px; }
.install-notice p { margin: 12px 0; line-height: 1.5; }
.install-notice button, .install-notice a { display: inline-flex; padding: 10px 12px; min-height: 44px; align-items: center; border-radius: 10px; font: inherit; color: inherit; }
.install-notice .install-notice-dismiss { position: absolute; right: 4px; top: 2px; width: 44px; justify-content: center; font-size: 24px; background: transparent; border: 0; }
@media (max-width: 680px) { .install-notice { margin: 8px 12px; } }

.install-notice details button { background: var(--green); color: var(--ink); border: 0; font-weight: 500; }
.install-notice details a { color: var(--green-link); }

/* Public vendor bag instructions: the app's Satoshi, surfaces and card face, with room to read on a desk. */
.vendor-guide-page { min-height: 100svh; padding: env(safe-area-inset-top) max(20px, env(safe-area-inset-right)) calc(32px + env(safe-area-inset-bottom)) max(20px, env(safe-area-inset-left)); }
.vendor-guide { max-width: 1040px; margin-inline: auto; }
.vendor-guide-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding-block: 16px; }
.vendor-guide-brand { display: inline-flex; align-items: center; gap: 10px; color: var(--text); font-weight: 700; text-decoration: none; }
.vendor-guide-app { display: inline-flex; align-items: center; gap: 4px; min-height: 44px; padding: 8px 0 8px 8px; font-size: 14px; font-weight: 500; text-decoration: none; }
.guide-browse { display: flex; flex-wrap: wrap; gap: 8px; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
.guide-browse a { display: inline-flex; align-items: center; min-height: 44px; padding: 8px 14px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); color: var(--text); text-decoration: none; font-size: 14px; font-weight: 500; }
.guide-browse a:hover { background: var(--tab-pill); }
.vendor-guide main { display: grid; gap: 40px; }
.vendor-guide-hero { display: grid; align-items: center; gap: 30px; padding-block: 24px 0; }
.vendor-guide-intro { display: grid; gap: 16px; }
.vendor-guide-eyebrow { color: var(--green-link); font-size: 11px; font-weight: 700; line-height: 16px; letter-spacing: 0.13em; }
.vendor-guide h1 { max-width: 9em; font-size: clamp(38px, 6vw, 58px); font-weight: 500; line-height: 1.07; letter-spacing: -0.04em; }
.vendor-guide p { line-height: 1.6; }
.vendor-guide-lead { font-size: 20px; font-weight: 500; line-height: 1.4 !important; }
.vendor-guide-intro > p:not(.vendor-guide-eyebrow):not(.vendor-guide-lead), .vendor-guide-section-head > p:not(.vendor-guide-eyebrow) { color: var(--muted); }
.vendor-guide-actions { display: flex; flex-wrap: wrap; gap: 12px; }
.vendor-guide-actions .btn { width: auto; min-width: 220px; max-width: 100%; padding-inline: 24px; }
.vendor-guide-note { color: var(--muted); font-size: 13px; }
.vendor-guide-card { width: 100%; max-width: 460px; justify-self: center; }
.vendor-guide-card .vendor-face, .vendor-guide-card .vendor-foil { animation: none; }
.vendor-guide-card .vendor-foil { display: none; }
.vendor-guide-app svg, .how-vendor-guide svg { transform: rotate(180deg); }
.vendor-guide-section-head { display: grid; gap: 9px; }
.vendor-guide h2 { font-size: 28px; line-height: 1.2; font-weight: 500; letter-spacing: -0.025em; }
.vendor-guide h3 { font-size: 18px; line-height: 1.4; font-weight: 700; }
.vendor-guide-codes { display: grid; gap: 20px; padding: 24px; background: var(--surface); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--float-shadow); }
.vendor-guide-code-grid { display: grid; gap: 24px; }
.vendor-guide-code { display: grid; align-content: start; gap: 10px; min-width: 0; }
.vendor-guide-code p { color: var(--muted); font-size: 14px; }
.vendor-guide-icon { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 14px; background: var(--green); color: var(--ink); }
.vendor-guide-icon.private { background: var(--medallion); color: var(--text); }
.vendor-guide-setup { display: grid; gap: 24px; }
.vendor-guide-steps { display: grid; gap: 12px; padding: 0; margin: 0; list-style: none; }
.vendor-guide-step { display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 16px; padding: 24px 20px; border-radius: 20px; background: var(--surface); border: 1px solid var(--line); }
.vendor-guide-number { width: 40px; height: 40px; display: grid; place-items: center; border: 1px solid var(--green-link); color: var(--green-link); border-radius: 50%; font-size: 14px; font-weight: 700; }
.vendor-guide-step > div { display: grid; gap: 10px; }
.vendor-guide-step p { font-size: 15px; }
.vendor-guide-step .vendor-guide-note { font-size: 13px; }
.vendor-guide-availability { display: grid; grid-template-columns: 44px minmax(0, 1fr); gap: 16px; padding: 24px; border-radius: 24px; border: 1px solid var(--green-link); }
.vendor-guide-availability > div { display: grid; gap: 12px; }
.vendor-guide-availability h2 { font-size: 22px; }
.vendor-guide-availability p { font-size: 14px; }
.vendor-guide-faq { display: grid; }
.vendor-guide-faq .vendor-guide-section-head { margin-bottom: 16px; }
.vendor-guide-faq details { border-bottom: 1px solid var(--line); }
.vendor-guide-faq summary { padding: 20px 4px; min-height: 56px; cursor: pointer; font-weight: 500; }
.vendor-guide-faq details > div { display: grid; gap: 12px; padding: 0 4px 24px; color: var(--muted); font-size: 14px; max-width: 76ch; }
.vendor-guide-footer { display: grid; gap: 24px; padding: 28px 24px; background: var(--surface); border-radius: 24px; border: 1px solid var(--line); }
.vendor-guide-footer > div:first-child { display: grid; gap: 8px; }
.vendor-guide-footer p { color: var(--muted); }
.vendor-guide-recipient { display: inline-flex; align-items: center; gap: 8px; width: fit-content; min-height: 44px; font-size: 14px; }
.vendor-guide-recipient svg { transform: rotate(180deg); }
.how-vendor-guide { display: flex; justify-content: center; align-items: center; gap: 4px; min-height: 44px; font-size: 13px; line-height: 18px; text-align: center; text-decoration: none; }
@media (min-width: 740px) {
  .vendor-guide-page { padding-inline: max(40px, env(safe-area-inset-left)); }
  .vendor-guide main { gap: 56px; }
  .vendor-guide-top { padding-block: 24px; }
  .vendor-guide-hero { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 48px; padding-block: 36px 8px; }
  .vendor-guide-code-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 36px; }
  .vendor-guide-codes, .vendor-guide-footer { padding: 32px; }
  .vendor-guide-step { grid-template-columns: 48px minmax(0, 1fr); padding: 28px 32px; gap: 24px; }
  .vendor-guide-step > div { max-width: 76ch; }
}
@media (max-width: 380px) {
  .vendor-guide-brand { font-size: 14px; }
  .vendor-guide-top { gap: 8px; }
  .vendor-guide-codes, .vendor-guide-step, .vendor-guide-availability, .vendor-guide-footer { padding: 20px 16px; }
  .vendor-guide-step { grid-template-columns: 32px minmax(0, 1fr); gap: 12px; }
  .vendor-guide-number { width: 32px; height: 32px; font-size: 12px; }
  .vendor-guide-availability { grid-template-columns: minmax(0, 1fr); }
  .vendor-guide-actions .btn { width: 100%; min-width: 0; }
}
