/*
 * Marketing site styles (tada-234.1).
 *
 * Deliberately standalone — this does NOT import app/src/board.css. The apex is
 * a static page with no build step and no app bundle; pulling in the SPA's
 * stylesheet would drag along BV/SDV rules that have no markup here, and couple
 * a marketing tweak to the product's CSS. The tokens below are copied from
 * board.css so the two read as one product. If the palette changes there,
 * change it here too — that duplication is the deal a separate deploy makes.
 */
:root {
  --bg: #14171c;
  --panel: #1c2027;
  --panel-2: #232833;
  --line: #2e3540;
  --text: #e6e9ef;
  --dim: #9aa4b2;
  --faint: #6b7480;
  --done: #46c98a;
  --planned: #7c5cff;
  --idea: #e8eaf0;
  --bug: #e0705f;
  --in-progress: #f0c040;
  --accent: #f59e0b;
  --gutter: 28px;
  --measure: 62ch;
}

* {
  box-sizing: border-box;
}


body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.6 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
}

/* ── header ─────────────────────────────────────────────────────────────── */

.site-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px var(--gutter);
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.brand {
  font-weight: 800;
  font-size: 20px;
  letter-spacing: -0.01em;
  text-decoration: none;
}

/* Header nav (tada-319.2). Docs sits inset from Sign in — 20px, tighter than
   the header's own 16px+ outer gap, so the two read as one group pinned to the
   right rather than as three evenly-spread items. A plain link, not a second
   button: two buttons side by side would compete for the same attention, and
   Sign in is the action the header exists to offer. */
.site-nav {
  display: flex;
  align-items: center;
  gap: 20px;
}
.nav-link {
  color: var(--dim);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
}
.nav-link:hover {
  color: var(--text);
}
/* The current section, on the docs pages themselves. */
.nav-link.is-current {
  color: var(--text);
}
/* ── buttons (mirrors the app's .btn / .btn.ghost) ──────────────────────── */

.btn {
  display: inline-block;
  height: 36px;
  line-height: 36px;
  padding: 0 16px;
  border-radius: 8px;
  border: none;
  background: var(--accent);
  color: #1a1200;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover {
  filter: brightness(1.08);
}
.btn.ghost {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--line);
}

/* ── hero ───────────────────────────────────────────────────────────────── */

.hero {
  padding: 88px var(--gutter) 56px;
  max-width: var(--measure);
  margin: 0 auto;
  text-align: center;
}
.hero h1 {
  margin: 0 0 20px;
  font-size: clamp(34px, 6vw, 56px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-weight: 800;
}
.lede {
  margin: 0 auto 32px;
  color: var(--dim);
  font-size: clamp(16px, 2.2vw, 19px);
}
.cta-row {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

/* ── board preview ──────────────────────────────────────────────────────── */

/* Four lanes on desktop; scrolls horizontally on narrow screens rather than
   squeezing the cards to unreadable widths. `grid-auto-flow: column` keeps the
   four lanes on one row while scrolling — a plain `repeat(4, …)` would let them
   wrap once the viewport is narrower than four minimums.

   Scroll-padding on the inline edges means the last lane clears the viewport
   edge instead of sitting flush against the cut, which is what makes the strip
   read as scrollable rather than clipped. */
.board-preview {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(190px, 1fr);
  gap: 14px;
  max-width: 1040px;
  margin: 0 auto;
  padding: 0 var(--gutter) 72px;
  overflow-x: auto;
  scroll-padding-inline: var(--gutter);
  overscroll-behavior-x: contain;
}
/* `stretch` (the grid default) rather than per-lane height: the lanes hold
   different numbers of cards, and ragged bottoms read as a broken layout rather
   than as the real board, whose lanes are full-height columns. */
.lane {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px;
  min-width: 0;
  align-self: stretch;
}
.lane-head {
  margin-bottom: 10px;
}
.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  color: #14171c;
}
.badge.idea {
  background: var(--idea);
}
.badge.planned {
  background: var(--planned);
  color: #fff;
}
.badge.in-progress {
  background: var(--in-progress);
}
.badge.done {
  background: var(--done);
}
.card {
  position: relative;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 12px 14px;
  margin-bottom: 10px;
  font-size: 14px;
  line-height: 1.45;
  overflow: hidden;
}
.card:last-child {
  margin-bottom: 0;
}
.card-type {
  margin-right: 6px;
}
/* The card progress bar, pinned to the bottom edge like the app's. */
.card-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: var(--line);
  display: block;
}
.card-bar i {
  display: block;
  height: 100%;
  background: var(--in-progress);
}

