
/* ============================================================
   Character Arc marketing site
   Tokens from src/styles/tokens.css
   Buttons + eyebrow from src/styles/base.css (verbatim spec)
   Cursor from src/styles/cursor.css (three layers)
   Nav underline from dextercklam.com index.html line 441
   Scenes from src/scenes/*.ts, SCENE_CALM 0.75
   Onboarding mirrors src/flows/Start.tsx
   Dark only. No mascot. No em dashes. No en dashes.
   ============================================================ */

:root{

  /* THE UNDERLINE RULE (owner, 08 Aug 2026). One stroke, used by every
     underline in the product: the marketing site's nav links and the
     app's section tabs, and anything added later.

     It is a straight inked line that TAPERS, thick at the left where
     the pen lands and thinner to the right where it lifts. The earlier
     version wobbled, which read as a squiggle rather than a considered
     mark. The fading is not in this shape at all: it comes from the
     gold gradient underneath, so the line thins and pales together,
     which is what a real stroke does.

     Nothing else may invent its own underline. Change it here and every
     underline in the product changes with it. */
  --stroke-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 6' preserveAspectRatio='none'%3E%3Cpath d='M0 1.1C60 1.0 140 1.5 200 2.1L200 3.4C140 3.2 60 3.6 0 4.0Z' fill='%23000'/%3E%3C/svg%3E");
  --font-heading:"Merriweather Sans",system-ui,sans-serif;
  --font-body:"Manrope",system-ui,sans-serif;
  --font-eyebrow:"Permanent Marker",cursive;

  --dark:#181818; --gold:#e0bb75; --gold-ink:#b8963e; --blue:#3a75bd;
  --cream:#f6f1eb; --white:#ffffff; --grey:#9e9e9e; --graphite:#444444; --salmon:#f6c0b3;

  --ochre:#c99a4e; --terracotta:#c56a47; --garnet:#b24a50; --plum:#8c5a78;
  --indigo:#5a63a6; --dustyblue:#5a86b0; --teal:#2f8477; --fern:#6e9160; --olive:#9a924e;
  --feel:#efe7d8; --think:#3a75bd; --do:#e0bb75;

  --s-1:8px; --s-2:16px; --s-3:24px; --s-4:32px; --s-5:40px; --s-6:48px;
  --s-7:64px; --s-8:80px; --s-9:96px; --s-10:120px;

  /* One cushion, the same on every side (owner, 07 Sep 2026). The air above a
     block, below it, and between it and the next one is the page's own gutter,
     so an element sits in equal space top, bottom, left and right and a phone
     fits more of a section in one view. It widens with the gutter at 860px. */
  --cushion:var(--s-3);

  --radius:16px; --radius-sm:10px; --sheet-radius:24px;
  --glow:0 0 20px 5px rgba(224,187,117,.45);
  --gold-lo:#d9b167; --gold-hi:#edcb90;
  --ease-out:cubic-bezier(.22,1,.36,1);
  --ease-spring:cubic-bezier(.34,1.56,.64,1);

  --h1-lg:clamp(34px,4.7vw,52px);
  --h1:clamp(28px,4.4vw,42px);
  --h2:clamp(24px,3.4vw,34px);
  --h3:clamp(19px,2.2vw,22px);
  --lead:clamp(18px,1.9vw,21px);
  --body:clamp(16px,1.4vw,17.5px);
  --small:15px; --very-small:13px; --eyebrow-size:13px;

  /* dark surface contract */
  --bg:var(--dark); --text:var(--white); --accent:var(--gold); --muted:var(--grey);
  --panel:rgba(24,24,24,.86); --hairline:rgba(255,255,255,.08);
  --card-gold-hairline:rgba(224,187,117,.5);
  --gold-text:var(--accent); --hair:var(--hairline); --ink:var(--text);
  --vellum-fill:rgba(18,18,26,.6); --vellum-fill-wide:rgba(18,18,26,.9); --vellum-solid:#16161c;
  --input-text:var(--gold); --input-bg:rgba(255,255,255,.04); --range-track:rgba(255,255,255,.1);
  --pole:var(--cream); --danger:#cf928a;
  --scrollbar-thumb:rgba(255,255,255,.14); --scrollbar-thumb-hover:rgba(255,255,255,.26);
  --nav-fill:rgba(20,20,20,.93);
  --scrim:linear-gradient(180deg,rgba(24,24,24,.74) 0%,rgba(24,24,24,.30) 46%,rgba(24,24,24,.58) 100%);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;background:var(--bg);color:var(--text);
  font-family:var(--font-body);font-size:var(--body);line-height:1.62;
  font-weight:400;-webkit-font-smoothing:antialiased;overflow-x:hidden
}
::selection{background:rgba(224,187,117,.28)}
/* brand scrollbars, verbatim from base.css: thin and quiet, neutral thumb */
*{scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) transparent}
*::-webkit-scrollbar{width:8px;height:8px}
*::-webkit-scrollbar-track{background:transparent}
*::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:8px}
*::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}
*::-webkit-scrollbar-corner{background:transparent}

/* ---------- type ---------- */
h1,h2,h3,h4{font-family:var(--font-heading);font-weight:800;line-height:1.14;margin:0;letter-spacing:-.015em}
h1{font-size:var(--h1)} .h1-lg{font-size:var(--h1-lg)}
h2{font-size:var(--h2)} h3{font-size:var(--h3);font-weight:700}
p{margin:0 0 var(--s-2)}
/* The last line of a copy column drops its trailing margin so the space
   between the words and the panel below them is the cushion and nothing
   more (owner, 07 Sep 2026). */
.hero-copy>:last-child,.grid2.with-actions>:first-child>:last-child{margin-bottom:0}
b.g,.gold{color:var(--gold-text);font-weight:inherit}
a{color:inherit;text-decoration:none}

/* the eyebrow rule, verbatim from base.css: dash BEFORE, fading right */
.eyebrow{
  font-family:var(--font-eyebrow);font-size:var(--eyebrow-size);
  color:var(--accent);text-transform:uppercase;letter-spacing:.14em;
  /* Block level rather than inline (owner, 07 Sep 2026): as an inline box the
     eyebrow inherited half a line of leading above it, which put 12px of
     unasked air between the top of a section and its hairline. Every other
     declaration is base.css's recipe unchanged. */
  display:flex;align-items:center;gap:14px;margin:0 0 var(--s-2);line-height:1
}
.eyebrow::before{
  content:"";width:22px;height:1px;flex:none;
  background:linear-gradient(90deg,var(--accent),rgba(224,187,117,.2))
}
.lead{font-size:var(--lead);line-height:1.55;opacity:.92}
.muted{color:var(--muted)}
.small{font-size:var(--small)} .vsmall{font-size:var(--very-small)}
.marker{font-family:var(--font-eyebrow);color:var(--gold-text);letter-spacing:.04em}
/* THE HEADING IS THE LABEL (13 Sep 2026, owner: the grey clarifier line under
   a heading looked misplaced in colour, size and spacing). Search engines and
   screen readers read the heading element, not how big it is drawn. So the
   plain phrase a person would search for is the section's h2, drawn exactly
   as the eyebrow it replaces, and the poetic line keeps its look as display
   text through .h2. A screen reader's list of headings gains clear landmarks
   ("Crossroads: hard decisions") instead of lines of poetry, and nothing is
   hidden, which search engines rightly treat as a trick. */
h2.eyebrow,h3.eyebrow{font-weight:400}
.h2{font-family:var(--font-heading);font-weight:800;line-height:1.14;margin:0;letter-spacing:-.015em;font-size:var(--h2)}
.helper{color:var(--text);font-size:var(--very-small)}

/* ---------- layout ---------- */
.wrap{width:100%;max-width:1160px;margin:0 auto;padding:0 var(--cushion)}
.narrow{max-width:720px} .mid{max-width:900px}
@media(min-width:860px){:root{--cushion:var(--s-5)}}

section.scene-sec{position:relative;min-height:100svh;display:flex;align-items:center;overflow:hidden}
section.scene-sec.short{min-height:auto;padding:var(--s-9) 0}
.scene-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:0;pointer-events:none}
.scene-scrim{position:absolute;inset:0;z-index:1;background:var(--scrim);pointer-events:none}
/* Every scene fades into the page ground at its top and bottom edge, so two
   sections meet in a blend rather than a cut (owner, 04 Sep 2026). Sits with
   the scrim, above the canvas and below the words. */
