/* ════════════════════════════════════════════════════════════════
   1 · TOKENS
   The Notion contract, pasted verbatim. Everything the page paints
   downstream resolves through these or the landing layer below.
   ════════════════════════════════════════════════════════════════ */
:root {
  /* ─── Surface ──────────────────────────────────────────────────── */
  --bg:           #ffffff;
  --surface:      #f6f5f4;               /* warm white — section alternation */
  --surface-warm: var(--surface);        /* aliases to warm white tier */

  /* ─── Foreground ───────────────────────────────────────────────── */
  --fg:   rgba(0, 0, 0, 0.95);           /* near-black — primary text */
  --fg-2: #31302e;                       /* warm dark — headings on surfaces */
  --muted: #615d59;                      /* warm gray 500 — secondary text */
  --meta:  #a39e98;                      /* warm gray 300 — placeholder/captions */

  /* ─── Border ───────────────────────────────────────────────────── */
  --border:      rgba(0, 0, 0, 0.1);    /* whisper border — standard */
  --border-soft: rgba(0, 0, 0, 0.06);  /* subtler row dividers */

  /* ─── Accent ───────────────────────────────────────────────────── */
  --accent:        #0075de;             /* Notion Blue — links, primary CTAs */
  --accent-on:     #ffffff;
  --accent-hover:  #005bab;             /* Active Blue — pressed state */
  --accent-active: color-mix(in oklab, var(--accent), black 14%);

  /* ─── Semantic ─────────────────────────────────────────────────── */
  --success: #1aae39;                   /* Notion green — confirmation */
  --warn:    #dd5b00;                   /* Notion orange — warning */
  --danger:  #dc2626;

  /* ─── Typography ───────────────────────────────────────────────── */
  --font-display: "NotionInter", "Inter", -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-body:    "NotionInter", "Inter", -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-mono:    ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Monaco, Consolas, monospace;

  --text-xs:   12px;                    /* badge / micro label */
  --text-sm:   14px;                    /* caption / footer */
  --text-base: 16px;                    /* body */
  --text-lg:   20px;                    /* body large — introductions */
  --text-xl:   26px;                    /* sub-heading */
  --text-2xl:  40px;                    /* sub-heading large */
  --text-3xl:  48px;                    /* section heading */
  --text-4xl:  64px;                    /* display hero */

  --leading-body:     1.5;
  --leading-tight:    1.00;
  --tracking-display: -0.033em;

  /* ─── Spacing ──────────────────────────────────────────────────── */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-8:  32px;
  --space-12: 48px;

  --section-y-desktop: 80px;
  --section-y-tablet:  48px;
  --section-y-phone:   32px;

  /* ─── Radius ───────────────────────────────────────────────────── */
  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-lg:   12px;
  --radius-pill: 9999px;

  /* ─── Elevation ────────────────────────────────────────────────── */
  --elev-flat:   none;
  --elev-ring:   0 0 0 1px var(--border);
  --elev-raised:
    rgba(0, 0, 0, 0.04) 0px 4px 18px,
    rgba(0, 0, 0, 0.027) 0px 2px 7.85px,
    rgba(0, 0, 0, 0.02) 0px 0.8px 2.93px,
    rgba(0, 0, 0, 0.01) 0px 0.175px 1.04px;

  /* ─── Focus ────────────────────────────────────────────────────── */
  --focus-ring: 0 0 0 3px rgba(9, 127, 232, 0.3);

  /* ─── Motion ───────────────────────────────────────────────────── */
  --motion-fast:   150ms;
  --motion-base:   200ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);

  /* ─── Layout ───────────────────────────────────────────────────── */
  --container-max:            1200px;
  --container-gutter-desktop: 24px;
  --container-gutter-tablet:  16px;
  --container-gutter-phone:   12px;
}

/* ── Landing layer ────────────────────────────────────────────────
   Motion vocabulary and the product's own colour data. Nothing here
   invents a surface colour: the sheet dots and the select-pill trio
   are read out of CSVita's 17-hue oklch table, so the chips and the
   demo grid cannot drift from the app they picture. */
:root{
  --motion-open:     200ms;
  --motion-press:     90ms;
  --motion-rise:       3px;
  --motion-rise-lg:   10px;
  --ease-out:         cubic-bezier(.16,1,.3,1);

  /* Stagger is a token, not a literal, so reducing motion can collapse
     every delay at once instead of out-specifying an nth-child rule. */
  --stagger:          60ms;
  --stagger-tight:    24ms;
  --tick-scale:       .6;

  /* One select hue, resolved as the app resolves it: tint → edge → mark. */
  --pill-tint: oklch(93.2% 0.032 255.585);
  --pill-edge: oklch(80.9% 0.105 251.813);
  --pill-mark: oklch(48.8% 0.243 264.376);
}

/* ════════════════════════════════════════════════════════════════
   2 · BASE
   ════════════════════════════════════════════════════════════════ */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--bg);color:var(--fg);
  font-family:var(--font-body);font-size:var(--text-base);line-height:var(--leading-body);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
h1,h2,h3,h4,p,figure{margin:0}
ul{margin:0;padding:0;list-style:none}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
svg{display:block}
kbd{font-family:var(--font-mono);font-size:.92em}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
::selection{background:color-mix(in srgb, var(--accent) 16%, transparent)}

.skip{
  position:absolute;left:8px;top:-64px;z-index:100;
  background:var(--fg);color:var(--bg);padding:12px 18px;border-radius:var(--radius-md);
  box-shadow:var(--elev-raised);font-weight:600;font-size:14px;
  transition:top var(--motion-fast) var(--ease-standard);
}
.skip:focus{top:8px}

.container{max-width:var(--container-max);margin:0 auto;padding:0 var(--container-gutter-desktop)}

/* ════════════════════════════════════════════════════════════════
   3 · TYPE
   NotionInter at Notion's own compression: the display sizes take
   negative tracking, body copy takes none, and the mono carries every
   piece of machine text — file names, counts, shortcuts.
   ════════════════════════════════════════════════════════════════ */
