/* SquadBite site stylesheet — 1.2.1 */
/* SquadBite — site styles.
   Palette and type are lifted directly from the app's design_guidelines.json /
   src/theme/tokens.ts so the site and the product read as one thing. Do not
   introduce blues or purples; the app's tokens deliberately exclude them. */

:root {
  --surface: #FCFBF8;
  --surface-2: #FFFFFF;
  --surface-3: #F5F5F4;
  --ink: #1C1917;
  --ink-2: #292524;
  --ink-3: #44403C;
  --muted: #78716C;
  --brand: #E07A5F;
  --brand-deep: #994D35;
  --brand-tint: #FDF5ED;
  --honey: #F2CC8F;
  --sage: #81B29A;
  --warning: #E29578;
  --border: #E7E5E4;
  --border-strong: #D6D3D1;

  --radius-sm: 6px;
  --radius-md: 12px;
  --radius-lg: 20px;
  --radius-pill: 999px;

  --shadow-card: 0 4px 12px rgba(28, 25, 23, 0.06);
  --shadow-lift: 0 10px 30px rgba(28, 25, 23, 0.09);

  /* These four cannot be derived by inverting a palette entry, so they are
     their own tokens. --btn-* in particular: the App Store button used
     var(--ink) as its fill, which in dark mode is near-white — white text on a
     white pill. */
  --btn-bg: #1C1917;
  --btn-fg: #FFFFFF;
  --header-bg: rgba(252, 251, 248, 0.82);
  --icon-stroke: #994D35;

  color-scheme: light;

  --display: "Lora", Georgia, "Times New Roman", serif;
  --body: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;

  --page: 1080px;
  --gutter: 24px;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img, svg { max-width: 100%; }

a { color: var(--brand-deep); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--brand); }

/* Visible keyboard focus everywhere — the default outline disappears against
   the cream surface, so it is redrawn rather than removed. */
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

.wrap {
  width: 100%;
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--surface);
  padding: 10px 16px;
  border-radius: 0 0 var(--radius-md) 0;
  z-index: 100;
}
.skip:focus { left: 0; color: var(--surface); }

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--header-bg);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--border);
}

.site-header .inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: 64px;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--display);
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
}
.wordmark:hover { color: var(--ink); }

.mark {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: var(--brand);
  display: grid;
  place-items: center;
  flex: none;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 22px;
  font-size: 15px;
}
.site-nav a {
  color: var(--ink-3);
  text-decoration: none;
  font-weight: 500;
}
.site-nav a:hover { color: var(--brand-deep); }

/* ---------- shared section furniture ---------- */

.band { padding: 88px 0; }
.band-tint { background: var(--brand-tint); border-block: 1px solid var(--border); }
.band-quiet { background: var(--surface-3); border-block: 1px solid var(--border); }

/* The eyebrow labels what the section IS, so it stays a small-caps utility
   line rather than decoration. */
.eyebrow {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand-deep);
  margin: 0 0 14px;
}

h1, h2, h3 { font-family: var(--display); font-weight: 600; letter-spacing: -0.02em; color: var(--ink); }

h1 {
  font-size: clamp(2.4rem, 6.2vw, 3.9rem);
  line-height: 1.08;
  margin: 0 0 20px;
}

h2 {
  font-size: clamp(1.75rem, 3.6vw, 2.5rem);
  line-height: 1.18;
  margin: 0 0 16px;
}

h3 {
  font-size: 1.16rem;
  line-height: 1.35;
  margin: 0 0 8px;
}

.lede {
  font-size: clamp(1.05rem, 2.1vw, 1.2rem);
  color: var(--ink-3);
  max-width: 60ch;
  margin: 0 0 32px;
}

.section-intro { max-width: 62ch; margin-bottom: 44px; }
.section-intro p { color: var(--ink-3); margin: 0; }

/* ---------- hero ---------- */

.hero { padding: 76px 0 84px; }

/* Single centred column, following helmarr.com. The pills and the store
   button were the parts asked to be centred; centring only those under a
   left-aligned headline reads as a mistake rather than a choice, so the whole
   hero centres and the rings move below it. */
.hero .inner { display: block; text-align: center; }

.hero-copy { max-width: 720px; margin: 0 auto; }

.hero .lede { margin-left: auto; margin-right: auto; }

.platform-tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 0 0 28px;
  padding: 0;
  list-style: none;
}
.platform-tags li {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 5px 13px;
}

