/* My Sādhana Today — the landing page.
   ────────────────────────────────────────────────────────────────────────────────────────────
   The theme tokens are the app's own, from src/style.css, so the site and the app are one
   palette rather than two that nearly match. Dark is the default (:root) because dark is the
   app's default; light is an override on [data-theme="light"], set by the inline script in
   <head> and by the toggle.

   Do not retune a value here on its own. If one moves, it moves in the app first and this file
   follows — the whole point is that a visitor who downloads the app recognises the screen.

   Three tokens are this file's own, and each says why beside it: --accent (both themes),
   --accent-ink, and --shadow-ink. They are the ones the app has not needed yet, and the accent
   pair is the only place the site's colour is not the app's byte for byte. */
:root {
  color-scheme: dark;
  --bg: #14131C;
  --surface: #1D1B29;
  --surface-2: #262436;
  --border: #322F45;
  --text: #ECE9F5;
  --muted: #9A95B5;
  /* The app's violet is #7C5CFF, and on this page it would be text: a link in the prose and the
     label of the one filled button. It lands at 4.31:1 as a link on --bg and 4.35:1 under white
     ink — both a whisker under 4.5:1, and a mid-tone violet cannot be rescued by choosing a
     better ink, because it is equally far from black and from white. So the hue is kept exactly
     and the value is moved: this tint clears 6.2:1 as a link and 7.0:1 with the page's own
     ground as ink on top of it. The same pass belongs in the app, and when it lands there this
     file should follow it rather than the other way round. */
  --accent: #9A80FF;
  --accent-ink: #14131C;   /* text on an --accent fill; a violet this light needs a dark ink */
  --good: #54D18C;
  --warn: #F0A23B;
  --bad: #E8597A;
  /* Card and toast shadows. Tokenised because the colour is not the same on both grounds: over
     near-white a neutral black shadow greys the paper, so light uses the ink at a low alpha.
     The app draws no shadows at all — it is a window, not a page — so this pair is the
     landing's own. */
  --shadow-ink: rgba(0, 0, 0, .45);
  --radius: 14px;

  /* One face, the system sans, everywhere. Unlike the two sister sites there is no serif here:
     the kit's wordmark is a bold condensed sans beside a script "my", and setting the headings
     in a Palatino would put a third voice on a page that already has two. Headings are
     separated by size and weight instead. */
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  --topbar-h: 60px;
  --page: 1120px;          /* content column; the bands are centred inside it */
}
[data-theme="light"] {
  color-scheme: light;
  --bg: #F5F3FB; --surface: #FFFFFF; --surface-2: #F0EDF8; --border: #E2DEF0;
  --text: #1C1A28; --muted: #6C6685;
  /* The app leaves --accent alone in light mode, so #7C5CFF lands on near-white at 3.97:1 as a
     link. Same hue, taken deep enough to clear it: 6.1:1 on --bg, 5.8:1 on a card, and 6.7:1
     for white ink inside a primary button. */
  --accent: #5B3FD6; --accent-ink: #FFFFFF;
  --good: #1F7A4C; --warn: #8A5200; --bad: #B3213F;
  --shadow-ink: rgba(28, 26, 40, .12);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; }
/* Anchored sections must not slide under the sticky bar. */
:target, section[id] { scroll-margin-top: calc(var(--topbar-h) + 12px); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg); color: var(--text);
  font-family: var(--sans);
  font-size: 16px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* Theme-aware scrollbars (the default track is white, which glares in dark mode). */
* { scrollbar-color: var(--border) transparent; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--surface-2); border: 3px solid var(--bg); border-radius: 8px; }

a { color: var(--accent); }
a:hover { text-decoration: none; }
h1, h2, h3 { line-height: 1.25; }
img { max-width: 100%; }

/* Visually hidden but readable by assistive tech. */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 60;
  background: var(--accent); color: var(--accent-ink);
  padding: 10px 16px; border-radius: 0 0 10px 10px; font-weight: 600; text-decoration: none;
}
.skip-link:focus { top: 0; }

/* Keyboard focus, once, in one place — every control below inherits it. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

/* ── The brand ───────────────────────────────────────── */
/* Artwork in both slots, which is where this page parts from its two sister sites. Their
   wordmarks are plain letterforms with tracking and are set as live HTML text; this one is a
   script "my" beside a bold condensed "SĀDHANA TODAY" with a drawn macron, and no font stack
   reproduces it. So the kit's own cuts are used: the horizontal strip in the bar, the stacked
   lockup with the mālā above it in the hero.
   Both are one flat ink on a transparent ground — #455E75 for paper, #FFF4E2 for night — so the
   theme swap below is not decoration, it is the only thing keeping the mark visible. */