/* ── content bands ──────────────────────────────────────────────────────── */

/* The last band ends the page (there is no footer or closing CTA), so it
   carries the closing whitespace itself — the symmetric 64px leaves the final
   content sitting too near the bottom edge. */
.band:last-of-type {
  padding-bottom: 112px;
}
.band {
  padding: 64px var(--gutter);
  border-top: 1px solid var(--line);
  max-width: 1040px;
  margin: 0 auto;
}
.band h2 {
  margin: 0 0 12px;
  font-size: clamp(24px, 3.4vw, 32px);
  letter-spacing: -0.01em;
}
.section-lede {
  margin: 0 0 32px;
  color: var(--dim);
  max-width: var(--measure);
}

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px;
}
.feature {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 22px;
}
.feature h3 {
  margin: 0 0 10px;
  font-size: 18px;
}
.feature p {
  margin: 0;
  color: var(--dim);
  font-size: 15px;
}

/* ── docs pages (tada-319.2) ────────────────────────────────────────────── */

/* One measure-width column rather than the apex's centered hero: docs are read
   left-to-right in sequence, and centered body text at this length is harder to
   track back to the next line. */
.doc {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 56px var(--gutter) 112px;
}
.eyebrow {
  margin: 0 0 8px;
  color: var(--accent);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.doc h1 {
  margin: 0 0 20px;
  font-size: clamp(30px, 5vw, 44px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-weight: 800;
}
/* Left-aligned here, unlike the hero's centered .lede. */
.doc-lede {
  margin: 0 0 8px;
  text-align: left;
}
.doc h2 {
  margin: 48px 0 12px;
  font-size: clamp(20px, 2.8vw, 26px);
  letter-spacing: -0.01em;
  scroll-margin-top: 24px;
}
.doc h2:first-of-type {
  margin-top: 40px;
}
.doc p {
  margin: 0 0 16px;
  color: var(--dim);
}
.doc strong {
  color: var(--text);
  font-weight: 650;
}

/* The board figures (tada-319.10). The app's own components render inside
   .app-figure, styled by the scoped board.css — so these rules only handle
   *placement* on the docs page, never the look of the board itself. The lanes
   need a real width to read as columns, so the figures bleed past the text
   measure and scroll horizontally on narrow screens rather than crushing. */
.fig {
  margin: 24px calc(-1 * var(--fig-bleed)) 8px;
  padding: 0;
  --fig-bleed: clamp(0px, (100vw - 2 * var(--gutter) - var(--measure)) / 2, 140px);
}
.fig figcaption {
  margin-top: 12px;
  padding-left: 2px;
  color: var(--faint);
  font-size: 13.5px;
  line-height: 1.5;
}
/* Both figures scroll horizontally rather than crushing their lanes — the same
   treatment the apex's board preview uses. The scroll container is the only
   thing these rules own; the boards inside lay themselves out with the app's
   own rules (.task-board is already a flex row, so it needs no grid here).

   Note `overflow-x` is NOT `auto` here: at full width the
   row's fractional width (scrollWidth rounds up, clientWidth rounds down) armed
   a scrollbar under a board that plainly fit. `clip` shows no scrollbar and no
   scroll; the media query below turns real scrolling on only where it is
   actually needed. */
.figure-board,
.figure-task-board {
  overflow-x: clip;
  padding-bottom: 4px;
}
/* The BV lanes are not a flex row in the app (BoardView supplies that), so the
   outer figure provides it.

   `flex: 1 1 0` — grow and *shrink* from a zero basis, so four lanes divide
   exactly the width available and never overflow it. The earlier
   `flex: 1 0 200px` + `min-width: 200px` refused to shrink, so the row computed
   2px wider than its container and raised a scrollbar under a board that
   visibly fit. `min-width: 0` overrides the flex item default of `auto`, which
   would otherwise floor each lane at its content width and reintroduce the
   same overflow.

   Below the breakpoint the lanes stop dividing and take a fixed width instead,
   scrolling within the figure — four lanes narrower than that break Story
   titles mid-word. That override lives in the media query below, which must
   come *after* this rule: the two selectors have equal specificity, so source
   order is what decides. */
.figure-board {
  display: flex;
  gap: 12px;
  align-items: stretch;
}
.figure-board > .lane {
  flex: 1 1 0;
  min-width: 0;
}

/* Below this the lanes would divide to less than the 180px floor below, so the
   figure switches to fixed-width lanes and scrolls instead. 900px is where four
   180px lanes plus their gaps and the page gutters stop fitting — set from that
   arithmetic rather than a round number, so the two halves agree. */
@media (max-width: 900px) {
  .figure-board,
  .figure-task-board {
    overflow-x: auto;
    scroll-padding-inline: var(--gutter);
    overscroll-behavior-x: contain;
  }
  /* The floor goes on the *content*, never on the scroll box: a min-width on
     the box itself cannot be satisfied by scrolling, so it widens the document
     and the whole page scrolls sideways. Inside the scroller it does what it
     should — hold four readable columns and let the box scroll to them. */
  .figure-board > .lane {
    flex: 0 0 180px;
  }
}
/* .card-title reserves 28px on the right for the actions strip — the kebab that
   floats over the title's row in the app. The presentational card renders no
   kebab, so in a figure that reserve is 28px of dead space that pushes titles
   into breaking mid-word ("Marketi / ng site"). Reclaim it here rather than in
   board.css, whose value is correct for the app. */
.figure-board .card-title {
  padding-right: 0;
}
/* The inner board's own .task-board sets margin-top for its place in the SDV,
   where it sits below the story fields. In a figure it is the first thing in
   the box, so that top margin is a stray gap. */
.figure-task-board .task-board {
  margin-top: 0;
}
/* .task-board carries `margin-inline: calc(-30px + var(--board-inset))` so it
   can escape .detail-scroll's 30px padding and sit just inside the SDV card's
   rounded edge. A figure has no such padding, so that negative margin hangs the
   board ~17px off both edges and it clips. Rather than cancel the rule — which
   would mean re-stating a value board.css owns — the figure supplies the
   padding the component is written against, so the arithmetic comes out where
   it does in the app. */
.figure-task-board {
  padding-inline: 30px;
}
/* The lanes are `flex: 1` against their container; here that's the figure. Give
   the row a floor so four columns stay readable, and let the host scroll when
   the viewport can't fit it. */
.figure-task-board .task-board {
  min-width: 600px;
}
.figure-task-board .task-lane {
  min-width: 0;
}
/* board.css hides .task-board below 600px because the *app* swaps the SDV to a
   flat checklist there. A figure is not the app: it is illustrating what the
   task board is, and a caption pointing at nothing is worse on a phone than a
   board you scroll sideways. So the figure opts out of that rule and keeps its
   own scroll affordance. This is the class of thing sourcing the app's real CSS
   buys you — its *behavior*, not just its looks — and it has to be opted out of
   deliberately rather than silently inherited. */
@media (max-width: 599px) {
  .figure-task-board .task-board {
    display: flex;
  }
}

/* The Story-contains-Tasks figure (tada-319.2). The nesting is the point, so
   the Tasks sit visibly *inside* the Story's panel, on the card surface the app
   uses for a card-within-a-lane. Static markup, like the apex's board preview —
   it stands in for the real UI without shipping any of it. */
.model {
  margin: 24px 0 8px;
  padding: 0;
}
.model-story {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 16px;
}
.model-story-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.model-emoji {
  font-size: 16px;
  line-height: 1;
}
/* The kind-label ("Story"), not the story's title — this figure names the
   entity, which is what the section is teaching. */
.model-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--faint);
  margin-right: auto;
}
.model-title {
  margin: 10px 0 14px;
  color: var(--text);
  font-weight: 600;
}
.model-tasks {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 8px;
}
.model-tasks li {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 9px 12px;
  font-size: 14px;
  color: var(--dim);
}
/* Sits close under the panel and slightly dimmer than body text, so it reads
   as belonging to the figure rather than as the next paragraph — it is followed
   immediately by a callout of similar weight. */