/* ---------- App Store button ---------- */

.store-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 14px;
}

.appstore {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  text-decoration: none;
  padding: 12px 22px;
  border-radius: var(--radius-md);
  border: 1px solid var(--btn-bg);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.appstore:hover { color: var(--btn-fg); transform: translateY(-1px); box-shadow: var(--shadow-lift); }
.appstore svg { flex: none; }
.appstore .apple { fill: var(--btn-fg); }
.appstore .stack { display: flex; flex-direction: column; line-height: 1.1; text-align: left; }
.appstore .small { font-size: 11px; opacity: 0.82; letter-spacing: 0.02em; }
.appstore .big { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }

/* Pre-launch state. Same footprint as the live badge so nothing shifts when
   the real link goes in. */
.appstore[aria-disabled="true"] {
  background: var(--surface-2);
  color: var(--ink-3);
  border-color: var(--border-strong);
  cursor: default;
}
.appstore[aria-disabled="true"]:hover { transform: none; box-shadow: none; color: var(--ink-3); }
.appstore[aria-disabled="true"] .apple { fill: var(--ink-3); }

.store-note { font-size: 14px; color: var(--muted); margin: 16px 0 0; }

/* ---------- macro ring (the signature element) ---------- */

.rings { display: grid; place-items: center; margin-top: 52px; }

.rings figure {
  margin: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 30px 28px 24px;
  width: 100%;
  max-width: 340px;
}

.rings svg { display: block; margin: 0 auto; }

/* Stroke 14 with radii 20 apart leaves the app's 6px gap between rings —
   MacroRings.tsx uses stroke 14, gap 6 and steps its radius by the sum. */
.ring-track { fill: none; stroke: var(--surface-3); stroke-width: 14; }

/* Four states on a 12s loop — a day filling up, roughly 2.4s held and 0.6s
   moving. One shared @keyframes block drives every ring: the per-ring values
   live in --s1..--s4 as inline custom properties, so adding a ring or retuning
   a state never means touching the keyframes. That held when the calorie ring
   was dropped for v85 — three rings animate through the same four states with
   no change here, which is what the indirection was for. */
.ring-value {
  fill: none;
  stroke-width: 14;
  stroke-linecap: round;
  transform: rotate(-90deg);
  transform-origin: 120px 120px;
  stroke-dasharray: var(--circ);
  stroke-dashoffset: var(--s1);
  animation: ring-cycle 12s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

@keyframes ring-cycle {
  0%, 20%  { stroke-dashoffset: var(--s1); }
  25%, 45% { stroke-dashoffset: var(--s2); }
  50%, 70% { stroke-dashoffset: var(--s3); }
  75%, 95% { stroke-dashoffset: var(--s4); }
  100%     { stroke-dashoffset: var(--s1); }
}

/* The centre readout crossfades on the same clock. Four <text> elements
   stacked at one position — SVG has no text node a CSS animation can rewrite,
   so opacity is the only way to do this without JavaScript. */
.ring-num { opacity: 0; animation: 12s linear infinite; }
.ring-num.n1 { opacity: 1; animation-name: num-1; }
.ring-num.n2 { animation-name: num-2; }
.ring-num.n3 { animation-name: num-3; }
.ring-num.n4 { animation-name: num-4; }

@keyframes num-1 { 0%, 20% { opacity: 1 } 25%, 95% { opacity: 0 } 100% { opacity: 1 } }
@keyframes num-2 { 0%, 20% { opacity: 0 } 25%, 45% { opacity: 1 } 50%, 100% { opacity: 0 } }
@keyframes num-3 { 0%, 45% { opacity: 0 } 50%, 70% { opacity: 1 } 75%, 100% { opacity: 0 } }
@keyframes num-4 { 0%, 70% { opacity: 0 } 75%, 95% { opacity: 1 } 100% { opacity: 0 } }

.ring-center { text-anchor: middle; font-family: var(--display); }
.ring-center .num { font-size: 33px; font-weight: 600; fill: var(--ink); }
.ring-center .lbl { font-size: 12px; font-family: var(--body); font-weight: 600; fill: var(--muted); letter-spacing: 0.08em; }

.ring-key {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  font-size: 13px;
  color: var(--ink-3);
}
.ring-key li { display: inline-flex; align-items: center; gap: 7px; }
.ring-key b { font-weight: 600; color: var(--ink-2); }
.ring-key i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--dot);
  display: inline-block;
}