h1,h2,h3{font-family:var(--font-display);font-weight:700;color:var(--fg);text-wrap:balance}
h1{font-size:clamp(40px, 6vw, var(--text-4xl));line-height:1.05;letter-spacing:var(--tracking-display)}
h2{font-size:clamp(32px, 4.2vw, var(--text-3xl));line-height:1.06;letter-spacing:-0.025em}
h3{font-size:var(--text-xl);line-height:1.3;letter-spacing:-0.02em}

.lead{font-size:var(--text-lg);line-height:1.4;color:var(--muted);max-width:58ch}
.small{font-size:var(--text-sm);line-height:1.5}
.muted{color:var(--muted)}
.mono{font-family:var(--font-mono)}

.eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--font-display);font-size:var(--text-xs);font-weight:600;
  letter-spacing:0.08em;text-transform:uppercase;color:var(--muted);margin-bottom:16px;
}
/* The dot is the reference's eyebrow marker: one accent per label, no
   second accent anywhere near it. */
.eyebrow i{width:6px;height:6px;border-radius:50%;background:var(--accent);display:inline-block}

/* ════════════════════════════════════════════════════════════════
   4 · ACTIONS
   One primary per viewport. The hero owns the blue; the closing band
   repeats it once at the end of the scroll. The nav carries the same
   destination as a ghost, so the first screen never holds two rivals
   for the same action.
   ════════════════════════════════════════════════════════════════ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:44px;padding:12px 18px;border-radius:var(--radius-sm);
  font-family:var(--font-display);font-size:15px;font-weight:600;line-height:1;
  border:1px solid transparent;cursor:pointer;white-space:nowrap;
  transition:background-color var(--motion-fast) var(--ease-standard),
             border-color var(--motion-fast) var(--ease-standard),
             color var(--motion-fast) var(--ease-standard),
             transform var(--motion-fast) var(--ease-standard);
}
.btn svg{flex:0 0 auto}
.btn:active{transform:scale(.98);transition-duration:var(--motion-press)}
.btn-primary{background:var(--accent);color:var(--accent-on);border-color:var(--accent)}
.btn-primary:hover{background:var(--accent-hover);border-color:var(--accent-hover)}
.btn-primary:active{background:var(--accent-active);border-color:var(--accent-active)}
.btn-primary:focus-visible{outline:2px solid var(--accent-on);outline-offset:-4px;box-shadow:0 0 0 2px var(--accent)}
.btn-ghost{background:var(--bg);color:var(--fg);border-color:var(--border)}
.btn-ghost:hover{background:var(--surface);border-color:color-mix(in oklab, var(--border), black 16%)}
.btn-sm{padding:8px 14px;font-size:14px}

/* A text link steps to the darker accent: it has to clear 4.5:1 on the
   warm sections too, not only on white. */
.tlink{
  display:inline-flex;align-items:center;gap:6px;
  font-size:14px;font-weight:600;color:var(--accent-hover);
  border-bottom:1px solid transparent;padding-bottom:1px;min-height:24px;
  transition:border-color var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard);
}
.tlink svg{width:14px;height:14px}
.tlink:hover{border-bottom-color:currentColor;color:var(--accent-active)}

.pill{
  display:inline-flex;align-items:center;gap:6px;
  font-family:var(--font-display);font-size:var(--text-xs);font-weight:600;letter-spacing:0.02em;
  padding:5px 11px;border-radius:var(--radius-pill);
  background:var(--surface);color:var(--muted);border:1px solid var(--border);
}

/* ════════════════════════════════════════════════════════════════
   5 · NAV — clean horizontal rule on white, not sticky
   ════════════════════════════════════════════════════════════════ */
.nav{border-bottom:1px solid var(--border-soft);background:var(--bg);position:relative;z-index:20}
.nav__in{display:flex;align-items:center;justify-content:space-between;gap:24px;min-height:64px}
.nav__left{display:flex;align-items:center;gap:28px;min-width:0}
.brand{display:inline-flex;align-items:center;gap:10px;flex-shrink:0}
.brand svg.mark{width:28px;height:28px}
.brand__word{font-family:var(--font-display);font-size:16px;font-weight:700;letter-spacing:-0.02em;color:var(--fg)}
.nav__links{display:flex;align-items:center;gap:22px}
.nav__links a{
  display:inline-flex;align-items:center;min-height:44px;
  font-family:var(--font-display);font-size:14px;font-weight:500;color:var(--muted);
  transition:color var(--motion-fast) var(--ease-standard);
}
.nav__links a:hover{color:var(--fg)}
.nav__end{display:flex;align-items:center;gap:12px;flex-shrink:0}
.nav__store{min-height:44px}

/* ════════════════════════════════════════════════════════════════
   6 · HERO — centred copy, the window below it
   ════════════════════════════════════════════════════════════════ */
.hero{padding:72px 0 32px;text-align:center}
.hero__inner{max-width:880px;margin:0 auto}
.hero h1{text-wrap:balance}
.hero .lead{margin:18px auto 0}
.hero__actions{margin-top:28px;display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap}

.mock-wrap{margin-top:40px}
/* The window spans the page column: it already sits inside .container,
   so it inherits the same measure and gutters as every section below. */
.mock-caption{margin-top:12px;font-size:var(--text-sm);color:var(--muted);text-align:center}

/* ════════════════════════════════════════════════════════════════
   7 · THE MOCKUP — the app itself
   Every colour in here is a scoped token copy of CSVita's own chrome,
   so the window cannot drift from the app it pictures. Only the frame
   is the landing page's: a 12px radius and the Notion shadow stack.
   ════════════════════════════════════════════════════════════════ */