section.scene-sec::before,section.scene-sec::after{content:"";position:absolute;left:0;right:0;height:min(22vh,180px);z-index:1;pointer-events:none}
section.scene-sec::before{top:0;background:linear-gradient(to bottom,var(--bg),rgba(24,24,24,0))}
section.scene-sec::after{bottom:0;background:linear-gradient(to top,var(--bg),rgba(24,24,24,0))}
section.scene-sec#hero::before{height:0}
/* The home page settles on sections (owner, 04 Sep 2026): proximity rather than
   mandatory, so a held finger can still peek at the bottom of a section, and
   letting go glides to the nearest one in the direction of travel. The footer
   and the drawer are left alone. */
/* No scroll snap (owner, 07 Sep 2026): it fought a reader looking at the
   edge of a section. The sections reveal gently as they arrive instead. */
html:has(body[data-page="home"]){scroll-behavior:smooth}
@media(prefers-reduced-motion:reduce){html:has(body[data-page="home"]){scroll-behavior:auto}}

/* ---------- Long pages: a background that does not grow with the document ----------

   THE BUG THIS FIXES. .scene-canvas is absolutely positioned to fill its
   section, and on a legal page that section is the whole document. The scene
   engine sizes the backing store to the element's box times the device pixel
   ratio, so the Privacy Policy at 12,280 CSS pixels tall was asking for a
   2538 by 24559 bitmap: 62 million pixels, about 249 MB, cleared and repainted
   on every animation frame. Short pages were fine, which is why this looked
   like "long pages are slow" rather than "the canvas is the length of the page".

   Pinning it to the viewport caps that at one screen, about 4.6 million pixels,
   whatever the document's length. The scene also stops scrolling away, which is
   what a background should do anyway. */
.page-long .scene-canvas,
.page-long .scene-scrim{position:fixed;inset:0;width:100vw;height:100svh}
.page-long section.scene-sec{overflow:visible}

/* ---------- Tall sections: the same fix, everywhere else (13 Sep 2026) ----------

   The long page fix above found the real rule, and it was only ever applied
   to legal pages: a scene canvas must never be taller than the screen. On
   the primary pages a single section can still be several screens tall, and
   its canvas stretched with it. Measured on a phone profile, the membership
   page's one Valley canvas was 3,816px tall, repainted every frame: 23
   seconds of blocked main thread and a tap that took 3.5 seconds to answer.

   So a section the engine finds taller than 1.2 screens pins its scene to
   the viewport while it scrolls through, exactly as the legal pages do, and
   a short section is left precisely as it was. The painters compose for a
   screen, so a tall section now shows its whole scene instead of a slice of
   sky. overflow:clip rather than hidden, because hidden makes the section a
   scroll container and a pinned child would stop pinning. */
section.scene-sec.scene-tall{display:block;overflow:clip}
section.scene-sec.scene-tall>.scene-canvas,
section.scene-sec.scene-tall>.scene-scrim{position:sticky;inset:auto;top:0;width:100%;height:100svh;margin-bottom:-100svh}
/* A short section's own padding would start the pinned scene below its top
   edge, so for a tall one the padding moves onto the body: same total space,
   same place for every word, scenery from the very top. */
section.scene-sec.short.scene-tall{padding-top:0;padding-bottom:0}
section.scene-sec.short.scene-tall>.scene-body{padding-top:calc(var(--s-9) + var(--s-5));padding-bottom:calc(var(--s-9) + var(--s-5))}

/* Let the browser skip what is off screen.

   content-visibility: auto tells it not to lay out or paint a block until it
   comes near the viewport, and contain-intrinsic-size gives it a height to
   assume in the meantime so the scrollbar does not jump. This is the modern
   answer to "only load as you scroll": no pagination, no JavaScript, no change
   to the markup, and it degrades to nothing in a browser that lacks it.
   The auto keyword makes it remember each block's real height once measured.

   Applied per prose block rather than to the whole article, because a single
   contained block the length of the page would save nothing.

   The placeholder heights are measured, not guessed: on the Privacy Policy the
   median paragraph is 85px across 97 of them and a list is about 300px. A
   single 120px guess for everything made the page report 18,511px instead of
   its true 12,569, so the scrollbar was 47 percent wrong until you scrolled
   past each block. Headings are deliberately left out: at 25px they cost
   nothing to lay out, there are 28 of them, and containing them only adds
   error. */
.page-long .narrow > p{content-visibility:auto;contain-intrinsic-size:auto 85px}
.page-long .narrow > ul,
.page-long .narrow > ol,
.page-long .narrow > table{content-visibility:auto;contain-intrinsic-size:auto 300px}

/* The cursor glow blends against everything behind it, which on a very tall
   page means compositing a large area on every pointer move. It is a flourish,
   and a legal page is the one place it earns nothing. */
.page-long .ca-light{display:none}
.scene-body{position:relative;z-index:2;width:100%;padding:var(--s-9) 0}
.scene-sec.short .scene-body{padding:var(--s-5) 0}
.page:not(#page-home) section.scene-sec:first-child .scene-body{padding:var(--s-6) 0 var(--s-8)}

/* ---------- vellum ---------- */
/* The app's own vellum (src/styles/slice.css .vellum, owner 05 Sep 2026): the fill,
   the blur, a hairline all round, and the gold line of light fading in from the
   sides across the top edge, never a solid gold top border. */
.vellum{
  position:relative;overflow:hidden;
  background:var(--vellum-fill);
  -webkit-backdrop-filter:blur(10px) saturate(1.2);backdrop-filter:blur(10px) saturate(1.2);
  border:1px solid var(--hair);
  border-radius:var(--radius)
}
.vellum::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,var(--card-gold-hairline),transparent);pointer-events:none}
@media(min-width:860px){.vellum{background:var(--vellum-fill-wide)}}
.sheet{border-radius:var(--sheet-radius)}
.pad{padding:var(--s-3)}
@media(min-width:860px){.pad{padding:var(--s-4)}}

/* ---------- buttons: verbatim from src/styles/base.css ---------- */
.btn{
  font-family:var(--font-body);font-size:var(--small);font-weight:600;letter-spacing:-.006em;
  background:transparent;border:2px solid transparent;border-radius:var(--radius);
  padding:0 18px;min-height:44px;cursor:pointer;
  transition:transform .24s var(--ease-spring),box-shadow .32s var(--ease-out),
             background .24s var(--ease-out),color .24s var(--ease-out),border-color .24s var(--ease-out);
  display:inline-flex;align-items:center;justify-content:center;gap:9px;white-space:nowrap
}
.btn:focus-visible{outline:none;box-shadow:var(--glow)}
.btn-primary{
  background:linear-gradient(180deg,var(--gold-hi),var(--gold-lo));color:var(--white);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),0 6px 18px -8px rgba(224,187,117,.55)
}
.btn-primary:hover{
  transform:translateY(-2px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),0 10px 26px -8px rgba(224,187,117,.75)
}
.btn-secondary{background:transparent;border-color:var(--text);color:var(--text)}
.btn-secondary:hover,.btn-secondary:active{background:var(--text);color:var(--bg)}
.btn-sm{min-height:38px;font-size:13.5px;padding:0 15px}
.btn-block{width:100%}
.btn:disabled{opacity:.4;cursor:not-allowed;transform:none!important;box-shadow:none!important}
.btn:disabled:hover{background:linear-gradient(180deg,var(--gold-hi),var(--gold-lo));color:var(--white)}
.link-quiet{background:none;border:none;padding:0;color:var(--gold-text);font-family:var(--font-body);font-size:var(--very-small);cursor:pointer;text-decoration:none;font-weight:700}
.link-quiet:hover{text-decoration-color:var(--gold-text)}
/* A quiet link inside running text takes that text's size and face
   (owner, 07 Sep 2026): the class is built for standalone small links
   and buttons, so inside a lead it printed noticeably smaller than the
   words around it. */
p .link-quiet{font-size:inherit;font-family:inherit}


/* ---------- inputs ---------- */
.field{margin-bottom:var(--s-2)}
.builder .field{margin-bottom:10px}
/* Native tick boxes in the brand's gold, never the browser's blue. */
.builder input[type=checkbox],.builder input[type=radio]{accent-color:var(--gold-lo);width:18px;height:18px;flex:none}
.field>label,.field-label{display:block;font-size:var(--very-small);color:var(--muted);margin:0 0 7px;letter-spacing:.02em}
.inp{
  width:100%;min-height:46px;padding:0 15px;border-radius:var(--radius-sm);
  background:var(--input-bg);border:1px solid var(--hair);color:var(--input-text);
  font-family:var(--font-body);font-size:16px;font-weight:600;
  transition:box-shadow .3s,border-color .3s
}
.inp::placeholder{color:var(--muted);font-weight:400}
.inp:focus{outline:none;box-shadow:var(--glow);border-color:var(--card-gold-hairline)}
.form-error{color:var(--danger);font-size:var(--very-small);margin:6px 0 0}