.rings figcaption {
  margin-top: 16px;
  text-align: center;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
}

/* ---------- feature grid ---------- */

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 22px;
}

.card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 26px 24px;
  box-shadow: var(--shadow-card);
}

.card .icon {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  background: var(--brand-tint);
  display: grid;
  place-items: center;
  margin-bottom: 16px;
}

.card .icon svg { stroke: var(--icon-stroke); }

.card p { margin: 0; color: var(--ink-3); font-size: 15.5px; }

/* ---------- plans ---------- */

.plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 22px;
  align-items: start;
}

.plan {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 28px 26px;
  box-shadow: var(--shadow-card);
}
.plan.featured { border-color: var(--brand); box-shadow: var(--shadow-lift); }

.plan .price {
  font-family: var(--display);
  font-size: 2rem;
  font-weight: 600;
  color: var(--ink);
  margin: 4px 0 2px;
}
.plan .price small { font-family: var(--body); font-size: 0.92rem; font-weight: 500; color: var(--muted); }
.plan .price-alt { font-size: 14px; color: var(--muted); margin: 0 0 20px; }

.plan ul { list-style: none; margin: 0; padding: 0; }
.plan li {
  position: relative;
  padding-left: 27px;
  margin-bottom: 11px;
  font-size: 15.5px;
  color: var(--ink-3);
}
.plan li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 8px;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--sage);
  border-bottom: 2px solid var(--sage);
  transform: rotate(-45deg);
}

.plan-note {
  margin: 34px 0 0;
  font-size: 14px;
  color: var(--muted);
  max-width: 68ch;
}

/* ---------- note band (stands in for reviews until real ones exist) ---------- */

.note-band { max-width: 720px; margin: 0 auto; text-align: center; }
.note-band blockquote {
  margin: 0 0 20px;
  font-family: var(--display);
  font-size: clamp(1.3rem, 2.8vw, 1.75rem);
  line-height: 1.42;
  color: var(--ink);
}
.note-band .attrib { font-size: 14.5px; color: var(--muted); margin: 0; }

/* ---------- reviews (kept ready; see index.html) ---------- */

.rating-line {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 40px;
  font-size: 15px;
  color: var(--ink-3);
}
.stars { color: var(--brand); letter-spacing: 2px; font-size: 18px; }

.review {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 24px;
  box-shadow: var(--shadow-card);
}
.review .stars { font-size: 15px; margin-bottom: 10px; }
.review p { margin: 0 0 14px; color: var(--ink-2); font-size: 15.5px; }
.review .who { font-size: 13.5px; color: var(--muted); margin: 0; }

/* ---------- screenshots (kept ready; see index.html) ---------- */

.shots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 26px;
}
.shot { margin: 0; }
.shot img {
  width: 100%;
  border-radius: 26px;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lift);
  display: block;
}
.shot figcaption { margin-top: 12px; font-size: 14px; color: var(--muted); text-align: center; }

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  padding: 48px 0 56px;
}

.footer-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  justify-content: space-between;
  align-items: flex-start;
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 15px;
}
.footer-nav a { color: var(--ink-3); text-decoration: none; font-weight: 500; }
.footer-nav a:hover { color: var(--brand-deep); }

.legal-line { font-size: 14px; color: var(--muted); margin: 26px 0 0; }

/* ---------- legal pages ---------- */

.legal { padding: 64px 0 88px; }
.legal .wrap { max-width: 760px; }

.legal h1 { font-size: clamp(2rem, 5vw, 2.7rem); margin-bottom: 10px; }
.legal .updated { color: var(--muted); font-size: 14.5px; margin: 0 0 12px; }

.legal h2 {
  font-size: 1.45rem;
  margin: 46px 0 12px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}
.legal h3 { font-size: 1.06rem; margin: 26px 0 8px; }

.legal p, .legal li { color: var(--ink-2); font-size: 16.5px; }
.legal ul, .legal ol { padding-left: 22px; }
.legal li { margin-bottom: 8px; }

.legal table {
  width: 100%;
  border-collapse: collapse;
  margin: 18px 0 8px;
  font-size: 15.5px;
}
.legal th, .legal td {
  text-align: left;
  vertical-align: top;
  padding: 11px 12px;
  border-bottom: 1px solid var(--border);
}
.legal th { color: var(--ink); font-weight: 700; background: var(--surface-3); }