.mock{
  --m-bg:#ffffff;
  --m-surface:#f6f8fa;
  --m-fg:#1f2328;
  --m-muted:#656d76;
  --m-line:#d0d7de;
  --m-line-soft:#d8dee4;
  --m-accent:#0969da;
  --m-accent-hover:#0550ae;
  --m-subtle:#ddf4ff;
  --m-success:#1a7f37;
  --m-danger:#cf222e;
  --m-hair-check:#868e96;
  --m-mono:ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  background:var(--m-bg);border:1px solid var(--border);border-radius:var(--radius-lg);
  overflow:hidden;text-align:left;box-shadow:var(--elev-raised);
  font-family:var(--font-body);color:var(--m-fg);
}

/* titlebar + tabs */
.mock-bar{
  display:flex;align-items:stretch;height:36px;
  background:var(--m-surface);border-bottom:1px solid var(--m-line);
}
.mock-brand{
  display:flex;align-items:center;gap:7px;padding:0 12px 0 10px;
  border-right:1px solid var(--m-line);flex-shrink:0;color:var(--m-fg);
}
.mock-brand svg{width:16px;height:16px}
.mock-brand span{font-size:12px;font-weight:600;letter-spacing:-.01em}
.mock-tabs{display:flex;align-items:stretch;flex:1 1 auto;min-width:0;overflow:hidden}
.m-tab{
  position:relative;display:flex;align-items:center;gap:7px;
  padding:0 10px;font-size:12px;font-weight:600;letter-spacing:-.01em;
  color:var(--m-muted);background:var(--m-surface);
  border-right:1px solid var(--m-line);flex-shrink:0;max-width:150px;
  transition:background-color var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard);
}
.m-tab span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-tab:hover{background:color-mix(in oklab, var(--m-surface), white 55%);color:var(--m-fg)}
.m-tab[aria-selected="true"]{background:var(--m-bg);color:var(--m-fg)}
.m-tab[aria-selected="true"]::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--m-accent);
}
.m-tab:focus-visible{outline:2px solid var(--m-accent);outline-offset:-3px;z-index:2}
.m-dot{width:7px;height:7px;border-radius:50%;background:var(--dot,var(--m-muted));flex-shrink:0}
.mock-newtab{
  width:34px;display:grid;place-items:center;color:var(--m-muted);flex-shrink:0;
  border-right:1px solid var(--m-line);
  transition:background-color var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard);
}
.mock-newtab:hover{background:var(--m-bg);color:var(--m-fg)}
.mock-newtab svg{width:12px;height:12px}
.mock-win{display:flex;align-items:stretch;margin-inline-start:auto;flex-shrink:0}
.mock-win i{
  width:40px;display:grid;place-items:center;color:var(--m-muted);
  transition:background-color var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard);
}
.mock-win i svg{width:10px;height:10px}
.mock-win i:hover{background:var(--m-bg);color:var(--m-fg)}
.mock-win i.close:hover{background:var(--m-danger);color:var(--m-bg)}

/* query bar */
.mock-query{
  display:flex;align-items:center;gap:9px;height:38px;padding:0 10px;
  border-bottom:1px solid var(--m-line-soft);background:var(--m-bg);
}
.mock-query .lens{width:13px;height:13px;color:var(--m-muted);flex-shrink:0}
.mock-query input{
  flex:1 1 auto;min-width:0;height:26px;border:1px solid transparent;border-radius:5px;
  background:transparent;color:var(--m-fg);font:inherit;font-size:12.5px;padding:0 4px;
}
.mock-query input::placeholder{color:var(--m-muted)}
.mock-query input:hover{background:var(--m-surface)}
.mock-query input:focus{outline:none;background:var(--m-bg);border-color:var(--m-accent);box-shadow:0 0 0 2px var(--m-subtle)}
.m-kbd{
  font-family:var(--m-mono);font-size:10.5px;line-height:1;color:var(--m-muted);
  border:1px solid var(--m-line);border-bottom-width:2px;border-radius:4px;
  padding:3px 5px;background:var(--m-bg);flex-shrink:0;
}

/* toolbar */
.mock-toolbar{
  display:flex;align-items:center;gap:5px;height:38px;padding:0 10px;
  border-bottom:1px solid var(--m-line);background:var(--m-bg);
}
/* Toolbar chips are bordered at rest, exactly as the app's own .chip is
   (1px solid var(--border) on a white fill). Without it four 12px labels
   floated on the toolbar rule and read as loose text, not controls. */
.m-tool{
  display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 9px;
  border:1px solid var(--m-line);border-radius:5px;background:var(--m-bg);
  font-size:12px;font-weight:500;color:var(--m-fg);
  transition:background-color var(--motion-fast) var(--ease-standard),
             border-color var(--motion-fast) var(--ease-standard),
             color var(--motion-fast) var(--ease-standard);
}
.m-tool svg{width:12px;height:12px;color:var(--m-muted)}
/* Hover steps the edge darker rather than repeating the rest colour, so the
   state stays visible now that the border is always drawn. Same formula as
   the app's own .chip:hover (--border, black 18%). */
.m-tool:hover{
  background:var(--m-surface);
  border-color:color-mix(in oklab, var(--m-line), black 18%);
}
/* Open/on state mirrors the app's own .chip.has-value: full accent border,
   accent-subtle fill, accent text. */
.m-tool[aria-expanded="true"],.m-tool.is-on{
  background:var(--m-subtle);border-color:var(--m-accent);color:var(--m-accent-hover);
}
.m-tool[aria-expanded="true"] svg,.m-tool.is-on svg{color:var(--m-accent)}
.m-tool:focus-visible{outline:2px solid var(--m-accent);outline-offset:1px}