/* ---------- the brand date picker, from the app's .bdp rules ---------- */
.bdp{position:relative}
.bdp-field{
  display:flex;justify-content:space-between;align-items:center;width:100%;min-height:44px;
  padding:14px var(--s-2);font-family:var(--font-body);font-size:var(--body);
  background:var(--input-bg);color:var(--input-text);
  border:1.5px solid var(--accent);border-radius:var(--radius);cursor:pointer
}
.bdp-field.empty{color:var(--grey)}
.bdp-field:focus-visible{outline:none;box-shadow:var(--glow)}
.bdp-cal-icon{width:18px;height:18px;flex:none;background:var(--gold-text);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Crect x='3.5' y='5' width='17' height='15.5' rx='3'/%3E%3Cpath d='M3.5 9.5h17M8 2.8v4M16 2.8v4'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Crect x='3.5' y='5' width='17' height='15.5' rx='3'/%3E%3Cpath d='M3.5 9.5h17M8 2.8v4M16 2.8v4'/%3E%3C/svg%3E") center/contain no-repeat}
.bdp-panel{width:min(320px,92vw);padding:var(--s-2);background:var(--vellum-solid);
  border:1px solid var(--hairline);border-radius:var(--radius);box-shadow:0 18px 44px rgba(0,0,0,.3);
  position:fixed;z-index:1000;max-width:calc(100vw - 16px);box-sizing:border-box}
/* One height in every view (owner, 05 Sep 2026): the day grid is six rows of
   34px under its weekday row, 243px together, and the month and year grids
   stretch their four rows to fill the same 243px, so the panel never grows,
   shrinks or leaves a gap beneath the numbers. */
.bdp-grid:not(.bdp-weekdays):not(.bdp-months){grid-auto-rows:34px}
.bdp-grid.bdp-months{height:243px;grid-auto-rows:1fr;align-content:stretch}
.bdp-precision{display:flex;border:1px solid var(--hairline);border-radius:10px;overflow:hidden;margin-bottom:var(--s-2)}
.bdp-seg{flex:1;border:none;background:transparent;color:var(--text);font-family:var(--font-body);
  font-size:var(--very-small);font-weight:600;padding:8px 0;cursor:pointer}
.bdp-seg.on{background:linear-gradient(180deg,var(--gold-hi),var(--gold-lo));color:var(--white)}
.bdp-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--s-1)}
.bdp-title{font-weight:700;font-size:var(--small);font-family:var(--font-body);border:none;background:none;
  color:var(--text);cursor:pointer;padding:8px 10px;border-radius:10px}
.bdp-title:hover{background:var(--input-bg)}
.bdp-nav{width:36px;height:36px;border:none;border-radius:10px;background:var(--input-bg);color:var(--text);font-size:20px;cursor:pointer}
.bdp-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px;min-width:0}
.bdp-months{grid-template-columns:repeat(3,1fr);gap:6px}
.bdp-weekdays span{text-align:center;font-size:var(--very-small);color:var(--muted);padding:4px 0}
.bdp-day{border:none;background:transparent;color:var(--text);font-family:var(--font-body);
  font-size:var(--small);min-height:36px;border-radius:10px;cursor:pointer;appearance:none;
  -webkit-appearance:none;padding:0;min-width:0}
.bdp-day:hover{background:var(--input-bg)}
.bdp-day.today{color:var(--gold-text);font-weight:700}
.bdp-day.sel{background:linear-gradient(180deg,var(--gold-hi),var(--gold-lo));color:var(--white);font-weight:700}
.bdp-day:disabled{color:var(--muted);opacity:.4;cursor:default}
.bdp-day:disabled:hover{background:transparent}

/* segmented switch, from the app's Milestone / Setback control */
.seg-switch{display:inline-flex;padding:3px;gap:3px;border:1px solid var(--hair);border-radius:var(--radius-sm);background:rgba(255,255,255,.02)}
.seg{
  font-family:var(--font-body);font-size:13.5px;font-weight:600;color:var(--text);
  background:transparent;border:none;border-radius:8px;padding:8px 14px;cursor:pointer;
  display:inline-flex;align-items:center;gap:7px;transition:background .25s,color .25s
}
.seg.on{background:linear-gradient(180deg,var(--gold-hi),var(--gold-lo));color:var(--white)}

/* chips, per FEEDBACK 884: transparent + 70% text outline, gold gradient + white text when on */
.chip{
  font-family:var(--font-body);font-size:13.5px;font-weight:600;
  background:transparent;border:1px solid rgba(255,255,255,.7);color:var(--text);
  border-radius:999px;padding:7px 14px;cursor:pointer;
  transition:background .25s,color .25s,border-color .25s,opacity .25s
}
.chip:hover{border-color:var(--gold-text)}
.chip.on{background:linear-gradient(180deg,var(--gold-hi),var(--gold-lo));color:var(--white);border-color:transparent}
.chip:disabled{opacity:.32;cursor:not-allowed}
.chip.prompt{cursor:default}
.chip.prompt.done{opacity:.34}
.chips-row{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:var(--s-2)}

.area-adder{display:flex;gap:8px;margin-bottom:10px}
.btn-plus{
  width:46px;height:46px;flex:0 0 auto;border-radius:var(--radius-sm);
  border:1px solid var(--card-gold-hairline);background:rgba(224,187,117,.08);
  color:var(--gold-text);font-size:20px;line-height:1;cursor:pointer;transition:background .25s
}
.btn-plus:hover{background:rgba(224,187,117,.18)}

/* emotion instrument */
.emo-words{display:flex;flex-wrap:wrap;gap:7px;margin-top:10px}
.rail{margin-top:12px}
.rail-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px}
.rail-val{font-family:var(--font-eyebrow);color:var(--gold-text);font-size:15px}
.rail-track{display:flex;gap:4px}
.rail-track button{
  flex:1;height:26px;border-radius:6px;border:1px solid var(--hair);
  background:rgba(255,255,255,.03);cursor:pointer;transition:background .2s,border-color .2s
}
.rail-track button:hover{border-color:var(--card-gold-hairline)}
.rail-track button.on{background:linear-gradient(180deg,var(--gold-hi),var(--gold-lo));border-color:transparent}
.rail-ends{display:flex;justify-content:space-between;margin-top:6px;font-size:11.5px;color:var(--muted)}

/* progress */
.start-progress{margin-bottom:var(--s-3)}
.start-progress-row{display:flex;justify-content:space-between;font-size:var(--very-small);color:var(--muted);margin-bottom:7px}
.start-progress-track{height:4px;border-radius:99px;background:var(--range-track);overflow:hidden}
.start-progress-fill{height:100%;border-radius:99px;background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi));transition:width .7s var(--ease-out)}

/* ---------- nav ---------- */
header.nav{
  position:fixed;top:0;left:0;right:0;z-index:60;
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-2);
  padding:12px max(var(--s-3),env(safe-area-inset-left));
  background:transparent;opacity:0;transform:translateY(-14px);pointer-events:none;
  transition:opacity .7s var(--ease-out),transform .7s var(--ease-out)
}
header.nav.show{
  opacity:1;transform:none;pointer-events:auto;background:var(--nav-fill);
  -webkit-backdrop-filter:blur(18px) saturate(1.25);backdrop-filter:blur(18px) saturate(1.25)
}
header.nav::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--hair);opacity:.7}
.wordmark{font-family:var(--font-heading);font-weight:800;font-size:16px;letter-spacing:-.015em;white-space:nowrap;cursor:pointer}
nav.links{display:none;gap:var(--s-4);align-items:center}
@media(min-width:900px){nav.links{display:flex}}

/* the underline, from dextercklam.com: gold hairline fading right, wiping in from the left */
.ul-link{position:relative;padding-bottom:2px;font-size:14px;font-weight:600;opacity:.82;transition:color .2s ease,opacity .2s ease;cursor:pointer}
.ul-link::after{
  content:"";position:absolute;left:0;bottom:-4px;width:100%;height:1px;
  background:linear-gradient(90deg,var(--gold),rgba(224,187,117,.25));
  transform:scaleX(0);transform-origin:left;transition:transform .28s ease
}
.ul-link:hover{opacity:1}
.ul-link:hover::after,.ul-link.active::after{transform:scaleX(1)}
.ul-link.active{color:var(--gold-text);opacity:1}
/* the drawn variant: same timing and colour ramp, a marker stroke with a taper */
.ul-link::after{background:none;height:5px;bottom:-6px;
  -webkit-mask:var(--stroke-mask) left center/100% 100% no-repeat;mask:var(--stroke-mask) left center/100% 100% no-repeat;
  background-image:linear-gradient(90deg,var(--gold),rgba(224,187,117,.25))}