.callout {
  background: var(--brand-tint);
  border: 1px solid var(--border-strong);
  border-left: 4px solid var(--brand);
  border-radius: var(--radius-md);
  padding: 18px 20px;
  margin: 24px 0;
}
.callout p { margin: 0; }
.callout p + p { margin-top: 10px; }

.toc {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 22px 24px;
  margin: 30px 0 8px;
}
.toc h2 {
  border-top: 0;
  padding-top: 0;
  margin: 0 0 12px;
  font-size: 1.05rem;
  font-family: var(--body);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.toc ol { margin: 0; padding-left: 20px; columns: 2; column-gap: 30px; }
.toc li { margin-bottom: 6px; font-size: 15px; }
.toc a { text-decoration: none; }
.toc a:hover { text-decoration: underline; }

/* ---------- responsive ---------- */

@media (max-width: 880px) {
  .hero { padding: 52px 0 64px; }
  .band { padding: 64px 0; }
  .site-nav { gap: 16px; font-size: 14px; }
  .toc ol { columns: 1; }
}

@media (max-width: 560px) {
  body { font-size: 16px; }
  :root { --gutter: 20px; }
  .site-nav a[data-optional] { display: none; }
  .footer-grid { flex-direction: column; gap: 22px; }
}

/* ---------- dark ----------
   Three modes, matching the app. src/theme/ThemeContext.tsx stores light /
   dark / system under settings.themeMode and Settings exposes it, so the app's
   appearance is independent of the OS — "app in Dark on a Light phone" is a
   normal state that no media query can see. theme.js resolves the stored
   choice onto <html data-theme="...">; the media query below covers "system"
   and the no-JavaScript fallback.

   Values are the app's own darkColors from src/theme/tokens.ts, not a generic
   inversion.

   THE TOKEN BLOCK IS DUPLICATED BELOW ON PURPOSE. CSS cannot share a
   declaration list between a plain selector and a media query, and the
   no-attribute case has to work with JavaScript off. If you edit one copy,
   edit the other — the packaging check asserts they are identical after
   whitespace normalisation, so drift is caught, but only if someone runs it. */

:root[data-theme="dark"] {
    --surface: #1C1917;
    --surface-2: #292524;
    --surface-3: #35302D;
    --ink: #FAFAF9;
    --ink-2: #F5F5F4;
    --ink-3: #D6D3D1;
    --muted: #A8A29E;

    --brand: #E07A5F;
    /* onBrandTertiary in the app's dark palette. The light-mode #994D35 is a
       4.9:1 link colour on cream and a 2.1:1 disaster on #1C1917. */
    --brand-deep: #F0B49B;
    --brand-tint: #33241E;
    --honey: #F2CC8F;
    --sage: #81B29A;
    --warning: #E29578;

    --border: #3A3532;
    --border-strong: #504945;

    /* Shadows barely register on a dark surface — the app leans on
       surfaceSecondary for elevation and keeps only a faint spread. */
    --shadow-card: 0 4px 12px rgba(0, 0, 0, 0.34);
    --shadow-lift: 0 10px 30px rgba(0, 0, 0, 0.46);

    /* These four cannot be derived by inverting a palette entry. --btn-* in
       particular: the App Store button used var(--ink) as its fill, which in
       dark is near-white — white text on a white pill. */
    --btn-bg: #FAFAF9;
    --btn-fg: #1C1917;
    --header-bg: rgba(28, 25, 23, 0.84);
    --icon-stroke: #F0B49B;

    color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
  /* "system" mode, and the no-JS fallback where the attribute was never set. */
  :root[data-theme="system"], :root:not([data-theme]) {
    --surface: #1C1917;
    --surface-2: #292524;
    --surface-3: #35302D;
    --ink: #FAFAF9;
    --ink-2: #F5F5F4;
    --ink-3: #D6D3D1;
    --muted: #A8A29E;

    --brand: #E07A5F;
    /* onBrandTertiary in the app's dark palette. The light-mode #994D35 is a
       4.9:1 link colour on cream and a 2.1:1 disaster on #1C1917. */
    --brand-deep: #F0B49B;
    --brand-tint: #33241E;
    --honey: #F2CC8F;
    --sage: #81B29A;
    --warning: #E29578;

    --border: #3A3532;
    --border-strong: #504945;

    /* Shadows barely register on a dark surface — the app leans on
       surfaceSecondary for elevation and keeps only a faint spread. */
    --shadow-card: 0 4px 12px rgba(0, 0, 0, 0.34);
    --shadow-lift: 0 10px 30px rgba(0, 0, 0, 0.46);

    /* These four cannot be derived by inverting a palette entry. --btn-* in
       particular: the App Store button used var(--ink) as its fill, which in
       dark is near-white — white text on a white pill. */
    --btn-bg: #FAFAF9;
    --btn-fg: #1C1917;
    --header-bg: rgba(28, 25, 23, 0.84);
    --icon-stroke: #F0B49B;

    color-scheme: dark;
  }
}

/* Two fixups that are rules rather than tokens, so they need their own
   selectors in both places. */
:root[data-theme="dark"] .appstore[aria-disabled="true"],
:root[data-theme="dark"] .appstore[aria-disabled="true"]:hover {
  background: var(--surface-2);
  color: var(--ink-3);
}
:root[data-theme="dark"] .appstore[aria-disabled="true"] .apple { fill: var(--ink-3); }
/* Font smoothing that helps on cream makes light-on-dark text look thin. */
:root[data-theme="dark"] body { -webkit-font-smoothing: auto; }

@media (prefers-color-scheme: dark) {
  :root[data-theme="system"] .appstore[aria-disabled="true"],
  :root[data-theme="system"] .appstore[aria-disabled="true"]:hover,
  :root:not([data-theme]) .appstore[aria-disabled="true"],
  :root:not([data-theme]) .appstore[aria-disabled="true"]:hover {
    background: var(--surface-2);
    color: var(--ink-3);
  }
  :root[data-theme="system"] .appstore[aria-disabled="true"] .apple,
  :root:not([data-theme]) .appstore[aria-disabled="true"] .apple { fill: var(--ink-3); }
  :root[data-theme="system"] body,
  :root:not([data-theme]) body { -webkit-font-smoothing: auto; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* Freeze on state 3. Without an explicit value the rings would fall back to
     stroke-dashoffset: var(--circ) — a fully undrawn, empty ring. */
  .ring-value { animation: none; stroke-dashoffset: var(--s3); }
  .ring-num { animation: none; opacity: 0; }
  .ring-num.n1 { opacity: 0; }
  .ring-num.n3 { opacity: 1; }
  .appstore { transition: none; }
  .appstore:hover { transform: none; }
}

/* ---------- appearance toggle ----------
   Hidden until theme.js adds .js to <html>. Without JavaScript there is no
   preference to store and nothing the button could do, and a dead control is
   worse than no control — the page still follows the OS in that case. */

.theme-toggle { display: none; }
.js .theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--ink-3);
  cursor: pointer;
  flex: none;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.js .theme-toggle:hover { border-color: var(--border-strong); color: var(--brand-deep); }

/* Visually hidden but still announced. Carries the appearance-change status. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- /join invite landing ---------- */

/* Single-purpose page: someone tapped an invite link and either does not have
   the app or the Universal Link did not fire. Everything here serves reading
   six characters and acting on them, so it is centred, short, and has no nav. */
.join-wrap {
  max-width: 420px;
  margin: 0 auto;
  padding: 64px 24px 48px;
  text-align: center;
}

.join-logo {
  font-family: var(--display);
  font-weight: 600;
  font-size: 20px;
  color: var(--brand);
  text-decoration: none;
}

.join-wrap h1 {
  font-family: var(--display);
  font-size: 28px;
  line-height: 1.2;
  color: var(--ink);
  margin: 32px 0 12px;
}

.join-sub { color: var(--ink-3); margin: 0 0 16px; }

/* Monospace and wide tracking because this is meant to be COPIED BY EYE onto a
   keyboard. O/0 and I/1 are the whole problem with a 6-character code, and the
   body face does not distinguish them. */
.join-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 40px;
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px 12px;
  margin: 0 0 20px;
  /* The tracking adds a trailing gap that makes the block look off-centre. */
  text-indent: 0.18em;
}

.join-code-none { color: var(--muted); letter-spacing: 0; }

.join-note {
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
  margin: 0 0 28px;
}

.join-btn {
  display: block;
  padding: 15px 20px;
  border-radius: var(--radius-lg);
  background: var(--brand);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  margin-bottom: 12px;
}

.join-btn-alt {
  background: transparent;
  color: var(--ink-2);
  border: 1px solid var(--border);
}