/* filter bar */
.mock-filters{
  display:none;align-items:center;gap:7px;min-height:38px;padding:6px 10px;
  background:var(--m-surface);border-bottom:1px solid var(--m-line);flex-wrap:wrap;
}
.mock-filters[data-open="true"]{display:flex}
.m-where{
  font-family:var(--m-mono);font-size:9.5px;font-weight:600;letter-spacing:.12em;
  color:var(--m-muted);text-transform:uppercase;padding-inline:2px 4px;
}
.m-cond{
  display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 6px 0 8px;
  border:1px solid var(--m-line);border-radius:5px;background:var(--m-bg);
  font-size:11px;color:var(--m-muted);white-space:nowrap;
}
.m-cond b{color:var(--m-fg);font-weight:600}
.m-cond .op{color:var(--m-muted)}
.m-cond .x{
  width:16px;height:16px;display:grid;place-items:center;border-radius:3px;color:var(--m-muted);
  font-size:12px;line-height:1;
}
.m-cond .x:hover{background:var(--m-surface);color:var(--m-fg)}
.m-add{
  display:inline-flex;align-items:center;height:24px;padding:0 6px;border-radius:4px;
  font-size:11px;font-weight:600;color:var(--m-accent-hover);
}
.m-add:hover{background:var(--m-subtle)}
.m-clear{
  margin-inline-start:auto;font-size:11px;color:var(--m-muted);font-weight:500;
  padding:0 6px;height:24px;border-radius:4px;
}
.m-clear:hover{background:var(--m-bg);color:var(--m-fg)}

/* grid */
.mock-grid{max-height:336px;overflow:auto;background:var(--m-bg);position:relative}
.mock-grid::-webkit-scrollbar{width:10px;height:10px}
.mock-grid::-webkit-scrollbar-thumb{background:var(--m-line);border-radius:6px;border:2px solid var(--m-bg)}
.mock-grid table{width:100%;table-layout:fixed;border-collapse:separate;border-spacing:0}
.mock-grid thead th{
  position:sticky;top:0;z-index:2;height:30px;background:var(--m-surface);
  border-bottom:1px solid var(--m-line);border-right:1px solid var(--m-line-soft);
  font-size:11.5px;font-weight:600;text-align:left;color:var(--m-fg);padding:0;
  white-space:nowrap;
}
.mock-grid thead th:last-child{border-right:0}
.th-btn{
  display:flex;align-items:center;gap:5px;width:100%;height:100%;padding:0 9px;
  font-size:11.5px;font-weight:600;color:var(--m-fg);
  transition:background-color var(--motion-fast) var(--ease-standard);
}
.th-btn:hover{background:color-mix(in oklab, var(--m-surface), white 40%)}
.th-btn .caret{width:10px;height:10px;color:var(--m-muted);flex-shrink:0}
.th-btn[data-dir] .caret{color:var(--m-accent-hover)}
.th-btn span{overflow:hidden;text-overflow:ellipsis}
.mock-grid tbody td{
  height:30px;padding:0 9px;border-bottom:1px solid var(--m-line-soft);
  border-right:1px solid var(--m-line-soft);font-size:12px;color:var(--m-fg);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:var(--m-bg);
}
.mock-grid tbody td:last-child{border-right:0}
.mock-grid tbody tr:hover td{background:color-mix(in oklab, var(--m-surface), white 55%)}
.mock-grid tbody tr.sel td{background:var(--m-subtle)}
.mock-grid tbody tr.sel td:first-child{color:var(--m-accent-hover);font-weight:700}
td.c-id{font-family:var(--m-mono);font-size:10.5px;color:var(--m-muted);padding:0}
td.c-num{text-align:right;font-family:var(--m-mono);font-size:11.5px}
td.c-check{text-align:center;padding:0}
td.c-long{color:var(--m-muted)}

.m-pill{
  display:inline-flex;align-items:center;gap:6px;padding:2px 9px;border-radius:9999px;
  font-size:11px;font-weight:600;border:1px solid transparent;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;line-height:1.5;
}
.m-pill i{width:6px;height:6px;border-radius:50%;flex-shrink:0}
.m-check{
  width:16px;height:16px;border-radius:4px;border:1.5px solid var(--m-hair-check);background:var(--m-bg);
  display:inline-grid;place-items:center;color:var(--m-bg);vertical-align:middle;
  transition:background-color var(--motion-fast) var(--ease-standard), border-color var(--motion-fast) var(--ease-standard);
}
.m-check svg{
  width:11px;height:11px;opacity:0;transform:scale(var(--tick-scale));
  transition:opacity var(--motion-fast) var(--ease-standard),
             transform var(--motion-base) var(--ease-out);
}
.m-check.on{background:var(--m-accent);border-color:var(--m-accent)}
.m-check.on svg{opacity:1;transform:scale(1)}
.m-check:hover{border-color:color-mix(in oklab, var(--m-line), var(--m-fg) 45%)}
.m-check.on:hover{background:var(--m-accent-hover);border-color:var(--m-accent-hover)}
.m-check:focus-visible{outline:2px solid var(--m-accent);outline-offset:2px}
.m-rowno{
  display:block;width:100%;height:29px;line-height:29px;padding:0 9px;text-align:left;
  font-family:var(--m-mono);font-size:10.5px;color:var(--m-muted);
  transition:color var(--motion-fast) var(--ease-standard);
}
.m-rowno:hover{color:var(--m-fg)}
.m-rowno:focus-visible{outline:2px solid var(--m-accent);outline-offset:-2px}
tr.sel .m-rowno{color:var(--m-accent-hover);font-weight:700}
.m-empty{padding:28px 10px;text-align:center;font-size:12px;color:var(--m-muted)}

/* status bar */
.mock-status{
  display:flex;align-items:center;gap:12px;height:32px;padding:0 11px;
  background:var(--m-surface);border-top:1px solid var(--m-line);
  font-family:var(--m-mono);font-size:10.5px;color:var(--m-muted);white-space:nowrap;overflow:hidden;
}
.mock-status .saved{display:inline-flex;align-items:center;gap:6px;color:var(--m-fg)}
.mock-status .saved i{width:6px;height:6px;border-radius:50%;background:var(--m-success);flex-shrink:0}
.mock-status .sep{width:1px;height:12px;background:var(--m-line);flex-shrink:0}
.mock-status b{color:var(--m-fg);font-weight:600}
.mock-status .end{margin-inline-start:auto;display:flex;align-items:center;gap:8px}
.mock-status .st-btn{
  height:22px;padding:0 7px;border-radius:4px;border:1px solid var(--m-line);
  background:var(--m-bg);color:var(--m-fg);font-family:var(--font-body);font-size:11px;font-weight:500;
  display:inline-flex;align-items:center;
}
.mock-status .st-btn:hover{background:var(--m-surface)}
.mock-status .st-primary{
  background:var(--m-success);border-color:var(--m-success);color:var(--m-bg);font-weight:600;
}
.mock-status .st-primary:hover{background:color-mix(in oklab, var(--m-success), black 12%)}