.nav-right{display:flex;align-items:center;gap:10px}
.menu-btn{display:grid;place-items:center;width:42px;height:42px;border-radius:var(--radius-sm);border:1px solid var(--hair);background:transparent;color:var(--text);cursor:pointer}
@media(min-width:900px){.menu-btn{display:none}}
@media(max-width:560px){header.nav .btn-primary{display:none}}

/* Opaque, and no backdrop blur (13 Sep 2026, Core Web Vitals): a full screen
   blur behind a 96 percent opaque panel could barely be seen, but it made the
   browser re-blur the whole screen over the moving scenes, and opening the
   menu took 648ms to answer a tap on a phone profile. */
.drawer{
  position:fixed;inset:0;z-index:80;background:rgb(20,20,20);
  display:flex;flex-direction:column;justify-content:center;gap:var(--s-2);padding:var(--s-6) var(--s-4);
  opacity:0;pointer-events:none;transition:opacity .5s var(--ease-out)
}
.drawer.open{opacity:1;pointer-events:auto}
.drawer .ul-link{font-family:var(--font-heading);font-weight:800;font-size:30px;padding:8px 0;align-self:flex-start}
.drawer .close{position:absolute;top:16px;right:16px;width:44px;height:44px;border-radius:var(--radius-sm);border:1px solid var(--hair);background:transparent;color:var(--text);font-size:20px;cursor:pointer}

/* ---------- pages ---------- */
main{position:relative}
.page{display:none}
.page.active{display:block;animation:ink .85s var(--ease-out) both}
@keyframes ink{from{opacity:0;transform:translateY(22px)}to{opacity:1;transform:none}}

.rv{opacity:0;transform:translateY(26px);transition:opacity .9s var(--ease-out),transform .9s var(--ease-out)}
.rv.in{opacity:1;transform:none}
.rv.d1{transition-delay:.1s}.rv.d2{transition-delay:.2s}.rv.d3{transition-delay:.3s}.rv.d4{transition-delay:.42s}

/* ---------- the light cursor: three layers, from src/styles/cursor.css ---------- */
html.ca-cursor-on *{cursor:none!important}
.ca-light,.ca-dot,.ca-ring{position:fixed;top:0;left:0;pointer-events:none;opacity:0;transition:opacity .4s ease}
body.ca-cursor-visible .ca-light,body.ca-cursor-visible .ca-dot,body.ca-cursor-visible .ca-ring{opacity:1}
.ca-light{
  width:640px;height:640px;margin:-320px 0 0 -320px;border-radius:50%;z-index:2147483200;
  background:radial-gradient(circle,rgba(224,187,117,.16) 0%,rgba(224,187,117,.07) 32%,rgba(224,187,117,.02) 55%,transparent 72%);
  mix-blend-mode:screen;will-change:transform
}
.ca-dot{
  width:8px;height:8px;margin:-4px 0 0 -4px;border-radius:50%;background:var(--gold);
  box-shadow:0 0 10px 2px rgba(224,187,117,.85);z-index:2147483400;will-change:transform;
  transition:opacity .4s ease,width .18s ease,height .18s ease,margin .18s ease,border-radius .18s ease
}
.ca-ring{
  width:38px;height:38px;margin:-19px 0 0 -19px;border-radius:50%;
  border:1.5px solid rgba(224,187,117,.65);z-index:2147483300;transform:scale(.55);
  transition:opacity .25s ease,transform .25s ease;will-change:transform
}
body.ca-hovering .ca-ring{opacity:1;transform:scale(1)}
body.ca-hovering .ca-dot{width:5px;height:5px;margin:-2.5px 0 0 -2.5px}
body.ca-text .ca-dot{width:2px;height:24px;margin:-12px 0 0 -1px;border-radius:1px}
body.ca-text .ca-ring{opacity:0}
body.ca-pressing .ca-ring{transform:scale(.85)}
@media(prefers-reduced-motion:reduce){.ca-light{display:none}}
@media(hover:none),(pointer:coarse){.ca-light,.ca-dot,.ca-ring{display:none}html.ca-cursor-on *{cursor:auto!important}}

/* ---------- hero + builder ---------- */
.hero-grid{display:grid;gap:var(--cushion);align-items:center}
@media(min-width:1000px){.hero-grid{grid-template-columns:1fr 1.02fr;gap:var(--s-7)}}
/* No margin of its own: the grid's own cushion is the whole gap between the
   panel and the first button (owner, 07 Sep 2026). */
.hero-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:0}
/* The builder keeps one height through every step and never scrolls inside
   (owner, 05 Sep 2026): each step was cut to fit a phone screen instead. The
   one fallback is a landscape phone, where a scroll beats a clipped form. */
/* One height through the drawing steps, and never a clipped button (owner,
   06 Sep 2026): the panel holds its height while a step fits, and grows for
   the step that does not, rather than scrolling inside or cutting off. */
.builder{display:flex;flex-direction:column;min-height:min(88svh,760px);height:auto}

.builder>.start-progress,.builder>.stage{flex:0 0 auto}
.builder .stage.reveal{height:clamp(240px,36svh,340px)}
/* Taller on the reveal (owner, 07 Sep 2026): the last screen is the one
   with the road ahead and an intention on it, and 26svh could not hold
   them. The drawing steps still get the shorter stage. */
.builder .stage{position:relative;height:clamp(180px,26svh,240px);border-radius:var(--radius-sm);overflow:hidden;background:rgba(255,255,255,.02);margin-bottom:var(--s-3)}
.builder svg{display:block;width:100%;height:100%}
.step{display:none;animation:ink .55s var(--ease-out) both}
.step.on{flex:1 1 auto;min-height:0;overflow:visible;padding:2px 10px 0 0}
.step.on{display:block}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media(max-width:520px){.row2{grid-template-columns:1fr}}
.start-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:var(--s-3)}
.signin-line{margin:var(--s-2) 0 0;font-size:var(--very-small);color:var(--muted)}
.signin-line .link-quiet{font-size:var(--very-small)}
.date-row{display:grid;grid-template-columns:1.1fr 1fr 1fr;gap:8px}
.date-row select,.date-row input{width:100%}
select.inp{appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--gold) 50%),linear-gradient(135deg,var(--gold) 50%,transparent 50%);background-position:calc(100% - 18px) 21px,calc(100% - 13px) 21px;background-size:5px 5px,5px 5px;background-repeat:no-repeat}

/* arc marks */
.arc-line{fill:none;stroke:var(--gold);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;filter:drop-shadow(0 0 7px rgba(224,187,117,.42))}
.arc-line.future{stroke-dasharray:5 7;opacity:.6;filter:none}
.arc-base{stroke:var(--hair);stroke-width:1;stroke-dasharray:2 6}
.mark-label{font-family:var(--font-eyebrow);font-size:11.5px;fill:var(--text);opacity:.84;letter-spacing:.03em}
.mark-date{font-family:var(--font-eyebrow);font-size:9.5px;fill:var(--muted);letter-spacing:.03em}
.anchor-label{font-family:var(--font-eyebrow);font-size:10.5px;fill:var(--gold);letter-spacing:.08em;text-transform:uppercase}

/* ---------- grids ---------- */
.grid3{display:grid;gap:var(--s-2)}
@media(min-width:760px){.grid3{grid-template-columns:repeat(3,1fr);gap:var(--s-3)}}
.grid2{display:grid;gap:var(--cushion)}
@media(min-width:860px){.grid2{grid-template-columns:1fr 1fr}}
.grid4{display:grid;gap:12px;grid-template-columns:1fr 1fr}
@media(min-width:760px){.grid4{grid-template-columns:repeat(4,1fr)}}
.legend{display:flex;flex-wrap:wrap;gap:var(--s-2) var(--s-3);margin-top:var(--s-3)}
.legend div{display:flex;align-items:center;gap:9px;font-size:13.5px;color:var(--muted)}
.dotchip{width:9px;height:9px;border-radius:50%;flex:0 0 auto;display:inline-block}
.stack>*+*{margin-top:var(--s-2)}
.center{text-align:center}