.model figcaption {
  margin-top: 10px;
  padding-left: 2px;
  color: var(--faint);
  font-size: 13.5px;
  line-height: 1.5;
}

/* The four types, as cards — the emoji is the same glyph the app renders, so
   the page shows the vocabulary rather than describing it.

   This is the one block that breaks the text measure: four peer categories read
   as one row, and at 62ch they would stack 2x2 and imply a grouping that isn't
   there. The negative margins are clamped so the grid never exceeds the
   viewport, and it collapses back inside the measure once there isn't room. */
.type-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  margin: 24px calc(-1 * var(--bleed)) 8px;
  --bleed: clamp(0px, (100vw - 2 * var(--gutter) - var(--measure)) / 2, 120px);
}
.type-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 18px;
}
.type-emoji {
  font-size: 22px;
  line-height: 1;
}
.type-card h3 {
  margin: 10px 0 6px;
  font-size: 16px;
}
.type-card p {
  margin: 0;
  font-size: 14px;
}

/* The status sequence, using the same badges as the board preview so the
   statuses read in their board colors. Arrows are generated content: they are
   punctuation between the badges, not content a screen reader should announce. */
.flow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 24px 0;
  padding: 0;
  list-style: none;
}
.flow li {
  display: flex;
  align-items: center;
  gap: 10px;
}
.flow li + li::before {
  content: "→";
  color: var(--faint);
}