/* ════════════════════════════════════════════════════════════════
   9 · SECTIONS
   White alternates with warm white; no hard section borders, only the
   hairline that separates a new band and 80px of air.
   ════════════════════════════════════════════════════════════════ */
.section{padding:var(--section-y-desktop) 0;border-top:1px solid var(--border-soft)}
.section--warm{background:var(--surface);border-top:1px solid var(--border-soft)}
.section__head{max-width:720px}
.section__head .lead{margin-top:14px}
.section__head--wide{max-width:820px}

/* ── proof strip: the product's own numbers, not marketing ones ── */
.proof{
  display:flex;align-items:center;justify-content:center;gap:10px 18px;flex-wrap:wrap;
  font-family:var(--font-mono);font-size:12px;color:var(--muted);
}
.proof em{font-style:normal;color:var(--fg);font-weight:600}
.proof .dot{width:3px;height:3px;border-radius:50%;background:var(--border);display:inline-block}

/* ── card grid — the whisper-bordered card, Notion's standard ──── */
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px}
.card{
  background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-lg);
  padding:24px 22px 22px;box-shadow:var(--elev-raised);
  display:flex;flex-direction:column;gap:0;min-width:0;
}
.card h3{font-size:16px;line-height:1.35;letter-spacing:-0.012em;font-weight:600;margin-bottom:8px}
.card p{font-size:14px;line-height:1.55;color:var(--muted)}
.card__vz{
  margin-top:18px;background:var(--surface);border:1px solid var(--border-soft);
  border-radius:var(--radius-md);padding:14px;display:flex;flex-direction:column;
  justify-content:center;gap:10px;min-height:150px;
}
.card__vz .viz-where{
  font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);
}
.viz-row{display:flex;align-items:center;gap:10px;min-height:24px}
.viz-k{font-size:12px;color:var(--muted);width:62px;flex-shrink:0}
.viz-v{font-size:12.5px;font-weight:600;color:var(--fg);font-family:var(--font-mono)}
.viz-cond{
  display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 9px;
  border:1px solid var(--border);border-radius:5px;background:var(--bg);
  font-size:11px;color:var(--muted);white-space:nowrap;
}
.viz-cond b{color:var(--fg);font-weight:600}
.viz-cond .op{color:var(--muted)}
.viz-cond .x{color:var(--meta);font-size:12px}
.viz-add{font-size:11px;font-weight:600;color:var(--accent-hover)}
.viz-search{
  display:flex;align-items:center;gap:8px;height:34px;padding:0 10px;
  border:1px solid var(--border);border-radius:6px;background:var(--bg);
}
.viz-search svg{width:12px;height:12px;color:var(--muted);flex-shrink:0}
.viz-search .q{font-size:12px;color:var(--fg);flex:1 1 auto}
.viz-search .k{font-family:var(--font-mono);font-size:10px;color:var(--muted)}
.viz-count{font-family:var(--font-mono);font-size:10.5px;color:var(--muted)}
.viz-result{
  display:flex;align-items:baseline;gap:8px;padding-top:7px;
  border-top:1px solid var(--border-soft);font-size:12px;min-width:0;
}
.viz-result:first-of-type{border-top:0;padding-top:0}
.viz-result .n{color:var(--fg);flex-shrink:0}
.viz-result .e{font-family:var(--font-mono);font-size:10.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis}

/* ── split: copy beside a card ─────────────────────────────────── */
.split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.02fr);gap:64px;align-items:center}
.bullets{margin-top:26px;display:grid;gap:12px}
.bullet{display:flex;gap:12px;align-items:flex-start}
.bullet .tick{
  width:20px;height:20px;border-radius:50%;background:var(--bg);
  border:1px solid var(--border);color:var(--success);
  display:grid;place-items:center;flex-shrink:0;margin-top:1px;
}
.bullet .tick svg{width:11px;height:11px}
.bullet p{font-size:15px;line-height:1.5;color:var(--muted)}

/* ── the file card: what is actually on disk ──────────────────── */
.file-card{
  background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-lg);
  overflow:hidden;box-shadow:var(--elev-raised);
}
.fc-head{display:flex;align-items:center;gap:9px;padding:16px 18px}
.fc-head svg{width:16px;height:16px;color:var(--muted);flex-shrink:0}
.fc-head .name{font-size:13px;font-weight:600;color:var(--fg);font-family:var(--font-mono)}
.fc-head .sp{margin-inline-start:auto}
.fc-saved{
  display:inline-flex;align-items:center;gap:6px;font-size:11.5px;
  color:var(--muted);font-family:var(--font-mono);
}
.fc-saved i{width:7px;height:7px;border-radius:50%;background:var(--success)}
.fc-rows{border-top:1px solid var(--border-soft)}
.fc-row{
  font-family:var(--font-mono);font-size:12px;color:var(--fg-2);
  padding:9px 18px;border-bottom:1px solid var(--border-soft);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.fc-row.head{color:var(--muted);font-weight:600;background:var(--surface)}
.fc-foot{
  display:flex;gap:14px;flex-wrap:wrap;padding:12px 18px;background:var(--surface);
  font-family:var(--font-mono);font-size:11px;color:var(--muted);
}
.fc-foot b{color:var(--fg-2);font-weight:600}

/* ── feature grid ──────────────────────────────────────────────── */
.feat-head{display:flex;align-items:flex-end;justify-content:space-between;gap:32px;flex-wrap:wrap}
.feat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px}
.feat{
  background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-lg);
  padding:22px 20px 20px;display:flex;flex-direction:column;min-width:0;
  box-shadow:var(--elev-raised);
  transition:border-color var(--motion-fast) var(--ease-standard),
             box-shadow var(--motion-fast) var(--ease-standard);
}
.feat:hover{border-color:color-mix(in oklab, var(--border), black 12%)}
/* ── feature illustrations ──────────────────────────────────────
   One 16:9 monochrome plate per card, drawn in the card's own ink over a
   whisper grid. Every shape is authored in its resting state, so a browser
   with scripting off — or a reader who asked for reduced motion — sees the
   finished drawing rather than an empty frame: each animation only runs
   forward from a state the markup never rests in, and it runs once. */