/* ---------- quests ---------- */
.bar{height:5px;border-radius:99px;background:var(--range-track);overflow:hidden}
.bar i{display:block;height:100%;border-radius:99px;background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi));width:0;transition:width .9s var(--ease-out)}
.flagrow{display:flex;gap:7px;align-items:center;height:22px}
.leafdot{width:11px;height:11px;border-radius:50% 0;transform:rotate(45deg);background:rgba(255,255,255,.12);transition:background .5s var(--ease-out),box-shadow .5s}
.leafdot.on{background:linear-gradient(135deg,var(--gold-lo),var(--gold-hi));box-shadow:0 0 12px rgba(224,187,117,.55)}
.pillar{display:flex;gap:12px;align-items:flex-start;padding:14px;border-radius:var(--radius-sm);border:1px solid var(--hair);transition:all .35s var(--ease-out)}
.pillar:hover{border-color:var(--card-gold-hairline);transform:translateY(-2px)}
.pillar .bdg{width:34px;height:34px;border-radius:50%;flex:0 0 auto;display:grid;place-items:center;border:1px solid var(--hair)}
.pillar h4{font-size:14px;font-weight:700;margin:0 0 2px;font-family:var(--font-body)}
.pillar p{font-size:12.5px;color:var(--muted);margin:0;line-height:1.45}

/* ---------- models ---------- */
.model-card{padding:var(--s-3);border-radius:var(--radius);border:1px solid var(--hair);transition:transform .4s var(--ease-out),box-shadow .4s,border-color .4s;cursor:pointer;position:relative;overflow:hidden}
.model-card:hover{transform:translateY(-3px);border-color:var(--card-gold-hairline);box-shadow:0 18px 40px -26px rgba(224,187,117,.6)}
.model-card .etym{font-family:var(--font-eyebrow);font-size:11.5px;color:var(--gold-text);letter-spacing:.05em;margin:0 0 8px}
.model-card h3{margin:0 0 8px}
.model-card p{font-size:14px;color:var(--muted);margin:0 0 12px;line-height:1.5}
.ladder{display:flex;gap:6px;align-items:center;font-size:11.5px;color:var(--muted)}
.ladder span{padding:3px 9px;border-radius:99px;border:1px solid var(--hair)}
.ladder span.done{border-color:var(--card-gold-hairline);color:var(--gold-text)}

/* ---------- membership ---------- */
.tiers{display:grid;gap:var(--s-3);align-items:start}
@media(min-width:900px){.tiers{grid-template-columns:1fr 1.1fr}}
.tier{position:relative;padding:var(--s-4) var(--s-3)}
@media(min-width:860px){.tier{padding:var(--s-5) var(--s-4)}}
/* THE VISIONARY CARD WEARS THE NIGHT'S INDIGO (owner, 08 Sep 2026), the
   same colour the app's own membership panel wears in Settings, so the
   two surfaces agree about which one is the paid tier.

   Not a flat fill and not the app's light tint. A flat slab at this
   size fights both the page's dark ground and the gold button on it,
   and the tint was too quiet to be noticed at all. This is the wash:
   the colour mixed with ink so it is genuinely opaque, one soft light
   from the top right, and a film of grain, which is the same recipe
   the app puts on a model card and a quest tile. Solid in the way that
   matters, with a surface rather than a slab.

   The gold breath around it stays: it is the only card on the page that
   glows, and that is the job it is doing. */
.tier.feature{
  --wash:var(--indigo);
  --wash-ink:70%; --wash-ink-far:34%; --wash-light:.14; --wash-grain:.09;
  border-color:rgba(122,132,196,.75);
  overflow:hidden;
  background:
    radial-gradient(120% 90% at 88% 8%, rgba(255,255,255,var(--wash-light)), transparent 58%),
    linear-gradient(
      168deg,
      color-mix(in srgb, var(--wash) var(--wash-ink), var(--dark)) 0%,
      color-mix(in srgb, var(--wash) calc((var(--wash-ink) + var(--wash-ink-far)) / 2), var(--dark)) 55%,
      color-mix(in srgb, var(--wash) var(--wash-ink-far), var(--dark)) 100%
    )
}
@supports not (background: color-mix(in srgb, red 70%, black)){
  .tier.feature{background:var(--indigo)}
}
/* The grain sits over the colour and behind the words. */
.tier.feature::after{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;border-radius:inherit;
  opacity:var(--wash-grain);mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.9 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")
}
.tier.feature > *{position:relative;z-index:1}
/* On the indigo, the founding panel and the muted helper both need
   lifting: grey on a coloured ground reads as dirt. */
.tier.feature .founding{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.22)}
.tier.feature .muted,.tier.feature .per{color:rgba(255,255,255,.72)}
.tier.feature::before{content:"";position:absolute;inset:-1px;border-radius:var(--sheet-radius);pointer-events:none;z-index:2;box-shadow:0 0 46px -14px rgba(224,187,117,.65);animation:breathe 7s ease-in-out infinite}
@keyframes breathe{0%,100%{opacity:.55}50%{opacity:1}}
.tier .amount{font-family:var(--font-heading);font-weight:800;font-size:clamp(36px,5vw,50px);line-height:1;letter-spacing:-.02em}
.tier .per{font-size:14px;color:var(--muted);font-weight:500}
.tiername{font-family:var(--font-heading);font-size:21px;font-weight:800;margin:0 0 4px}
.tagline{color:var(--muted);font-size:14.5px;margin:0 0 var(--s-3)}
.feat{list-style:none;margin:0;padding:0}
.feat li{display:flex;gap:11px;padding:9px 0;font-size:14.5px;line-height:1.5;border-bottom:1px solid var(--hair)}
.feat li:last-child{border-bottom:none}
.feat li .tick{flex:0 0 auto;margin-top:4px}
.feat .grp{font-family:var(--font-eyebrow);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--gold-text);padding:var(--s-3) 0 4px;border-bottom:none;display:block}
.more{max-height:0;overflow:hidden;transition:max-height .6s var(--ease-out)}
.more.open{max-height:2400px}
.founding{border-radius:var(--radius-sm);border:1px dashed var(--card-gold-hairline);padding:14px 16px;margin:var(--s-3) 0 0;background:rgba(224,187,117,.05)}
.never{display:grid;gap:10px}
@media(min-width:760px){.never{grid-template-columns:1fr 1fr}}
.never div{display:flex;gap:10px;align-items:center;font-size:14.5px;padding:11px 14px;border-radius:var(--radius-sm);border:1px solid var(--hair)}

/* FAQ: chevron down at rest, up when open */
.faq{border-top:1px solid var(--hair)}
.faq details{border-bottom:1px solid var(--hair)}
.faq summary{cursor:pointer;list-style:none;padding:18px 0;font-family:var(--font-heading);font-weight:700;font-size:17px;display:flex;justify-content:space-between;gap:16px;align-items:center}
.faq summary::-webkit-details-marker{display:none}
.faq summary .chev{flex:0 0 auto;color:var(--gold-text);transition:transform .35s var(--ease-out)}
.faq details[open] summary .chev{transform:rotate(180deg)}
/* The answer is body copy, not a caption: it reads in the page's own
   white rather than the muted grey (owner, 07 Sep 2026). And an open
   question turns gold, so you can see at a glance which one you opened. */
.faq .ans{padding:0 0 20px;color:var(--text);font-size:15px;max-width:70ch;line-height:1.6}
.faq details[open] summary{color:var(--gold-text)}

/* The quiet note card. It was a left-bordered strip; from 04 Sep 2026 it is the
   app's own vellum card, the gold hairline across the top edge and nothing else
   (owner: the strip read as a generic template element). */
.tape{position:relative;padding:var(--s-3);border-radius:var(--radius);background:var(--vellum-fill);-webkit-backdrop-filter:blur(10px) saturate(1.2);backdrop-filter:blur(10px) saturate(1.2);border:1px solid var(--hair);border-top-color:var(--card-gold-hairline)}
.tape p:last-child{margin-bottom:0}
.kpi{font-family:var(--font-heading);font-weight:800;font-size:clamp(28px,4vw,40px);line-height:1;letter-spacing:-.02em}
.kpi small{display:block;font-family:var(--font-body);font-size:13px;font-weight:500;color:var(--muted);letter-spacing:0;margin-top:8px}
.ring-wrap{display:flex;gap:var(--s-4);align-items:center;flex-wrap:wrap}
.ring-key{display:grid;gap:8px;flex:1 1 190px;min-width:180px}
.ring-key div{display:flex;align-items:center;gap:9px;font-size:13.5px}
.ring-key b{margin-left:auto;font-weight:700;color:var(--muted);font-size:12.5px}
.tfd{display:grid;grid-template-columns:60px 1fr 78px;gap:12px;align-items:center;margin-bottom:10px;font-size:13px}
.tfd .tr{height:6px;border-radius:99px;background:var(--range-track);position:relative;overflow:hidden}
.tfd .tr i{position:absolute;left:0;top:0;bottom:0;border-radius:99px;width:0;transition:width 1.1s var(--ease-out)}
.delta{font-family:var(--font-eyebrow);font-size:12px;color:var(--gold-text);letter-spacing:.04em;text-align:right}