.brand { display: flex; align-items: center; text-decoration: none; }
.brand-dark { display: block; }
.brand-light { display: none; }
[data-theme="light"] .brand-dark { display: none; }
[data-theme="light"] .brand-light { display: block; }

/* The strip is ~8.4:1 — always size it by width and let the height follow. */
.brand-word { width: 168px; height: auto; }
/* The stacked lockup is ~0.92:1 and already carries the wordmark under the mālā, so it needs no
   text beside it and the hero copy below simply ranges left under it. */
.brand-lockup { width: 168px; height: auto; }

/* ── Top bar ─────────────────────────────────────────── */
#topbar {
  position: sticky; top: 0; z-index: 50;
  height: var(--topbar-h);
  display: flex; align-items: center; gap: 16px;
  padding: 0 max(16px, calc((100% - var(--page)) / 2));
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
/* `color-mix` is recent enough to want a floor: an opaque bar is a fine outcome without it. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  #topbar { background: var(--bg); }
}
.topnav { display: flex; gap: 4px; margin-left: auto; }
.topnav a {
  color: var(--muted); text-decoration: none; font-size: 14px;
  padding: 8px 12px; border-radius: 10px; white-space: nowrap;
}
.topnav a:hover { background: var(--surface-2); color: var(--text); }
.topbar-controls { display: flex; align-items: center; gap: 8px; }

/* ── The language picker ─────────────────────────────── */
.lang { position: relative; }
/* Flag only when closed, which is why this is a hand-built listbox and not a <select>. */
.lang-btn { font-size: 17px; line-height: 1; }
.lang-flag { line-height: 1; }
.lang-list {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
  margin: 0; padding: 5px; list-style: none;
  min-width: 12.5em;
  /* 22 languages will not fit a short window; the list scrolls rather than running off it. */
  max-height: min(70vh, 460px); overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 10px 30px var(--shadow-ink);
}
.lang-list[hidden] { display: none; }
.lang-opt {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px;
  font-size: 14px; cursor: pointer;
}
.lang-opt:hover { background: var(--surface-2); }
/* The endonyms are in twelve scripts and several have tall ascenders and descenders; a fixed
   line-height keeps every row the same height so the list does not look ragged. */
.lang-opt-flag { font-size: 16px; line-height: 1.4; flex: none; }
.lang-opt-name { line-height: 1.4; }
.lang-opt[aria-selected="true"] { color: var(--accent); font-weight: 600; }
.icon-btn {
  width: 36px; height: 36px; display: grid; place-items: center;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 10px; cursor: pointer;
}
.icon-btn:hover { border-color: var(--accent); color: var(--accent); }
/* The hamburger. Absent above the breakpoint, where the nav is a row and there is nothing to
   disclose — `display: none` rather than visually hidden, so it is out of the tab order too. */
.nav-toggle { display: none; }
.nav-ico::before { content: '☰'; font-size: 17px; line-height: 1; }
/* Turns into a close glyph while the panel is open, so the button says what pressing it does
   now rather than what it did a moment ago. */
.nav-toggle[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }
.nav-toggle[aria-expanded="true"] .nav-ico::before { content: '✕'; font-size: 15px; }
/* One glyph, two states: the moon is what dark mode offers to leave, the sun what light does.
   Content, not an <img>, so it inherits `color` and needs no second asset. */
.theme-ico::before { content: '☀'; font-size: 17px; line-height: 1; }
[data-theme="light"] .theme-ico::before { content: '☾'; }

/* ── Layout ──────────────────────────────────────────── */
#main { display: block; }
.band, .hero, #foot {
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 16px;
}
.band { padding-top: 56px; }
.band:last-child { padding-bottom: 56px; }
.section-title { margin: 0 0 6px; font-weight: 600; font-size: 26px; letter-spacing: -.01em; }
.band-hint { margin: 0 0 16px; }
.section-title + .card, .section-title + .grid,
.band-hint + .card, .band-hint + .grid { margin-top: 16px; }

.card {
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px 20px;
  box-shadow: 0 1px 2px var(--shadow-ink);
}
.prose p { margin: 0 0 12px; }
.prose p:last-child { margin-bottom: 0; }
/* A subheading inside a card of running prose — "What is sādhana?" under the About paragraphs,
   and the supporter list's own heading. Needs air above it and almost none below. */
.prose h3 { margin: 22px 0 8px; font-size: 17px; font-weight: 600; }
.prose > h3:first-child { margin-top: 0; }
.hint { color: var(--muted); font-size: 14px; }
.muted { color: var(--muted); }

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

/* ── Hero ────────────────────────────────────────────── */
/* One column. The lockup, the headline, the lede, three facts and the two buttons — nothing to
   set beside them, so there is no grid here and the measure is held by .lede's own max-width
   rather than by a column. */