.feat-art{
  aspect-ratio:16/9;border:1px solid var(--border);border-radius:var(--radius-md);
  background:var(--surface);overflow:hidden;margin-bottom:16px;color:var(--fg-2);
  /* The card is a flex column, so the plate must not be allowed to shrink in
     the main axis — that would break the 16:9 box the drawing is measured
     against. */
  flex:0 0 auto;
}
.feat-art svg{display:block;width:100%;height:100%}
/* Type inside the plate is sized in CSS rather than by per-element
   attributes. These are user units, and the 320-unit viewBox lands almost
   exactly 1:1 on the plate — a three-column grid on a 1440 viewport gives a
   334px plate, a scale of 1.04 — so a unit is very nearly a pixel and the
   labels below hold ~11.5px and ~10.4px across the desktop range. Four
   levels replace the eleven near-identical sizes the attributes carried. */
.feat-art text{font-family:var(--font-body);fill:currentColor;stroke:none;font-size:11px}
.feat-art .m{font-family:var(--font-mono);fill-opacity:.8;font-size:11px}
.feat-art .u{font-family:var(--font-mono);fill-opacity:.55;font-size:10px}
.feat-art .t{font-family:var(--font-body);fill-opacity:.62;font-size:11px}
.feat-art .g{stroke-opacity:.2;stroke-width:.9}
.feat-art .cut{fill:var(--surface)}
.feat-art .f{fill:currentColor;stroke:none;fill-opacity:.07}
.feat-art .a{transform-box:fill-box;transform-origin:center}
/* Cards land before their drawing starts, so the sequence reads as the
   illustration arriving rather than as two animations competing. */
.feat-art{--art:180ms}

/* The illustration's stagger comes from the card it sits in: cards reveal
   one at a time as they are scrolled to, so a drawing only ever plays on
   screen — never off the bottom of the viewport where it would be spent
   before it was seen. --art stays overridable per card if a row ever needs
   to move as a unit. */
.js .feat-art.is-play .a{
  animation-name:var(--anim);
  animation-duration:var(--dur,.55s);
  animation-timing-function:var(--ease-out);
  animation-delay:calc(var(--art,0ms) + var(--d,0ms));
  animation-fill-mode:backwards;
  animation-iteration-count:var(--rep,1);
}

/* Each keyframe declares only its start where the end should be the
   element's own markup state — that is what keeps the drawing settling
   exactly where it was authored instead of snapping back to a default.
   `fa-in`/`fa-x`/`fa-pop` reveal a shape that is already in place; the
   rest change a property whose resting value lives in the markup. */
@keyframes fa-in{from{opacity:0;transform:translateY(5px)}}
@keyframes fa-x{from{opacity:0;transform:translateX(-10px)}}
@keyframes fa-pop{from{opacity:0;transform:scale(.74)}}
@keyframes fa-down{from{transform:translateY(0)}}
@keyframes fa-dash{from{stroke-dashoffset:var(--len,20)}}
@keyframes fa-key{from{fill-opacity:.45}}
@keyframes fa-caret{0%,100%{opacity:1}40%,60%{opacity:0}}
@keyframes fa-flash{from{fill-opacity:.34}}
@keyframes fa-prose{0%,26%{opacity:1}32%,64%{opacity:0}70%,100%{opacity:1}}
@keyframes fa-raw{0%,26%{opacity:0}32%,64%{opacity:1}70%,100%{opacity:0}}
@keyframes fa-tabs{0%,26%{transform:translateX(0)}34%,58%{transform:translateX(49px)}66%,100%{transform:translateX(0)}}

@media (prefers-reduced-motion:reduce){
  .js .feat-art.is-play .a{animation:none}
}
.feat h3{font-size:16px;line-height:1.35;letter-spacing:-0.012em;font-weight:600;margin-bottom:8px}
/* Card body sits at ~60 characters in a fixed column, where the last line can
   otherwise strand a single word. `pretty` is a progressive enhancement —
   browsers that support it rebalance the final two lines; the copy below is
   written short enough to read well without it. */
.feat p{font-size:14px;line-height:1.55;color:var(--muted);text-wrap:pretty}

/* ── stay band: the negative list beside one action card ──────── */
.stay-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:28px;align-items:start;margin-top:32px}
.neg-list{
  display:grid;border:1px solid var(--border);border-radius:var(--radius-lg);
  overflow:hidden;background:var(--bg);box-shadow:var(--elev-raised);
}
.neg-list li{
  display:flex;align-items:center;gap:12px;padding:15px 18px;
  border-bottom:1px solid var(--border-soft);font-size:15px;color:var(--fg);
}
.neg-list li:last-child{border-bottom:0}
.neg-list li s{
  width:22px;height:22px;border-radius:50%;background:var(--surface);
  border:1px solid var(--border);display:grid;place-items:center;flex:0 0 auto;
  color:var(--muted);font-size:12px;text-decoration:none;
}
.neg-list li span{color:var(--muted)}
.neg-list li strong{color:var(--fg);font-weight:600}
.stay-card{
  background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-lg);
  padding:24px;box-shadow:var(--elev-raised);
}
.stay-card h3{margin-bottom:8px}
.stay-card p{font-size:14px;line-height:1.6;color:var(--muted)}