footer{padding:var(--s-8) 0 var(--s-6);border-top:1px solid var(--hair);position:relative;z-index:2}
.foot-grid{display:flex;flex-wrap:wrap;gap:var(--s-4);justify-content:space-between;align-items:flex-start}
.foot-links{display:flex;flex-wrap:wrap;gap:var(--s-3) var(--s-4)}
/* THE FOOTER, IN COLUMNS (owner, 09 Sep 2026). One flat row of links
   was already at its limit and more are coming, so it is grouped by
   what somebody would be looking for: the product, things to read,
   what a membership costs, and the small print. Four columns on a wide
   screen, two on a tablet, one on a phone. */
.foot-cols{display:grid;gap:var(--s-4) var(--s-5);grid-template-columns:1fr;width:100%}
@media(min-width:560px){.foot-cols{grid-template-columns:1fr 1fr}}
@media(min-width:900px){.foot-cols{grid-template-columns:repeat(4,1fr)}}
.foot-col{display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.foot-col h4{
  margin:0 0 2px;font-family:var(--font-eyebrow);font-size:11.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--gold-text);font-weight:400
}
.foot-col .ul-link{font-size:14px}
.foot-links .ul-link{font-size:13.5px;opacity:.7}
.quiet-note{font-size:12.5px;color:var(--muted);margin-top:var(--s-4);max-width:62ch}

@media(prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
  html{scroll-behavior:auto}
}

/* ---------- the home page's questions (owner, 07 Sep 2026) ----------
   A plain accordion: <details> and <summary>, so it opens without any
   script, answers a keyboard, and is read by a crawler whether or not
   it is open. The hairline between rows is the page's own, the marker
   is the app's chevron rather than the browser's triangle. */
/* A heading over each run of questions, so a long list can be scanned
   (owner, 07 Sep 2026). The accordion itself is the one the membership
   page already uses: same details, same summary, same chevron. A second
   accordion recipe would be one more thing that drifts. */
/* A group heading is set exactly as the section's own hairline: same
   face, same size, same tracking (owner, 07 Sep 2026), and the run of
   questions under it drops the hairline it used to carry, because the
   heading is already the separator. */
.faq-group{
  font-family:var(--font-eyebrow);font-size:var(--eyebrow-size);letter-spacing:.14em;
  text-transform:uppercase;color:var(--gold-text);font-weight:400;
  margin:var(--s-5) 0 var(--s-2)
}
.faq-group:first-child{margin-top:var(--s-4)}
.faq-group + .faq{border-top:none}
.faq summary:focus-visible{outline:2px solid var(--gold-text);outline-offset:3px;border-radius:6px}
@media(max-width:600px){.faq summary{font-size:16px;padding:16px 0}}

/* ==================================================================
   THE TESTIMONIALS BAND (owner, 07 Sep 2026)
   Lives here rather than on one page, because the home page and the
   mockup have to be the same object.

   The card is the app's own testimonial preview (src/components/
   StoryFlow.tsx .story-prev, src/styles/app.css) filled with the app's
   own wash (src/styles/slice.css .wash), so what a member approves
   before sending is what a visitor sees. Every value below is copied
   from those two files, not approximated.

   Class prefix is tm-, never rv-, because .rv is already this site's
   reveal class and two unrelated things sharing a prefix is how a
   stylesheet starts to lie.
   ================================================================== */
.tm-band{position:relative;margin-top:var(--s-4);overflow:hidden}
/* The band bleeds to both edges and fades into the page ground, so a
   card entering or leaving is never cut off against a hard line. */
.tm-band::before,.tm-band::after{content:"";position:absolute;top:0;bottom:0;width:12%;z-index:2;pointer-events:none}
.tm-band::before{left:0;background:linear-gradient(90deg,var(--bg),transparent)}
.tm-band::after{right:0;background:linear-gradient(270deg,var(--bg),transparent)}
.tm-row{overflow:hidden;padding:var(--s-1) 0}
.tm-run{display:flex;gap:var(--s-3);width:max-content;will-change:transform}

/* Each run is printed twice, so travelling one full copy lands exactly
   where it began and the loop closes with no seam. Rightward starts a
   copy to the left and returns to zero; leftward is the reverse. The
   two rows run at different speeds on purpose: matched speeds read as
   one block sliding, which is the thing a two row band is trying to
   avoid. */