.hero { padding-top: 64px; padding-bottom: 8px; }
.hero-brand { margin-bottom: 22px; }
.hero-brand .brand-lockup { width: 176px; }
.hero h1 { margin: 0 0 14px; font-weight: 600; font-size: clamp(30px, 5vw, 44px); letter-spacing: -.015em; }
.lede { margin: 0 0 20px; font-size: 17px; color: var(--text); max-width: 46em; }

/* Three plain facts. Not "free, with everything in it" as on the two sister sites — this app has
   a supporter tier and a three-practice cap on the free plan, and a badge that said otherwise
   would be the first thing on the page and would be false. */
.badges { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 24px; padding: 0; }
.badges li {
  font-size: 13px; color: var(--muted);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px; padding: 5px 12px;
}
.hero-actions { display: flex; flex-wrap: wrap; gap: 10px; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 20px; border-radius: 12px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border);
  font-family: inherit; font-size: 15px; font-weight: 600;
  text-decoration: none; cursor: pointer;
}
.btn:hover { border-color: var(--accent); }
.btn.primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.btn.primary:hover { filter: brightness(1.06); }
/* A channel that has no URL yet. Rendered as a <div>, so there is nothing to click and nothing
   to focus — "coming soon" is information, not a control. Never given .primary either: a filled
   violet button is the page's strongest call to action and must not point nowhere. */
.btn.soon { opacity: .6; cursor: default; gap: 8px; }
.btn.soon:hover { border-color: var(--border); }
.btn-tag { font-size: 12px; font-weight: 400; color: var(--accent); white-space: nowrap; }

/* ── Features ────────────────────────────────────────── */
.feat h3 { margin: 0 0 8px; font-size: 16px; display: flex; align-items: baseline; gap: 8px; }
.feat-ico { color: var(--accent); font-size: 15px; line-height: 1; flex: none; }
.feat p { margin: 0 0 10px; font-size: 15px; }
.feat p:last-child { margin-bottom: 0; }

/* ── The quoted verse ────────────────────────────────── */
/* The Privacy section argues from scripture rather than from a policy, so the verse is set as a
   quotation with its reference — indented off an accent rule, the way a pull quote is, and not
   italicised: several of the twenty-one translations render it in scripts where italic is a
   synthetic slant rather than a real cut. */
.quote { margin: 16px 0; padding: 2px 0 2px 16px; border-left: 3px solid var(--accent); }
.quote blockquote { margin: 0; font-size: 16px; }
.quote figcaption { margin-top: 6px; font-size: 13px; color: var(--muted); }

/* ── The supporter list ──────────────────────────────── */
/* What a donation actually unlocks, item by item. A plain list rather than a two-column pricing
   table: there is one paid tier and no grid of ticks to draw, and a table would imply a
   comparison the app does not offer. */