/* ── faq ───────────────────────────────────────────────────────── */
.faq{display:grid;grid-template-columns:minmax(0,380px) minmax(0,1fr);gap:64px;align-items:start}
.faq-copy h2{margin-top:14px}
.faq-copy p{margin-top:16px;max-width:34ch}
.faq-copy .tlink{margin-top:22px}
.faq-list{border-top:1px solid var(--border)}
.faq-item{border-bottom:1px solid var(--border)}
.faq-item summary{
  display:flex;align-items:center;gap:20px;padding:22px 4px;cursor:pointer;
  list-style:none;min-height:64px;
}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary .q{
  font-family:var(--font-display);font-size:17px;font-weight:600;
  letter-spacing:-0.01em;color:var(--fg);flex:1 1 auto;min-width:0;
}
.faq-item summary .pm{
  width:16px;height:16px;flex-shrink:0;color:var(--muted);position:relative;
}
.faq-item summary .pm::before,
.faq-item summary .pm::after{
  content:"";position:absolute;background:currentColor;border-radius:1px;
  transition:transform var(--motion-fast) var(--ease-standard), opacity var(--motion-fast) var(--ease-standard);
}
.faq-item summary .pm::before{left:0;right:0;top:7px;height:2px}
.faq-item summary .pm::after{top:0;bottom:0;left:7px;width:2px}
.faq-item[open] summary .pm::after{transform:scaleY(0);opacity:0}
.faq-item summary:hover .q{color:var(--accent-hover)}
.faq-item summary:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:4px}
.faq-a{padding:0 44px 24px 4px;font-size:15px;line-height:1.62;color:var(--muted)}

/* ════════════════════════════════════════════════════════════════
   10 · CLOSING BAND + FOOTER
   The band is the page's one repeated action, centred, on white — the
   same shape as the hero so the page closes the way it opened.
   ════════════════════════════════════════════════════════════════ */
/* The band closes the page on white, the way it opened: FAQ above it is
   warm, so a warm band here would merge the two into one 1,100px field
   with a rule running through it. */
.cta-band{padding:64px 0;border-top:1px solid var(--border-soft);background:var(--bg);text-align:center}
.cta-band h2{max-width:720px;margin:0 auto}
.cta-band p{max-width:520px;margin:14px auto 0;color:var(--muted);font-size:16px;line-height:1.5}
.cta-band__actions{margin-top:26px;display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap}
.cta-band__meta{
  margin-top:14px;font-family:var(--font-mono);font-size:12px;color:var(--muted);
  letter-spacing:0.02em;display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap;
}
.cta-band__meta .dot{width:3px;height:3px;border-radius:50%;background:var(--border);display:inline-block}

.footer{border-top:1px solid var(--border);padding:20px 0 28px;background:var(--bg)}
.footer__row{
  display:flex;align-items:center;justify-content:space-between;gap:16px 24px;flex-wrap:wrap;
  font-size:13px;color:var(--muted);
}
.footer__brand{display:flex;align-items:center;gap:10px;color:var(--fg);font-weight:600;min-width:0}
.footer__brand svg.mark{width:22px;height:22px;flex-shrink:0}
.footer__brand .wordmark{font-family:var(--font-display);font-size:15px;font-weight:700;letter-spacing:-0.02em}
.footer__brand .tag{font-weight:400;font-size:13px;color:var(--muted)}
.footer__links{display:flex;align-items:center;gap:20px;flex-wrap:wrap}
.footer__links a{
  display:inline-flex;align-items:center;min-height:32px;font-size:13px;color:var(--muted);
  transition:color var(--motion-fast) var(--ease-standard);
}
.footer__links a:hover{color:var(--fg);text-decoration:underline;text-underline-offset:3px}
.footer__meta{font-family:var(--font-mono);font-size:12px;color:var(--muted)}


/* ════════════════════════════════════════════════════════════════
   11 · MOTION
   One vocabulary, borrowed from the app's own 0.8.15 note: a surface
   arrives 200ms on an ease-out curve after a short rise, a state step
   holds 150ms on --ease-standard, and a press is over in 90ms.

   Nothing animates layout. Every entrance is transform plus opacity,
   and every displacement comes from a token, which is what lets the
   reduced-motion block zero them in one place and keep the crossfade.
   ════════════════════════════════════════════════════════════════ */
@keyframes rise-in{
  from{opacity:0;transform:translate3d(0,var(--motion-rise),0)}
  to{opacity:1;transform:none}
}
@keyframes tab-bar{
  from{transform:scaleX(.5);opacity:0}
  to{transform:scaleX(1);opacity:1}
}
@keyframes ans-in{
  from{opacity:0;transform:translate3d(0,calc(-1 * var(--motion-rise)),0)}
  to{opacity:1;transform:none}
}

/* Content arrival. The hidden state exists only under .js, so a browser
   with scripting off — or one where the observer never runs — shows the
   page rather than an empty column. */
.js [data-reveal]{opacity:0;transform:translate3d(0,var(--motion-rise-lg),0)}
.js [data-reveal].is-in{
  opacity:1;transform:none;
  transition:opacity var(--motion-open) var(--ease-out),
             transform var(--motion-open) var(--ease-out);
}

/* Groups stagger, but only three steps deep: past that the last card
   lands so long after the first that the row reads as broken rather
   than choreographed. Items four and beyond share the third step. */
.js [data-reveal-group] > *{opacity:0;transform:translate3d(0,var(--motion-rise-lg),0)}
.js [data-reveal-group].is-in > *{
  opacity:1;transform:none;
  transition:opacity var(--motion-open) var(--ease-out),
             transform var(--motion-open) var(--ease-out);
}
.js [data-reveal-group].is-in > *:nth-child(2){transition-delay:var(--stagger)}
.js [data-reveal-group].is-in > *:nth-child(3){transition-delay:calc(2 * var(--stagger))}
.js [data-reveal-group].is-in > *:nth-child(n+4){transition-delay:calc(3 * var(--stagger))}