.tm-right .tm-run{animation:tm-right 72s linear infinite}
.tm-left .tm-run{animation:tm-left 88s linear infinite}
@keyframes tm-right{from{transform:translate3d(-50%,0,0)}to{transform:translate3d(0,0,0)}}
@keyframes tm-left{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
.tm-band:hover .tm-run,.tm-band:focus-within .tm-run,.tm-band.is-paused .tm-run{animation-play-state:paused}

/* .story-prev's shape and spacing, filled with .wash. The colour
   arrives per card in --c and is mixed with ink at --wash-ink where the
   words sit and --wash-ink-far at the foot, so the fill is solid and
   the words stay legible; one soft radial highlight lights it from the
   top right; and a film of grain keeps it a surface with light on it
   rather than a flat panel. */
.tm-card{
  --wash:var(--c);
  --wash-ink:70%; --wash-ink-far:34%; --wash-light:.14; --wash-grain:.09;
  position:relative;
  flex:0 0 auto;width:min(84vw,360px);margin:0;
  border:1px solid var(--hair);
  border-radius:16px;padding:16px;
  display:flex;flex-direction:column;gap:13px;
  overflow:hidden;
  background:
    radial-gradient(120% 90% at 88% 8%, rgba(255,255,255,var(--wash-light)), transparent 58%),
    linear-gradient(
      172deg,
      color-mix(in srgb, var(--wash) var(--wash-ink), var(--dark)) 0%,
      color-mix(in srgb, var(--wash) calc((var(--wash-ink) + var(--wash-ink-far)) / 2), var(--dark)) 52%,
      color-mix(in srgb, var(--wash) var(--wash-ink-far), var(--dark)) 100%
    )
}
/* The grain sits behind the words, never over them. */
.tm-card::after{
  content:'';position:absolute;inset:0;z-index:0;
  pointer-events:none;border-radius:inherit;
  opacity:var(--wash-grain);mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.9 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")
}
.tm-card > *{position:relative;z-index:1}
/* A browser without color-mix still gets a readable card. */
@supports not (background: color-mix(in srgb, red 70%, black)){
  .tm-card{background:var(--c)}
}

/* .story-quote, at the size a marketing band can carry. */
.tm-quote{font-family:var(--font-heading);font-weight:700;font-size:16px;line-height:1.5;margin:0;color:var(--text)}
/* .story-who and .story-who-text. */
.tm-who{display:flex;gap:11px;align-items:center;margin-top:auto}
.tm-who-text b{display:block;font-size:13px;font-weight:600;color:var(--text)}
.tm-who-text small{display:block;color:var(--muted);font-size:11.8px}
/* .story-av-small: the ring a real photo sits in. On a washed card the
   ring reads in light, not in the card's own colour, which would
   disappear into the ground it sits on. */
.tm-av{width:40px;height:40px;border-radius:999px;flex:0 0 auto;border:1px solid rgba(255,255,255,.32);object-fit:cover}
/* .story-monogram: the app's own fallback for a member with no photo. */
.tm-monogram{display:flex;align-items:center;justify-content:center;color:var(--text);font-family:var(--font-heading);font-weight:700;font-size:15px;background:rgba(255,255,255,.12)}

/* A visitor who asks for less motion gets a band that does not move:
   the rows wrap, stand still, and the pause button is pointless so it
   goes. */
@media(prefers-reduced-motion:reduce){
  .tm-run{animation:none;flex-wrap:wrap;width:auto;justify-content:center}
  .tm-run .tm-card:nth-child(n+5){display:none}
  .tm-band::before,.tm-band::after{display:none}
}

/* ==================================================================
   The measurement ask (owner, 06 Aug 2026). Sits at the foot, above
   everything, and does not block the page behind it: this is a
   question, not a wall. Matched by .consent-bar in the app's
   slice.css so the two read as one product.
   ================================================================== */
.consent-bar{
  position:fixed; left:0; right:0; bottom:0; z-index:80;
  display:flex; align-items:center; gap:16px; flex-wrap:wrap;
  justify-content:center;
  padding:14px 18px calc(14px + env(safe-area-inset-bottom));
  background:rgba(18,18,18,.94);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  border-top:1px solid var(--card-gold-hairline,rgba(224,187,117,.28));
}
.consent-text{
  margin:0; max-width:62ch; font-size:14px; line-height:1.5;
  color:var(--muted,#b9b4ab);
}
.consent-text a{ color:var(--gold-text,#e0bb75); }
/* The bar says what it is before it says what it does (owner, 07 Sep
   2026), so a visitor can tell at a glance what the choice is about. */
.consent-title{ display:block; color:var(--text); font-weight:700; margin-bottom:2px; }
/* The way back to the cookie question, on the cookies notice itself
   (owner, 09 Sep 2026). It was a button in the footer and read as
   neither a link nor a control there. */
.consent-control{
  border:1px solid var(--card-gold-hairline); border-radius:var(--radius-sm);
  background:rgba(224,187,117,.05); padding:var(--s-3); margin:var(--s-3) 0;
}
.consent-control b{ color:var(--gold-text) }
.consent-actions{ display:flex; gap:10px; flex-shrink:0; }
@media (max-width:640px){
  .consent-bar{ justify-content:stretch; }
  .consent-actions{ width:100%; }
  .consent-actions .btn{ flex:1; }
}

/* A primary that cannot be pressed yet says so, rather than swallowing
   the press and showing a line of red text below the fold. */
.btn.is-unavailable{ opacity:.45; cursor:not-allowed; box-shadow:none; }

/* The provider door on the save step (owner, 21 Aug 2026), the same
   shapes as the app's own auth screens. */
.auth-or{ display:flex; align-items:center; gap:12px; margin:14px 0; font-size:13px; opacity:.7; }
.auth-or::before,.auth-or::after{ content:""; flex:1; border-top:1px solid var(--hairline, currentColor); }
.btn-oauth{ display:inline-flex; align-items:center; justify-content:center; gap:10px; width:100%; }
/* Pinned with the builder's own specificity and again on the element
   (owner bug, 21 Aug 2026): `.builder svg` sizes the arc canvas to
   100% and took the G mark with it, filling the button. */
.oauth-mark,.builder .oauth-mark,.builder .btn-oauth svg{ width:18px; height:18px; min-width:18px; max-width:18px; flex:none; display:inline-block; }

/* Legal document tables (A4's price rows, A8's version list). Generated by
   scripts/build-legal.mjs, so the styling lives here rather than inline.
   The wrapper scrolls on a narrow screen; the page body never does. */
.legal-table{width:100%;border-collapse:collapse;margin:var(--s-2) 0;font-size:16px}
.legal-table th,.legal-table td{text-align:left;padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.10);vertical-align:top}
.legal-table th{font-weight:600;color:var(--gold-text)}
/* A comparison table must scroll inside its own box rather than push the
   page sideways on a phone (SEO brief section 10). --color-gold never
   existed, so these headings have been inheriting since the legal pages
   shipped; the token is --gold-text (found 13 Sep 2026). */
.tbl-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:var(--s-2) 0}
/* Read by a screen reader and by anything that parses the page, and
   not drawn for anybody who can see the graphic it describes. */
.visually-hidden{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}
.tbl-scroll .legal-table{min-width:620px;margin:0}
.legal-table tr:last-child td{border-bottom:0}
.narrow blockquote.tape{margin:var(--s-3) 0}
.narrow code{font-size:.95em;opacity:.9}

/* ---------- the arc, drawn as the app draws it (site revamp round 2, 04 Sep 2026) ----------
   Values copied from src/styles/slice.css and arc.css so the marks read the same on
   the site as in the app: the line, the kind dots, the hollow future dot, the neutral
   pole and coloured pennant, the crossroads mark and fan, the vellum card, the readout. */
.arc-line{stroke-width:2.5;filter:drop-shadow(0 0 7px rgba(224,187,117,.5))}
.arc-line.future{stroke-dasharray:5 7;stroke-width:2;opacity:.75;filter:none}
.arc-hit{fill:transparent;pointer-events:all;cursor:pointer}
.arc-dot.milestone{fill:var(--gold)}
.arc-dot.setback{fill:var(--garnet)}
.arc-dot.everyday{fill:var(--feel)}
.arc-impact-ring{fill:none;stroke:var(--gold);stroke-width:1.5}
.arc-stretch{pointer-events:none}
.arc-stretch.setback{stroke:var(--garnet);filter:drop-shadow(0 0 7px rgba(178,74,80,.5))}
.arc-dot-end.setback{fill:var(--garnet)}
.arc-dot-future{fill:transparent;stroke:var(--gold);stroke-width:2}
.arc-today-dot{fill:var(--gold)}
.arc-today-pulse{fill:none;stroke:var(--gold)}
.arc-today-plus{fill:none;stroke:var(--white);stroke-width:1.5;stroke-linecap:round;pointer-events:none}
.arc-label{font-family:var(--font-heading);font-size:12.5px;fill:var(--text);opacity:0;transition:opacity .35s var(--ease-out);pointer-events:none;paint-order:stroke;stroke:var(--bg);stroke-width:3px;stroke-linejoin:round}
.arc-label.shown{opacity:.95}
.arc-label.anchor{font-family:var(--font-eyebrow);fill:var(--gold-text);font-weight:400;stroke:none}
.arc-axis text{font-family:var(--font-body);font-size:11.5px;fill:var(--muted)}
.arc-axis line{stroke:var(--hair)}
.arc-flag-pole{stroke:var(--pole);stroke-width:2;stroke-linecap:round;pointer-events:none}
.arc-flag-pennant{fill:transparent;stroke:var(--flag,var(--ochre));stroke-width:1.6;stroke-linejoin:round}
.arc-done-flag .arc-flag-pennant{fill:var(--flag,var(--ochre));stroke:var(--flag,var(--ochre))}
.arc-aim-g .arc-flag-pennant{fill:var(--flag,var(--ochre));stroke:var(--flag,var(--ochre));opacity:.75}
.arc-aim-g .arc-flag-pole{stroke-dasharray:3 3;opacity:.7}
.arc-cx-branch{fill:none;stroke-width:1.7;stroke-dasharray:5 7;stroke-linecap:round;opacity:.85}
.arc-cx-branch.chosen{stroke-dasharray:none;opacity:1}
.arc-cx-disc-ring{fill:none}
.arc-cx-disc.chosen .arc-cx-num{fill:var(--bg)}
.arc-cx-num{font-family:var(--font-body);font-weight:700;font-size:11.5px;fill:var(--text);pointer-events:none}
.arc-cx-label{font-family:var(--font-heading);font-size:12.5px;fill:var(--text);pointer-events:none;paint-order:stroke;stroke:var(--bg);stroke-width:3px;stroke-linejoin:round}
.arc-cx-header{font-family:var(--font-heading);font-size:13.5px;font-weight:700;fill:var(--gold-text);paint-order:stroke;stroke:var(--bg);stroke-width:3px;stroke-linejoin:round}
.arc-cx-ring{fill:var(--gold);stroke:var(--gold);stroke-width:1.8}
.arc-cx-mark.open .arc-cx-ring,.arc-card-cx.open .arc-cx-ring{fill:none}
.arc-cx-fork{fill:none;stroke:var(--gold);stroke-linecap:round;stroke-linejoin:round}
.arc-cx-mark:not(.open) .arc-cx-fork,.arc-card-cx:not(.open) .arc-cx-fork{stroke:var(--bg)}
.arc-card-lead{stroke:var(--gold);stroke-width:1;stroke-dasharray:2 4;opacity:.32}
.arc-card-bg{fill:var(--vellum-solid);stroke:var(--card-gold-hairline);stroke-width:1}
.arc-card-title{font-family:var(--font-heading);font-size:12.5px;font-weight:700;fill:var(--text)}
.arc-card-meta{font-family:var(--font-body);font-size:10.5px;fill:var(--muted)}
.arc-card-dot.milestone{fill:var(--gold)}
.arc-card-dot.setback{fill:var(--garnet)}
.arc-card-dot.everyday{fill:var(--feel)}
.arc-card-dot.future{fill:transparent;stroke:var(--gold);stroke-width:1.6}
.arc-card-flag{fill:transparent;stroke:var(--flag,var(--ochre));stroke-width:1.3;stroke-linejoin:round}
.arc-card-flag.done{fill:var(--flag,var(--ochre))}
.arc-scrub-line{stroke:var(--text);stroke-width:1;opacity:.3;pointer-events:none}
.arc-scrub-dot{fill:var(--gold);pointer-events:none}
.arc-readout{position:absolute;top:10px;background:var(--vellum-solid);border:1px solid var(--hair);border-radius:10px;padding:6px 10px;pointer-events:none;white-space:nowrap;font-size:12.5px;color:var(--text);z-index:2}
.arc-label-date{font-family:var(--font-eyebrow);font-size:9.5px;fill:var(--gold-text);letter-spacing:.04em;text-transform:uppercase;opacity:.9;pointer-events:none;paint-order:stroke;stroke:var(--bg);stroke-width:3px;stroke-linejoin:round}
/* Preview heights follow the viewport so a whole section fits one phone screen
   (owner, 05 Sep 2026): eyebrow, headline, one sentence, the panel. */
/* Taller since 06 Sep 2026 (owner: the line needs room for its peaks
   and troughs), still sized so a beat fits one phone screen. */
.arc-h-hero{height:clamp(260px,46svh,420px)}
.arc-h-win{height:clamp(230px,36svh,320px)}
@media(max-width:600px){
  .arc-caption{display:none}
  /* Stacked buttons share one width (owner, 07 Sep 2026). */
  .hero-actions .btn,.win-actions .btn{flex:1 1 100%}
  .arc-h-hero{height:clamp(240px,40svh,420px)}
  .char-home .ring-wrap{flex-wrap:nowrap;align-items:center}
  .char-home .ring-wrap svg{width:118px;height:118px;flex:0 0 auto}
  .char-home .ring-key{min-width:0;flex:1 1 auto;gap:5px}
  .char-home .ring-key div{font-size:12.5px}
  /* The cushion above the first line of a section equals the gutter beside
     it, so the top of the story is not further from the screen edge than its
     left is (owner, 07 Sep 2026). */
  body[data-page="home"] .scene-body{padding:var(--cushion) 0}
}
/* The replay's drawing head (src/styles/arc.css): a soft gold light
   where the line is being written, the month it has reached, and a
   thin rule down to the foot of the panel. */
.arc-play-line{stroke:var(--card-gold-hairline);stroke-width:1;stroke-dasharray:2 5}
.arc-play-glow{fill:var(--gold);opacity:.18}
.arc-play-dot{fill:var(--gold)}
.arc-play-date{fill:var(--gold-text)}
.arc-again{margin-top:8px;display:block;visibility:hidden;opacity:0;transition:opacity .4s var(--ease-out)}
.arc-again.show{visibility:visible;opacity:1}
/* A section's doors (owner, 06 Sep 2026): the gold button to the builder
   and, where there is one, a ghost to the section's own page. On a wide
   screen they sit under the words, level with the panel's middle; on a
   phone they follow the panel. */
.win-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:0}
@media(min-width:860px){
  .grid2.with-actions{grid-template-rows:auto auto;row-gap:14px}
  .grid2.with-actions>:first-child{grid-column:1;grid-row:1;align-self:end}
  .grid2.with-actions>.vellum{grid-column:2;grid-row:1/3;align-self:center}
  .grid2.with-actions>.win-actions{grid-column:1;grid-row:2;align-self:start;margin-top:0}
}
/* The hero's button follows the panel on a phone like every other
   section's (owner, 06 Sep 2026); on a wide screen it sits under the
   words as before. */
@media(min-width:1000px){
  .hero-grid.with-actions{grid-template-rows:auto auto;row-gap:14px}
  .hero-grid.with-actions>.hero-copy{grid-column:1;grid-row:1;align-self:end}
  .hero-grid.with-actions>.vellum{grid-column:2;grid-row:1/3;align-self:center}
  .hero-grid.with-actions>.hero-actions{grid-column:1;grid-row:2;align-self:start;margin-top:0}
}
/* The home page's Character panel */
.char-home .ring-wrap{gap:var(--s-3)}
.char-top{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin:var(--s-3) 0 12px}
.char-xp{display:flex;align-items:baseline;gap:8px}
.char-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.char-stat-head{display:flex;align-items:center;gap:7px;margin-bottom:6px;font-size:13.5px}
.char-stat-head b{font-weight:700}
.char-stat-head .vsmall{margin-left:auto}
.arc-rep-num{font-family:var(--font-body);font-weight:700;font-size:11px;fill:var(--bg);pointer-events:none}
.arc-stage{position:relative}
/* An arc panel: the drawing runs edge to edge under the panel's own padding, and
   the rounded corners clip it, so the line reads as continuing past the frame. */
.arc-bleed{margin-left:calc(-1 * var(--s-3));margin-right:calc(-1 * var(--s-3))}
@media(min-width:860px){.arc-bleed{margin-left:calc(-1 * var(--s-4));margin-right:calc(-1 * var(--s-4))}}


/* The embed switch (docs/MAP.md): a Character page framed inside the
   app hides the site's own chrome and keeps only the page. The Your
   turn portal goes too: a Member peeking from inside the app already
   has an arc, so the door to start one is the site's business only. */
html.embed .nav,
html.embed .drawer,
html.embed footer,
html.embed .menu-btn,
html.embed .pt-sec {
  display: none !important;
}
html.embed section.scene-sec:first-of-type {
  padding-top: 0;
}

/* The portal door, shared by every drawn Character page and every guide
   (moved here from the Character baker, 13 Sep 2026). The close is a portal: the leaves fall outside the arch, the Valley
   is alive inside it, and the doors stand in the light. Ported from
   the portal mockup (owner, 09 Sep 2026: the step from reading a world
   to entering one). */
.pt-sec{display:flex;align-items:center}
.pt-wrap{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--s-7);align-items:center}
@media(max-width:900px){.pt-wrap{grid-template-columns:1fr;gap:var(--s-5);justify-items:center;text-align:center}
  .pt-copy .eyebrow{justify-content:center}}