/* Code blocks (tada-319.3). The site loads no highlighter — a build-time
   transform or a client-side library, and neither is worth it for a handful of
   config samples. Monospace on a panel reads fine without one. */
.code {
  margin: 20px 0;
  padding: 16px 18px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow-x: auto;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text);
}
.code code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
/* Inline code in prose. Dimmer background than .code so a run of them in a
   sentence doesn't stripe the paragraph. */
.doc p code,
.doc dd code,
.doc td code,
.doc dt code {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 1px 5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
  color: var(--text);
}

/* Flag/option list — a definition list rather than a table: each term is short
   and each description is a sentence or two, which a two-column table would set
   at an awkward measure. */
.flags {
  margin: 20px 0;
}
.flags dt {
  margin-top: 14px;
  font-weight: 600;
}
.flags dd {
  margin: 4px 0 0;
  padding-left: 16px;
  border-left: 1px solid var(--line);
  color: var(--dim);
}

/* The tool reference. A two-column table of names and sentences needs more than
   the 62ch prose measure — at measure width the descriptions set three words to
   a line — so it bleeds like the board figures, clamped to the viewport, and
   scrolls inside its own box rather than pushing the page sideways. */
.table-scroll {
  margin: 20px calc(-1 * var(--tbl-bleed)) 20px;
  --tbl-bleed: clamp(0px, (100vw - 2 * var(--gutter) - var(--measure)) / 2, 140px);
  overflow-x: auto;
  overscroll-behavior-x: contain;
}
.tools {
  width: 100%;
  min-width: 520px;
  border-collapse: collapse;
  font-size: 14px;
}
.tools th,
.tools td {
  text-align: left;
  vertical-align: top;
  padding: 9px 14px 9px 0;
  border-bottom: 1px solid var(--line);
}
.tools th {
  color: var(--text);
  font-weight: 600;
  white-space: nowrap;
}
.tools td {
  color: var(--dim);
}
.tools td:first-child {
  white-space: nowrap;
}

/* On a phone the two-column table is the wrong form: at 334px the description
   column sits entirely outside the scroll box, so the page shows a column of
   tool names beside tall empty rows and the reader has no cue the text is
   sideways. Stack each row into a block instead — name over description — which
   needs no horizontal scroll at all. */
@media (max-width: 599px) {
  .table-scroll {
    overflow-x: visible;
  }
  .tools {
    min-width: 0;
  }
  .tools thead {
    /* The headers label columns that no longer exist. Hidden accessibly rather
       than removed: the table is still a table to a screen reader. */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .tools tr {
    display: block;
    padding: 12px 0;
    border-bottom: 1px solid var(--line);
  }
  .tools td {
    display: block;
    padding: 0;
    border: 0;
  }
  .tools td:first-child {
    white-space: normal;
    margin-bottom: 5px;
  }
}

.callout {
  border-left: 2px solid var(--accent);
  padding: 2px 0 2px 16px;
  margin: 32px 0;
}