.plans { margin: 12px 0 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.plans li {
  position: relative; padding-left: 26px; font-size: 15px;
}
.plans li::before {
  content: '✓'; position: absolute; left: 4px; top: 0;
  color: var(--accent); font-size: 14px;
}

/* ── Downloads ───────────────────────────────────────── */
/* The version the cards below lead to. A chip rather than another line of prose: it is a fact
   about the files, not a sentence about them, and the band already opens with two hints in
   --muted that it would otherwise disappear into. `inline-block` so the border wraps the words
   and not the column. */
.dl-version {
  display: inline-block;
  margin: 0 0 16px;
  padding: 3px 11px;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface);
  font-size: 13px; color: var(--muted);
  /* The number is the payload, and it is read against the last one the visitor saw. Tabular
     figures keep 1.0.0 and 1.10.0 from shifting the digits around under it. */
  font-variant-numeric: tabular-nums;
}
/* Wide enough for a 64-character checksum to wrap in two lines rather than four. */
.grid-dl { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
/* The card owns the border; the link and the checksum row inside it are borderless panels
   divided by a rule, so the two read as one object. */
.dl-card {
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden;
}
.dl-card:not(.soon):hover { border-color: var(--accent); }
.dl {
  display: flex; align-items: center; gap: 12px;
  color: var(--text);
  padding: 14px 16px; text-decoration: none;
  flex: 1;  /* so a card with no checksum row still matches the height of one that has */
}
.dl-ico { font-size: 22px; line-height: 1; flex: none; width: 26px; text-align: center; }
.dl-body { min-width: 0; }
.dl-name { display: block; font-weight: 600; font-size: 15px; }
.dl-hint { display: block; font-size: 13px; color: var(--muted); }
/* A channel with no URL yet. Rendered as a <div>, so there is nothing to click and nothing to
   focus — "coming soon" is information, not a control. Dimmed per-part rather than on the whole
   card, because a row can carry a published checksum before its download URL exists. */
.dl.soon { opacity: .6; cursor: default; }
.dl.soon .dl-hint { color: var(--accent); }

/* The checksum row. What makes an unsigned build checkable, so it is given a line of its own
   rather than being folded into the hint. */
.dl-sum {
  display: flex; align-items: baseline; gap: 8px;
  width: 100%; padding: 9px 16px;
  background: var(--bg); color: var(--text);
  border: 0; border-top: 1px solid var(--border);
  font-family: inherit; font-size: 11px; text-align: left; cursor: pointer;
}
.dl-sum:hover { color: var(--accent); }
.dl-sum-label { color: var(--muted); letter-spacing: .06em; flex: none; }
/* Wraps rather than truncating — see the note in js/10-main.js on why a part-shown digest is
   worse than an ugly one. */
.dl-sum-hash {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 11px; color: var(--muted);
  overflow-wrap: anywhere; min-width: 0;
}
.dl-sum-copy { margin-left: auto; color: var(--accent); flex: none; }
.dl-sum.soon { opacity: .6; cursor: default; }
.dl-sum.soon:hover { color: var(--text); }
/* No digest yet: the placeholder is prose, not a hash, so it is not set in the mono face. */
.dl-sum.soon .dl-sum-hash { font-family: inherit; color: var(--accent); }

/* ── Support ─────────────────────────────────────────── */
.support-links { display: flex; flex-wrap: wrap; gap: 10px; margin: 22px 0 18px; }
.support-thanks { margin: 18px 0 0; font-size: 17px; font-weight: 600; color: var(--accent); }
/* The thanks line follows the wallet rows directly, and at 18px it read as the last row's
   caption rather than as the section closing. This is the one gap on the page that has to be
   larger than the rhythm around it. */
.crypto + .support-thanks { margin-top: 32px; }
.crypto { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border); }
.crypto h3 { margin: 0 0 4px; font-size: 16px; }
.crypto-list { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 8px; }
.crypto-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 12px; cursor: pointer; text-align: left;
  font-family: inherit;
}
.crypto-row:hover { border-color: var(--accent); }
/* No address set. Same treatment as .btn.soon, and the "coming soon" sits in the slot the
   address would have filled, so the row still says which chain is planned. */
.crypto-row.soon { opacity: .6; cursor: default; }
.crypto-row.soon:hover { border-color: var(--border); }
.crypto-row.soon .crypto-addr { font-family: inherit; font-size: 13px; color: var(--accent); }
.crypto-coin { font-weight: 600; font-size: 14px; flex: none; min-width: 5.5em; }
/* The address is the one string on the page that must be read character by character, so it is
   monospaced — and it wraps rather than truncating, because a half-shown wallet address that
   looks complete is worse than an ugly one. */
.crypto-addr {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12.5px; color: var(--muted);
  overflow-wrap: anywhere; min-width: 0;
}
.crypto-copy { margin-left: auto; font-size: 13px; color: var(--accent); flex: none; }

/* ── Footer ──────────────────────────────────────────── */
#foot {
  margin-top: 56px; padding-top: 24px; padding-bottom: 40px;
  border-top: 1px solid var(--border);
  font-size: 14px;
}
#foot p { margin: 0 0 6px; }

/* ── Toast ───────────────────────────────────────────── */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  z-index: 70;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 999px;
  padding: 10px 18px; font-size: 14px;
  box-shadow: 0 6px 20px var(--shadow-ink);
}
.toast[hidden] { display: none; }

/* ── Narrow ──────────────────────────────────────────── */
@media (max-width: 900px) {
  /* The nav stops being a row and becomes the panel the hamburger opens: full width under the
     bar, one link per line. It is the same markup and the same links — only the shape changes,
     which is why the toggle has nothing to build. */
  .topnav {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; gap: 2px;
    padding: 8px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: 0 10px 30px var(--shadow-ink);
    /* Long enough a list to need it on a landscape phone. */
    max-height: min(70vh, 420px); overflow-y: auto;
  }
  .topnav[data-open="true"] { display: flex; }
  .topnav a { padding: 12px; font-size: 15px; }
  .nav-toggle { display: grid; }
  .topbar-controls { margin-left: auto; }
  .hero { padding-top: 40px; }
  .hero-brand .brand-lockup { width: 140px; }
  .band { padding-top: 44px; }
}
@media (max-width: 420px) {
  /* The strip carries "my SĀDHANA TODAY" at 8.4:1, so it is the first thing that has to give
     when the bar runs out of room — the three controls beside it cannot shrink. */
  .brand-word { width: 132px; }
  .hero-brand .brand-lockup { width: 120px; }
  /* The popup is anchored to the button's right edge, so on a narrow screen it grows inward
     from there and cannot push the layout wider. */
  .lang-list { min-width: 11em; }
  .crypto-row { flex-wrap: wrap; }
  .crypto-copy { margin-left: 0; }
}