.pt-portal{position:relative;width:min(400px,84vw);aspect-ratio:5/7}
.pt-frame{position:absolute;inset:0;border-radius:50% 50% var(--sheet-radius) var(--sheet-radius) / 34% 34% var(--sheet-radius) var(--sheet-radius);overflow:hidden;border:1.5px solid var(--card-gold-hairline);transform:translateZ(0)}
.pt-frame canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
.pt-portal::before{content:"";position:absolute;inset:-2px;border-radius:50% 50% calc(var(--sheet-radius) + 2px) calc(var(--sheet-radius) + 2px) / 34% 34% calc(var(--sheet-radius) + 2px) calc(var(--sheet-radius) + 2px);box-shadow:0 0 34px 6px rgba(224,187,117,.34),0 0 110px 24px rgba(224,187,117,.13),inset 0 0 26px 2px rgba(224,187,117,.22);pointer-events:none;animation:ptBreathe 6s var(--ease-out) infinite}
@keyframes ptBreathe{
  0%,100%{box-shadow:0 0 34px 6px rgba(224,187,117,.34),0 0 110px 24px rgba(224,187,117,.13),inset 0 0 26px 2px rgba(224,187,117,.22)}
  50%{box-shadow:0 0 44px 9px rgba(224,187,117,.44),0 0 140px 34px rgba(224,187,117,.18),inset 0 0 34px 3px rgba(224,187,117,.3)}}
@media (prefers-reduced-motion: reduce){.pt-portal::before{animation:none}}
.pt-foot{position:absolute;left:0;right:0;bottom:0;padding:var(--s-6) var(--s-3) var(--s-3);display:flex;flex-direction:column;gap:10px;align-items:center;background:linear-gradient(180deg,rgba(24,24,24,0),rgba(24,24,24,.62) 55%,rgba(24,24,24,.8))}
.pt-foot .btn{width:100%;max-width:260px}
.pt-through{font-family:var(--font-eyebrow);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-text);margin:0 0 2px}
.pt-copy .lead{max-width:44ch}
@media(max-width:900px){.pt-copy .lead{margin-left:auto;margin-right:auto}}

/* ---------- The door: a link that takes you somewhere (13 Sep 2026) ----------
   The design rule, the app's own (DESIGN-SYSTEM section 11, and .sg-door in
   src/styles/app.css, values copied): a chevron means it opens in place, an
   arrow means it takes you somewhere. A door wears the arrow right after its
   words, is gold at rest because a link should look like one before it is
   touched, and on hover the arrow slides out 4px. Use it for any text link
   that leaves the page's current thought: read next, see every, go to. */
.door-link{display:inline-flex;align-items:center;gap:10px;color:var(--gold-text);font-family:var(--font-body);font-size:15px;font-weight:600;text-decoration:none;cursor:pointer}
.door-arrow{width:18px;height:18px;flex:0 0 auto;stroke:var(--gold-text);stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round;transition:transform .22s var(--ease-out)}
.door-link:hover .door-arrow,.door-link:focus-visible .door-arrow{transform:translateX(4px)}
@media (prefers-reduced-motion: reduce){.door-arrow{transition:none}}