/* ── arrival at the top of the page ────────────────────────────
   The hero is already the first thing read, so its entrance is an
   acknowledgement rather than a reveal: 200ms each, three steps for the
   copy, then the window settles in behind it. */
.js .hero__inner > *{animation:rise-in var(--motion-open) var(--ease-out) backwards}
.js .hero__inner > *:nth-child(2){animation-delay:var(--stagger)}
.js .hero__inner > *:nth-child(3){animation-delay:calc(2 * var(--stagger))}
.js .mock-wrap .mock{animation:rise-in 240ms var(--ease-out) calc(2 * var(--stagger)) backwards}

/* ── the demo window's own state changes ───────────────────────
   The app's behaviours, mirrored: the filter bar takes its box in one
   step and fades its contents in (0.8.15), the tab underline draws
   rather than appears, a checked box grows its tick, and a picked row
   steps into its tint instead of snapping. */
.mock-filters.is-opening > *{animation:rise-in var(--motion-open) var(--ease-out) backwards}
.mock-filters.is-opening > *:nth-child(2){animation-delay:var(--stagger-tight)}
.mock-filters.is-opening > *:nth-child(3){animation-delay:calc(2 * var(--stagger-tight))}
.mock-filters.is-opening > *:nth-child(4){animation-delay:calc(3 * var(--stagger-tight))}
.mock-filters.is-opening > *:nth-child(n+5){animation-delay:calc(4 * var(--stagger-tight))}

.m-tab[aria-selected="true"]::after{
  transform-origin:left center;
  animation:tab-bar var(--motion-open) var(--ease-out) backwards;
}

/* Row background is the one property worth transitioning inside the
   grid: hover and selection both move it, and the picked row is toggled
   in place rather than re-rendered, so the step is visible. */
.mock-grid tbody td{transition:background-color var(--motion-fast) var(--ease-standard)}

/* A sheet arriving is a new document — its rows fade up once, capped at
   five steps so a ten-row file does not turn into a waterfall. */
.mock-grid.swap tbody tr{animation:rise-in 180ms var(--ease-out) backwards}
.mock-grid.swap tbody tr:nth-child(2){animation-delay:var(--stagger-tight)}
.mock-grid.swap tbody tr:nth-child(3){animation-delay:calc(2 * var(--stagger-tight))}
.mock-grid.swap tbody tr:nth-child(4){animation-delay:calc(3 * var(--stagger-tight))}
.mock-grid.swap tbody tr:nth-child(n+5){animation-delay:calc(4 * var(--stagger-tight))}

/* An opened answer comes down out of its question. */
.faq-item[open] .faq-a{animation:ans-in var(--motion-open) var(--ease-out) backwards}

/* The filter bar is the one surface here that closes without an exit
   phase, deliberately: its removal collapses a row and moves the grid
   up, and a fade would only postpone that jump. The app reached the
   same conclusion for actions that discard content (0.8.15). */

/* ════════════════════════════════════════════════════════════════
   12 · RESPONSIVE
   ════════════════════════════════════════════════════════════════ */
@media (max-width:1080px){
  .grid-3{gap:14px}
  .split,.faq{gap:48px}
}
@media (max-width:1024px){
  .section{padding:var(--section-y-tablet) 0}
  .grid-3{grid-template-columns:1fr 1fr}
  .feat-grid{grid-template-columns:1fr 1fr}
  .split,.faq{grid-template-columns:1fr;gap:40px}
  .nav__links{display:none}
  .stay-grid{grid-template-columns:1fr}
}
@media (max-width:860px){
  .mock-grid{max-height:300px}
  .mock-grid table{min-width:720px}
  .hero{padding:56px 0 24px}
}
@media (max-width:720px){
  .container{padding:0 var(--container-gutter-tablet)}
  .section{padding:var(--section-y-phone) 0}
  .grid-3{grid-template-columns:1fr}
  .feat-grid{grid-template-columns:1fr}
  .hero{padding:40px 0 20px}
  .hero__actions .btn{width:100%}
  .cta-band__actions .btn{width:100%}
  /* "Get it from Microsoft Store" is a long label and .btn sets nowrap.
     Once these buttons are full-width they can no longer grow sideways,
     so the label wraps instead of clipping out of its own box. */
  .hero__actions .btn,.cta-band__actions .btn{
    white-space:normal;text-align:center;line-height:1.25;
  }
  .faq-a{padding-right:8px}
  .faq-item summary .q{font-size:16px}
  .footer__row{flex-direction:column;align-items:flex-start;gap:12px}
  .nav__in{min-height:60px;gap:12px}
}
@media (max-width:520px){
  .container{padding:0 var(--container-gutter-phone)}
  h1{font-size:clamp(34px,9.4vw,44px)}
  .mock-status .s-hide{display:none}
  .mock-brand span{display:none}
  .footer__brand .tag{display:none}
}

/* Reducing motion removes displacement, not feedback. The app took the
   same position in 0.8.15: it used to strip every transition, "which
   took away the only signal that anything had changed." So the rise
   tokens go to zero — every entrance becomes the crossfade it was
   wrapped around — and the stagger collapses so nothing arrives late. */
@media (prefers-reduced-motion:reduce){
  :root{
    --motion-rise:0px;
    --motion-rise-lg:0px;
    --tick-scale:1;
    --stagger:0ms;
    --stagger-tight:0ms;
  }
  *,*::before,*::after{
    animation-iteration-count:1 !important;
    scroll-behavior:auto !important;
  }
  .btn:active{transform:none}
  .m-tab[aria-selected="true"]::after{animation:none}
}

/* Print never runs the observer, so every reveal target would go to
   paper at opacity 0. The page returns to its resting state instead. */
@media print{
  .js [data-reveal],
  .js [data-reveal-group] > *{opacity:1;transform:none}
  .js .hero__inner > *,.js .mock{animation:none}
}