/* VenWeave — venweave.com
 *
 * Every colour here is lifted from the product's own tokens.css, not re-picked.
 * The front door is evidence about the software, so a prospect who signs up should
 * recognise the thing they land in. If a token changes in the app, change it here.
 *
 * Light neutrals are warm and faintly crimson-biased (#FBF8FA, #EAE3E7) rather than
 * true grey — the same deliberate choice the product makes. A pure mid-grey next to
 * this accent reads as unconsidered.
 *
 * One face. Inter, the brand typeface, for everything — no monospace accent and no
 * rounded badges. Both are house style for AI-tool marketing pages rather than for the
 * products this site is measured against, and the brand pack names exactly one
 * typeface. Numerals are tabular via font-variant-numeric, which is what the mono was
 * actually buying. The lockups are outlined SVG and carry no font dependency, so a
 * failed font load degrades the body copy and never the logo.
 *
 * NO SCRIPT RUNS ON THIS PAGE. The CSP in vercel.json is `default-src 'none'` with
 * no script-src at all, so every interaction and every animation here is CSS. That
 * is a deliberate posture, not a limitation to route around: the mobile menu is a
 * <details>, and the scroll reveals use `animation-timeline: view()`. Anything that
 * would need JS has to justify loosening the CSP first.
 */

/* Self-hosted as of 9 Aug 2026 -- was fonts.googleapis.com + fonts.gstatic.com.
 * One file, not four: Google serves Inter's woff2 as a single variable-weight
 * resource and points every discrete-weight @font-face at the same URL, which is
 * why all four rules below share one src -- the browser fetches it once and
 * renders each declared weight from its own variation axis. Confirmed by diffing
 * https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap
 * against a modern-browser UA: identical hash on all four blocks. Only the latin
 * subset is kept -- this site's copy is American-English body text, and the CSS
 * only ever declared 400/500/600/700 with no italic (grep the weights before
 * touching this if that ever changes). Downloaded, not synthesised: this is the
 * same file Google was already serving, just no longer fetched from Google.
 */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: light dark;

  --paper:            #FFFFFF;
  --ground:           #FBF8FA;
  --raised:           #F7F2F5;

  --ink:              #191218;
  --ink-muted:        #756971;
  --ink-faint:        #7F7279;

  --line:             #EAE3E7;
  --line-soft:        #F3EDF0;

  --accent:           #D81B60;
  --accent-strong:    #9E1250;
  --accent-wash:      #FDF2F7;
  --accent-contrast:  #FFFFFF;

  /* The official pack's --vw-pop-on-light -- the colour "VenWeave" was set in inside
     the lockup's own tagline, wherever this site echoes that tagline in markup. Equals
     --accent exactly in light mode; it earns its own token because the dark value
     below does not equal any existing one. Deliberately NOT pairing this with the
     pack's --vw-muted-on-light (#8A93A3): that measures 3.10:1 on white, below AA for
     text this small. The pack's own README says its hexes are "sampled from a
     screenshot," not contrast-checked -- the grey half of the tagline stays on this
     site's own --ink-muted (5.23:1), which does the same job and passes. */
  --tagline-pop:      #D81B60;

  /* Lifted from the application's --warning pair, for the one caution row the handoff
     illustration redraws. 5.16:1 here; the dark pair below is deliberately higher. */
  --warn:             #8A5A05;
  --warn-wash:        #F3EFE6;

  /* The brand ramp, 135deg, exactly as the pack specifies it -- bright to deep. */
  --gradient: linear-gradient(135deg, #F0468D 0%, #D81B60 55%, #9E1250 100%);

  /* Same three stops, same angle, ramp reversed -- for the one place a gradient sits
     BEHIND body copy. Text lives in the top-left corner, and on the canonical ramp
     that corner is #F0468D, which gives white only 3.52:1 -- fine for the 34px
     heading, a fail for the 17px paragraph under it. Reversed, that corner is #9E1250
     at 7.91:1. No hue is re-coloured and no second family is introduced; the rule is
     that the text-bearing end of the ramp is the high-contrast end. */
  --gradient-cta: linear-gradient(135deg, #9E1250 0%, #D81B60 55%, #F0468D 100%);

  /* The hero wash. Three soft radial stops from the brand ramp, all under 18% alpha,
     so the page still reads as white paper with light falling on it rather than as a
     coloured section. Kept as tokens because the dark palette needs different values,
     not a different opacity of the same ones. */
  --mesh-1: rgb(240 70 141 / 16%);
  --mesh-2: rgb(158 18 80 / 9%);
  --mesh-3: rgb(216 27 96 / 8%);
  --grid-line: rgb(25 18 24 / 5%);

  /* One elevation scale, four steps, used everywhere. Random per-component shadow
     values are the single most reliable tell of a page assembled rather than designed. */
  --shadow-sm:   0 1px 2px rgb(25 18 24 / 5%);
  --shadow-card: 0 1px 2px rgb(25 18 24 / 4%), 0 8px 24px -12px rgb(25 18 24 / 10%);
  --shadow-lift: 0 2px 4px rgb(25 18 24 / 5%), 0 16px 40px -16px rgb(25 18 24 / 16%);
  --shadow-deep: 0 4px 8px rgb(25 18 24 / 4%), 0 32px 64px -24px rgb(25 18 24 / 22%);

  /* 4pt scale, matching the product's spacing rhythm. */
  --s1: .25rem;  --s2: .5rem;   --s3: .75rem;  --s4: 1rem;
  --s5: 1.25rem; --s6: 1.5rem;  --s8: 2rem;    --s10: 2.5rem;
  --s12: 3rem;   --s16: 4rem;   --s20: 5rem;   --s24: 6rem;

  --measure: 36rem;      /* ~68 characters of Inter at 1.0625rem */
  --page: 76rem;
  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 18px;

  --sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Line-item kind colours, copied exactly from the product's tokens.css. The dashboard
     illustration in the hero renders the same four series the real chart does, so they
     have to be the same four values -- an approximation eyeballed off a screenshot is
     how a "based on the real app" mockup stops matching the real app.
     The product's own note on these: hue separation between the kinds is real, VALUE
     separation is not (equipment, labour and F&B sit within 0.01 luminance of each
     other). Anywhere two of them touch -- which is exactly the stacked chart below --
     they need a structural seam rather than relying on the fills to differ. Hence the
     2px gap between stacked segments. */
  --kind-equipment: #D4145A;
  --kind-labour:    #0E7983;
  --kind-fb:        #9F5E00;

  --ease: cubic-bezier(.2, .7, .3, 1);
}

/* The dark ramp is its own palette, not an inversion. The light gradient goes nearly
   black against ink, so it is replaced rather than reused — the brand pack is explicit
   about that and it is the easiest rule here to break by accident. */
@media (prefers-color-scheme: dark) {
  :root {
    --paper:           #16121A;
    --ground:          #0F0C12;
    --raised:          #221C28;

    --ink:             #F3F0F4;
    --ink-muted:       #A79FAB;
    --ink-faint:       #8D8494;

    --line:            #2C2632;
    --line-soft:       #221D28;

    --accent:          #FF4D85;
    --accent-strong:   #FF8FB0;
    --accent-wash:     #2A121D;
    --accent-contrast: #1A0410;

    /* The pack's --vw-pop-on-dark -- a third pink, distinct from both --accent and
       --accent-strong up here. 7.09:1 on this theme's --paper, comfortably clear. */
    --tagline-pop:     #FF6FA3;

    /* The application's dark --warning pair, 7.40:1 -- higher than the light pair, not
       lower, because a muted amber on near-black loses legibility faster than on paper. */
    --warn:            #D4A03C;
    --warn-wash:       #1E181B;

    --gradient: linear-gradient(135deg, #FF85B0 0%, #E0356F 100%);
    /* Dark needs no reversal: the canonical dark ramp already puts its bright end
       (#FF85B0) top-left, which against #1A0410 text is 8.64:1. Same rule, and here
       the pack's own order already satisfies it. */
    --gradient-cta: linear-gradient(135deg, #FF85B0 0%, #E0356F 100%);

    /* Lower alpha than light mode, and the bright end of the dark ramp rather than
       the deep end -- a deep-crimson glow on a near-black ground just reads as dirt. */
    --mesh-1: rgb(255 77 133 / 13%);
    --mesh-2: rgb(224 53 111 / 9%);
    --mesh-3: rgb(255 143 176 / 6%);
    --grid-line: rgb(243 240 244 / 5%);

    --shadow-sm:   0 1px 2px rgb(0 0 0 / 40%);
    --shadow-card: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px -12px rgb(0 0 0 / 60%);
    --shadow-lift: 0 2px 4px rgb(0 0 0 / 45%), 0 16px 40px -16px rgb(0 0 0 / 70%);
    --shadow-deep: 0 4px 8px rgb(0 0 0 / 45%), 0 32px 64px -24px rgb(0 0 0 / 80%);
  }
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}

/* Do NOT put `overflow-x: hidden` on body to contain the bleeding decorations. Setting
   either axis to something other than `visible` makes the other axis compute to `auto`,
   so body becomes its own scroll container -- and on a page this tall Chrome then stops
   painting everything below roughly 4000px while layout, hit-testing and computed
   opacity all still report correct. It looks exactly like a blank footer bug with no
   cause. The bleeds are clipped by their own parents instead: .hero and .close__card
   each carry `overflow: hidden`, which is where the clipping belongs. */

img, svg { max-width: 100%; height: auto; display: block; }

h1, h2, h3 { margin: 0; line-height: 1.12; letter-spacing: -.025em; text-wrap: balance; font-weight: 600; }
h1 { font-size: clamp(2.25rem, 4.8vw, 3.75rem); letter-spacing: -.036em; }
h2 { font-size: clamp(1.75rem, 3.4vw, 2.5rem); letter-spacing: -.03em; }
h3 { font-size: 1.0625rem; letter-spacing: -.012em; }
p  { margin: 0; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-strong); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.skip {
  position: absolute; left: var(--s4); top: -3rem; z-index: 100;
  padding: var(--s2) var(--s4); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--ink); border: 1px solid var(--line);
  font-size: .875rem; font-weight: 500; text-decoration: none;
  transition: top .15s var(--ease);
}
.skip:focus { top: var(--s4); }

.wrap { width: 100%; max-width: var(--page); margin-inline: auto; padding-inline: var(--s6); }
@media (max-width: 30rem) { .wrap { padding-inline: var(--s4); } }

.prose { max-width: var(--measure); }
.lede { font-size: clamp(1.0625rem, 1.5vw, 1.1875rem); color: var(--ink-muted); line-height: 1.62; }
/* Set here rather than as an inline style so the CSP can forbid inline styles
   outright -- `style-src 'unsafe-inline'` to space one paragraph is a bad trade. */
.prose .lede { margin-top: var(--s5); }

/* ── icons ──────────────────────────────────────────────────────────────── */

/* The sprite itself must stay in the layout tree for <use> to resolve reliably,
   so it is collapsed rather than display:none. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.ico {
  width: 22px; height: 22px; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.75;
  stroke-linecap: round; stroke-linejoin: round;
}
.ico--sm { width: 16px; height: 16px; stroke-width: 2; }
/* 13px, for the 12px labels inside the handoff panels. Stroke goes up again as the box
   comes down -- a 1.75 stroke on a 13px glyph reads as grey, not as a line. */
.ico--xs { width: 13px; height: 13px; stroke-width: 2.25; }

/* ── section rhythm ─────────────────────────────────────────────────────── */

/* Section rhythm lives on one class only. Nothing else sets block padding on a
   section, so there is no pair of selectors quietly cancelling each other out. */
/* The header is sticky, so an anchor jump would otherwise land with the section
   heading tucked underneath it. 5rem clears the 4.25rem bar plus a little air. Also
   applied to #main itself, which is what the #talk-access tray's close controls point
   at -- that tray is not opened from a plan card, so #plans is the wrong place to
   return a dismissed visitor to. */
#main, main > section[id] { scroll-margin-top: 5rem; }

/* Trimmed from s24/s16 on 10 Aug 2026 -- the site owner's own read was "I feel like
   I am scrolling forever." One step down the existing scale, not an arbitrary value:
   still the most generous padding on the page, just no longer the largest token
   available. See the README for the rest of what changed alongside this. */
.band { padding-block: var(--s20); }
@media (max-width: 48rem) { .band { padding-block: var(--s12); } }
.band--paper { background: var(--paper); border-block: 1px solid var(--line); }

/* Inter, letterspaced small caps. Not a monospace, and not a rounded badge -- both of
   those are house styles of AI-tool landing pages rather than of the products this site
   is measured against, and the brand pack names exactly one typeface. */
.eyebrow {
  display: block; margin-bottom: var(--s4);
  font-size: .75rem; font-weight: 600; letter-spacing: .11em; text-transform: uppercase;
  color: var(--accent);
}
.eyebrow--hero { margin-bottom: var(--s5); }
/* The slogan keeps the wordmark's own casing. Every other eyebrow is uppercased, but
   uppercasing this one throws away the capital W that makes VenWeave read as a single
   word rather than as "ven weave" -- and a wordmark that can be re-cased by a text
   transform is not being treated as a wordmark. */
.eyebrow--slogan {
  text-transform: none; letter-spacing: -.005em;
  font-size: .875rem; font-weight: 700;
  color: var(--ink);
}

/* ── slogan ─────────────────────────────────────────────────────────────── */

/* Three beats: the two audiences, then the answer. The wordmark carries the brand
   gradient so the slogan and the lockup read as the same object. */
.slogan { font-weight: 700; letter-spacing: -.025em; line-height: 1.15; text-wrap: balance; }

/* Solid --tagline-pop by default -- the colour the pack sets "VenWeave" in inside the
   lockup's own tagline, not this site's generic --accent-strong. The gradient's light
   end (#F0468D) measures ~3.4:1 on paper, which clears the 3:1 large-text threshold
   but fails the 4.5:1 that anything below 24px needs -- so only the display-size
   placement gets the ramp; everywhere else takes the flat colour. */
.slogan__mark { color: var(--tagline-pop); }

.slogan--band {
  margin-top: var(--s10); padding-top: var(--s10);
  border-top: 1px solid var(--line);
  font-size: clamp(1.75rem, 5vw, 3rem);
  text-align: center;
}
.slogan--band .slogan__mark {
  background: var(--gradient);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}

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

.site-head {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  border-bottom: 1px solid var(--line);
}
/* Nine top-level nav items plus two CTAs need more room than --page (76rem) gives
   every other .wrap on the site -- scoped to the header alone rather than widening
   --page itself, which would also stretch every section's content measure. Started at
   eleven flat links (needed 96rem); folding the three comparison pages into one
   Compare disclosure brought the real minimum down to 82.5rem, verified empirically --
   84rem matches that plus a small margin rather than carrying the old, now-oversized
   96rem forward. */
.site-head .wrap { max-width: 84rem; }
.site-head__inner {
  display: flex; align-items: center; gap: var(--s6);
  min-height: 4.25rem;
}
/* Row again. It was briefly a column with a separate markup slogan stacked under it,
   for the stretch when the lockup files had their baked-in tagline stripped out. Now
   that the real pack's lockup-horizontal-*.svg is back in assets/ -- tagline included,
   at its native size -- that markup line would just repeat what the image already
   says, directly underneath it. text-decoration: none stays regardless: this anchor
   holds only an image today, but the browser's default link underline would still
   apply to any text a future edit puts back in it -- that gap is what caused the
   underlined slogan the first time. */
.brand { flex: 0 0 auto; display: flex; align-items: center; text-decoration: none; }
/* 190px, above the pack's 160px tagline-legibility floor -- a real constraint now that
   the lockup carries its tagline again, not headroom. Below 160px, switch to
   lockup-horizontal-notagline-*.svg (see README) rather than shrinking this further. */
.brand img { width: 190px; }
.brand__dark { display: none; }
@media (prefers-color-scheme: dark) {
  .brand__light { display: none; }
  .brand__dark  { display: block; }
}

.site-nav { margin-left: auto; display: flex; align-items: center; gap: var(--s4); }
/* Eleven links plus two CTAs, added 9 Aug 2026 (three comparison pages, Security,
   Privacy, alongside the original six section anchors) -- tighter than the .875rem/s2
   original padding to keep as many viewports as possible off the collapse breakpoint
   below, not because dense nav is the goal on its own. */
.site-nav__links { display: flex; gap: 2px; }
.site-nav__links a {
  display: inline-flex; align-items: center; min-height: 40px;
  padding-inline: var(--s2);
  color: var(--ink-muted); font-size: .875rem; font-weight: 500; text-decoration: none;
  border-radius: var(--radius-sm); white-space: nowrap;
  transition: color .15s var(--ease), background-color .15s var(--ease);
}
.site-nav__links a:hover { color: var(--ink); background: var(--raised); }

/* The three comparison pages, grouped under one disclosure rather than three flat
   links -- added 9 Aug 2026, same day they were unbundled, once eleven flat links
   proved to be the wrong call for the header specifically (the footer keeps them
   flat; a footer column has no width fight to lose). Same <details> mechanism as
   .menu below, sized to sit inline in the flex row instead of pinned to a corner. */
.nav-drop { position: relative; }
.nav-drop summary {
  display: inline-flex; align-items: center; gap: 3px; min-height: 40px;
  padding-inline: var(--s2);
  color: var(--ink-muted); font-size: .875rem; font-weight: 500;
  border-radius: var(--radius-sm); white-space: nowrap; cursor: pointer;
  list-style: none;
  transition: color .15s var(--ease), background-color .15s var(--ease);
}
.nav-drop summary::-webkit-details-marker { display: none; }
.nav-drop summary:hover, .nav-drop[open] summary { color: var(--ink); background: var(--raised); }
.nav-drop__chevron { transition: transform .15s var(--ease); }
.nav-drop[open] .nav-drop__chevron { transform: rotate(180deg); }
.nav-drop__panel {
  position: absolute; left: 0; top: calc(100% + var(--s2));
  min-width: 11rem; padding: var(--s2);
  display: grid; gap: 2px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lift);
  z-index: 10;
}
.nav-drop__panel a {
  display: flex; align-items: center; min-height: 40px;
  padding-inline: var(--s3); border-radius: var(--radius-sm);
  color: var(--ink); font-size: .875rem; font-weight: 500; text-decoration: none;
}
.nav-drop__panel a:hover { background: var(--raised); color: var(--accent); }

.site-nav__cta { display: flex; align-items: center; gap: var(--s2); }

/* The menu must appear at exactly the width the link row disappears. On the first pass
   these were 60rem and 46rem, which left every viewport between 737px and 960px with no
   section navigation at all -- the links were gone and the menu had not arrived.
   Went to 92rem on 9 Aug 2026 when eleven flat links needed 90.5rem; came back down to
   84rem the same day once three of those eleven collapsed into one Compare disclosure
   and the real minimum dropped to 82.5rem, verified empirically both times rather than
   estimated. .wrap has a hard max-width -- past it, a wider window adds no room, so
   anything below this threshold would show a row that visibly overflows rather than
   one that is merely tight. */
@media (max-width: 84rem) {
  .site-nav__links { display: none; }
  .site-nav__cta .btn--quiet { display: none; }   /* Log in moves into the menu */
}
/* Below this the lockup, the CTA and the menu button stop fitting on one line. The CTA
   is in the menu panel, and the hero's own Request access button is one scroll away. */
@media (max-width: 30rem) { .site-nav { display: none; } }

/* ── mobile menu (no script) ────────────────────────────────────────────── */

.menu { display: none; margin-left: auto; position: relative; }
@media (max-width: 84rem) { .menu { display: block; } }

.menu__button {
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--ink);
  cursor: pointer; list-style: none;
}
.menu__button::-webkit-details-marker { display: none; }
.menu[open] .menu__button { background: var(--raised); border-color: var(--ink-faint); }

.menu__panel {
  position: absolute; right: 0; top: calc(100% + var(--s3));
  min-width: 14rem; padding: var(--s2);
  display: grid; gap: 2px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lift);
}
.menu__panel a {
  display: flex; align-items: center; min-height: 44px;
  padding-inline: var(--s3); border-radius: var(--radius-sm);
  color: var(--ink); font-size: .9375rem; font-weight: 500; text-decoration: none;
}
.menu__panel a:hover { background: var(--raised); color: var(--accent); }
/* So the primary action is never unreachable at the widths where the header CTA is
   hidden. */
.menu__cta {
  margin-top: var(--s2); justify-content: center;
  background: var(--accent); color: var(--accent-contrast); font-weight: 600;
}
.menu__cta:hover { background: var(--accent-strong); color: var(--accent-contrast); }

/* ── buttons ────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 42px; padding: var(--s2) var(--s5);
  border: 1px solid transparent; border-radius: var(--radius-sm);
  font: inherit; font-size: .9375rem; font-weight: 600;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: transform .15s var(--ease), box-shadow .15s var(--ease),
              background-color .15s var(--ease), border-color .15s var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn .ico { transition: transform .2s var(--ease); }
.btn:hover .ico { transform: translateX(2px); }

.btn--primary { background: var(--accent); color: var(--accent-contrast); box-shadow: var(--shadow-card); }
.btn--primary:hover { background: var(--accent-strong); color: var(--accent-contrast); box-shadow: var(--shadow-lift); }

.btn--ghost { background: var(--paper); color: var(--ink); border-color: var(--line); box-shadow: var(--shadow-sm); }
.btn--ghost:hover { background: var(--raised); color: var(--ink); border-color: var(--ink-faint); }

.btn--quiet { background: transparent; color: var(--ink-muted); }
.btn--quiet:hover { background: var(--raised); color: var(--ink); }

.btn--lg { min-height: 52px; padding-inline: var(--s6); font-size: 1rem; }

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

.hero {
  position: relative; overflow: hidden;
  background: var(--paper); border-bottom: 1px solid var(--line);
}
.hero > .wrap { position: relative; z-index: 1; }

/* Three soft radial stops rather than one linear wash. A single gradient across a
   full-width section reads as a banner; overlapping radials read as light, which is
   the effect the reference sites get and the reason their heroes have depth without
   an image. All of it lives under 18% alpha so body copy contrast is untouched. */
.hero__mesh {
  position: absolute; inset: -10% -5% 0;
  pointer-events: none;
  /* Centres deliberately sit outside the copy column: top-left above the fold line,
     right-hand behind the (opaque) product panel, bottom-centre under the proof strip.
     Measured, not assumed -- the darkest pixel under any text in this section is
     rgb(254,252,253), so ink-muted holds 5.1:1 while the section still reads as lit. */
  background:
    radial-gradient(52rem 34rem at  8% -10%, var(--mesh-1), transparent 62%),
    radial-gradient(46rem 32rem at 94%   8%, var(--mesh-2), transparent 60%),
    radial-gradient(38rem 26rem at 54% 106%, var(--mesh-3), transparent 64%);
}

/* Masked so the ruling fades out before it reaches the copy -- an un-masked grid
   behind a paragraph is texture competing with text. */
.hero__grid-lines {
  position: absolute; inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: 76px 76px;
  -webkit-mask-image: radial-gradient(72% 62% at 50% 24%, #000 0%, transparent 76%);
          mask-image: radial-gradient(72% 62% at 50% 24%, #000 0%, transparent 76%);
}

.hero__inner {
  display: grid; gap: var(--s12);
  padding-block: clamp(var(--s16), 8vw, 6.5rem) var(--s12);
}
@media (min-width: 64rem) {
  .hero__inner {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: var(--s16); align-items: center;
  }
}

.hero__copy h1 { max-width: 16ch; }
.hero__copy .lede { margin-top: var(--s6); max-width: 34rem; }
.hero__actions { margin-top: var(--s8); display: flex; flex-wrap: wrap; gap: var(--s3); }
/* ink-muted, not ink-faint. ink-faint clears 4.5:1 on flat paper by 0.08 and this line
   sits over the mesh, which spends that margin. It is also the one sentence on the page
   that says the software is real and in daily use, so it should not be the faintest
   thing in the hero. Same reasoning for .surface__caption and the footer. */
.hero__note {
  margin-top: var(--s6); max-width: 30rem;
  font-size: .875rem; line-height: 1.55; color: var(--ink-muted);
}

/* ── the product illustration ───────────────────────────────────────────── */

/* Drawn in markup, not exported. It re-themes with the tokens in dark mode, stays
   sharp on any display, adds no image weight, and — the part that matters — cannot
   drift out of date the way a screenshot silently does. */
.hero__panel { position: relative; }

.surface {
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--paper); box-shadow: var(--shadow-deep);
  overflow: hidden;
}
@media (min-width: 64rem) {
  /* A degree and a half. Enough to read as a rendered object rather than a diagram,
     not enough to make the figures inside look like a stock photo of a laptop. */
  .surface { rotate: -1.2deg; transform-origin: 60% 50%; }
}

/* Sidebar + content, the shape of the real dashboard rather than a generic browser
   window with three traffic-light dots. The dots are the giveaway on a fake screenshot:
   the product is not a browser, and a prospect who has seen the app should recognise
   the rail, the KPI row and the revenue chart. */
.app { display: grid; grid-template-columns: 8.5rem minmax(0, 1fr); }

.app__rail {
  padding: var(--s4) var(--s3); display: grid; gap: 2px; align-content: start;
  background: var(--ground); border-right: 1px solid var(--line);
}
.app__mark { width: 22px; margin: 0 var(--s2) var(--s4); opacity: .9; }
.app__group {
  padding: 0 var(--s2) var(--s1);
  font-size: .625rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-muted);
}
.app__nav {
  display: flex; align-items: center; gap: var(--s2);
  padding: 5px var(--s2); border-radius: 6px;
  font-size: .75rem; color: var(--ink-muted); white-space: nowrap;
}
.app__nav .ico { width: 13px; height: 13px; }
.app__nav.is-active { background: var(--accent-wash); color: var(--accent-strong); font-weight: 600; }

.app__main { min-width: 0; padding: var(--s4); display: grid; gap: var(--s4); }
.app__top { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.app__title { font-size: .9375rem; font-weight: 600; letter-spacing: -.015em; }
.app__scope {
  padding: 3px var(--s2); border-radius: 6px;
  border: 1px solid var(--line); background: var(--paper);
  font-size: .6875rem; color: var(--ink-muted); white-space: nowrap;
}

.kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s2); }
.kpi {
  min-width: 0; padding: var(--s3);
  border: 1px solid var(--line); border-radius: 8px; background: var(--paper);
}
.kpi__label, .kpi__foot, .kpi__value { display: block; }
.kpi__label { font-size: .625rem; font-weight: 500; color: var(--ink-muted); }
.kpi__value { margin-top: 3px; font-size: 1.0625rem; font-weight: 600; letter-spacing: -.03em; }
.kpi__foot { margin-top: 2px; font-size: .5625rem; color: var(--ink-muted); }
@media (max-width: 34rem) { .kpi__foot { display: none; } }

.rk { padding: var(--s3); border: 1px solid var(--line); border-radius: 8px; background: var(--paper); }
.rk__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); }
.rk__title { font-size: .75rem; font-weight: 600; }
.rk__legend { display: flex; flex-wrap: wrap; gap: var(--s3); margin-left: auto; }
.rk__legend span { display: inline-flex; align-items: center; gap: 5px; font-size: .625rem; color: var(--ink-muted); }
.sw { width: 8px; height: 8px; border-radius: 2px; }
.sw--equip { background: var(--kind-equipment); }
.sw--lab   { background: var(--kind-labour); }
.sw--fb    { background: var(--kind-fb); }

.rk__plot {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--s3);
  height: 88px; margin-top: var(--s3);
}
/* The 2px gap is the structural seam the product's own token notes call for: these three
   fills are within 0.01 luminance of one another, so where they stack they would read as
   one block without it. It is load-bearing, not styling. */
.rk__col { display: flex; flex-direction: column; justify-content: flex-end; gap: 2px; }
.seg { display: block; border-radius: 2px; }
.seg--equip { background: var(--kind-equipment); }
.seg--lab   { background: var(--kind-labour); }
.seg--fb    { background: var(--kind-fb); }
/* Heights per column, set here rather than inline so the CSP can keep forbidding
   style attributes outright. */
.rk__col:nth-child(1) .seg--equip { height: 26%; } .rk__col:nth-child(1) .seg--lab { height: 14%; } .rk__col:nth-child(1) .seg--fb { height: 7%; }
.rk__col:nth-child(2) .seg--equip { height: 34%; } .rk__col:nth-child(2) .seg--lab { height: 17%; } .rk__col:nth-child(2) .seg--fb { height: 11%; }
.rk__col:nth-child(3) .seg--equip { height: 30%; } .rk__col:nth-child(3) .seg--lab { height: 21%; } .rk__col:nth-child(3) .seg--fb { height: 9%; }
.rk__col:nth-child(4) .seg--equip { height: 45%; } .rk__col:nth-child(4) .seg--lab { height: 24%; } .rk__col:nth-child(4) .seg--fb { height: 14%; }
.rk__col:nth-child(5) .seg--equip { height: 38%; } .rk__col:nth-child(5) .seg--lab { height: 19%; } .rk__col:nth-child(5) .seg--fb { height: 12%; }
.rk__col:nth-child(6) .seg--equip { height: 52%; } .rk__col:nth-child(6) .seg--lab { height: 27%; } .rk__col:nth-child(6) .seg--fb { height: 16%; }

.rk__axis {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--s3);
  margin-top: 6px; font-size: .5625rem; color: var(--ink-muted); text-align: center;
}

.mrg {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 3px var(--s3);
  padding: var(--s3); border: 1px solid var(--line); border-radius: 8px; background: var(--paper);
}
.mrg__label { grid-column: 1 / -1; font-size: .625rem; font-weight: 600; color: var(--ink-muted); }
.mrg__name { font-size: .75rem; font-weight: 500; }
.mrg__val { font-size: .75rem; font-weight: 600; }
.mrg__bar { grid-column: 1 / -1; height: 4px; border-radius: 2px; background: var(--line-soft); overflow: hidden; }
.mrg__bar i { display: block; width: 65%; height: 100%; border-radius: 2px; background: var(--accent); }

.surface__caption {
  margin-top: var(--s3); text-align: right;
  font-size: .6875rem; color: var(--ink-muted);
}

/* Panel entrance. Plays once — bars rise, KPI cards stagger in just after,
   the margin bar fills last — then holds still. No loop, so it never
   competes with the headline for attention after the first pass. */
.kpi { opacity: 0; animation: panel-rise .5s ease-out .1s both; }
.kpi:nth-child(2) { animation-delay: .18s; }
.kpi:nth-child(3) { animation-delay: .26s; }
@keyframes panel-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

.rk__col .seg { transform: scaleY(0); transform-origin: bottom; animation: panel-grow .6s cubic-bezier(.2,.7,.3,1) both; }
.rk__col:nth-child(1) .seg { animation-delay: .05s; }
.rk__col:nth-child(2) .seg { animation-delay: .12s; }
.rk__col:nth-child(3) .seg { animation-delay: .19s; }
.rk__col:nth-child(4) .seg { animation-delay: .26s; }
.rk__col:nth-child(5) .seg { animation-delay: .33s; }
.rk__col:nth-child(6) .seg { animation-delay: .4s; }
@keyframes panel-grow { to { transform: scaleY(1); } }

.mrg__bar i { width: 0; animation: panel-fill 1s cubic-bezier(.2,.7,.3,1) .55s both; }
@keyframes panel-fill { to { width: 65%; } }

@media (prefers-reduced-motion: reduce) {
  .kpi, .rk__col .seg, .mrg__bar i { animation: none !important; opacity: 1 !important; transform: none !important; }
  .mrg__bar i { width: 65% !important; }
}

/* Kept below the component rules on purpose. These override single declarations that
   the blocks above also set, and at equal specificity the later rule wins -- writing
   this media query above `.app__rail { display: grid }` silently does nothing, which
   is exactly what it did on the first pass. */
@media (max-width: 30rem) {
  .app { grid-template-columns: 1fr; }
  .app__rail { display: none; }
  .app__main { padding: var(--s3); gap: var(--s3); }
  .kpis { grid-template-columns: 1fr 1fr; }
  .kpi:last-child { display: none; }   /* two tiles read; three at 300px do not */
  .rk__legend { margin-left: 0; }
}
@media (min-width: 64rem) { .surface__caption { margin-top: var(--s4); } }

/* ── proof strip ────────────────────────────────────────────────────────── */

/* Deliberately not a logo wall. There are no outside customers to name yet, and a row
   of invented grey logos would be exactly the sort of thing the copy above argues
   against. Every line here is something the codebase can back. */
.proof {
  position: relative; z-index: 1;
  margin: 0; padding: var(--s5) 0 0; list-style: none;
  border-top: 1px solid var(--line);
  display: grid; gap: var(--s3) var(--s6);
  padding-bottom: var(--s12);
}
@media (min-width: 40rem) { .proof { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .proof { grid-template-columns: repeat(4, 1fr); } }
.proof li {
  display: flex; align-items: center; gap: var(--s2);
  font-size: .8125rem; line-height: 1.45; color: var(--ink-muted);
}
.proof .ico { color: var(--accent); }

/* ── the contrast pair ──────────────────────────────────────────────────── */

/* Two columns because this section genuinely is a comparison — the claim is that
   the category sorts into inventory-first and money-first tools. Anywhere the
   content is not actually a pair, it does not get this treatment. */
.versus { display: grid; gap: var(--s4); margin-top: var(--s10); }
@media (min-width: 44rem) { .versus { grid-template-columns: 1fr 1.08fr; gap: var(--s5); align-items: start; } }

.versus__card {
  padding: var(--s8); border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--paper);
}
/* The one card that is the argument gets the weight: brand border, wash, and the
   only shadow in the pair. The other is deliberately flat -- that asymmetry is the
   point being made, so it should be visible before either heading is read. */
.versus__card--ours {
  border-color: color-mix(in srgb, var(--accent) 34%, var(--line));
  background: var(--accent-wash);
  box-shadow: var(--shadow-card);
}
.versus__card h3 { margin-bottom: var(--s3); display: flex; align-items: center; gap: var(--s2); }
.versus__card--ours h3 { color: var(--accent-strong); }
.versus__card p { color: var(--ink-muted); font-size: .9375rem; }
.versus__list { margin: var(--s5) 0 0; padding: 0; list-style: none; display: grid; gap: var(--s3); }
.versus__list li { position: relative; padding-left: var(--s6); font-size: .9375rem; color: var(--ink-muted); }
.versus__list li::before {
  content: ""; position: absolute; left: 0; top: .52em;
  width: 8px; height: 8px; border-radius: 2px; background: var(--ink-faint);
}
.versus__card--ours .versus__list li { color: var(--ink); }
.versus__card--ours .versus__list li::before { background: var(--accent); }

.versus__more { margin-top: var(--s6); font-size: .9375rem; color: var(--ink-muted); }
.versus__more a { font-weight: 600; color: var(--accent); }

/* ── module bento ───────────────────────────────────────────────────────── */

/* Six equal cards in a 3x2 grid is the shape of a page that has stopped making
   decisions. A six-column track lets Reporting take the width its illustration needs
   and People take the width its eight tags need, and the unevenness gives the eye an
   order to read them in. */
.modules { display: grid; gap: var(--s4); margin-top: var(--s10); }
@media (min-width: 44rem) {
  .modules { grid-template-columns: repeat(6, 1fr); }
  .module { grid-column: span 3; }
  .module--wide { grid-column: span 6; }
  .module--full { grid-column: span 6; }
}
@media (min-width: 64rem) {
  .module { grid-column: span 2; }
  .module--wide { grid-column: span 4; }
  .module--full { grid-column: span 6; }
}

.module {
  display: flex; flex-direction: column;
  padding: var(--s6);
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg);
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), transform .2s var(--ease);
}
.module:hover {
  border-color: color-mix(in srgb, var(--accent) 26%, var(--line));
  box-shadow: var(--shadow-card);
  transform: translateY(-2px);
}
/* A bare icon, not a tinted rounded square. The chip treatment is the single most
   common signature of a generated marketing page, and the product's own sidebar draws
   these icons plain -- so plain is both less generic and more faithful. */
.module__ico { display: inline-flex; margin-bottom: var(--s4); color: var(--accent); }
.module__ico .ico { width: 24px; height: 24px; }
.module h3 { margin-bottom: var(--s2); }
.module p { font-size: .9375rem; color: var(--ink-muted); }
/* Set as a run of text with middot separators rather than a row of rounded pills.
   Pills read as tags you can click, these are not interactive, and a grid of them is
   the most recognisable tell of a generated page. */
.module__items {
  margin: var(--s4) 0 0; padding: var(--s4) 0 0; list-style: none;
  display: flex; flex-wrap: wrap;
  border-top: 1px solid var(--line-soft);
  font-size: .8125rem; color: var(--ink-muted);
}
.module__items li:not(:last-child)::after {
  content: "·"; margin-inline: .45em; color: var(--ink-faint);
}

.module--wide { flex-direction: column; gap: var(--s6); }
@media (min-width: 52rem) {
  .module--wide { flex-direction: row; align-items: center; gap: var(--s8); }
  .module__text { flex: 1 1 55%; }
  .module__viz  { flex: 1 1 45%; }
}
.module--wide .module__items { margin-top: var(--s4); }

/* A six-bar paired chart. Not real data and not presented as any -- it is a shape
   that says "this section produces charts", which is what the cell is for. */
.spark {
  display: flex; align-items: flex-end; gap: var(--s2);
  height: 108px; padding: var(--s4);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--ground);
}
/* Same two series colours the app uses, not a tinted brand ramp -- the point of the
   cell is that this section produces the product's charts. */
.spark__bar { flex: 1; border-radius: 3px 3px 2px 2px; }
.spark__bar--a { height: 42%; background: var(--kind-equipment); }
.spark__bar--b { height: 30%; background: var(--kind-labour); }
.spark__bar--c { height: 68%; background: var(--kind-equipment); }
.spark__bar--d { height: 44%; background: var(--kind-labour); }
.spark__bar--e { height: 92%; background: var(--kind-equipment); }
.spark__bar--f { height: 58%; background: var(--kind-labour); }
.spark__key {
  display: flex; gap: var(--s4); margin-top: var(--s3);
  font-size: .75rem; color: var(--ink-muted);
}
.spark__key span { display: inline-flex; align-items: center; gap: 6px; }
.dot { width: 8px; height: 8px; border-radius: 2px; background: var(--kind-equipment); }
.dot--fb { background: var(--kind-labour); }

/* ── collaboration / the note board ─────────────────────────────────────── */

.collab { display: grid; gap: var(--s8); margin-top: var(--s10); align-items: start; }
@media (min-width: 62rem) {
  .collab { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: var(--s16); }
}

.board {
  padding: var(--s5);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--paper); box-shadow: var(--shadow-deep);
}
.board__head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2) var(--s3);
  padding-bottom: var(--s4); border-bottom: 1px solid var(--line);
}
.board__event { font-size: .9375rem; font-weight: 600; letter-spacing: -.015em; }
.board__meta { font-size: .75rem; color: var(--ink-muted); }

.board__notes { display: grid; gap: var(--s4); padding: var(--s5) var(--s2); }
@media (min-width: 30rem) { .board__notes { grid-template-columns: 1fr 1fr; gap: var(--s4) var(--s3); } }

/* One tint mechanism for every author, mixed against --paper, so the board themes
   itself in dark mode without a second palette to keep in sync. The three non-brand
   hues are the application's own identity colours; there they are assigned by a hash
   of the author id and carry no meaning beyond "not the same person as the last one",
   which is exactly what they are doing here. */
.note {
  --note-c: var(--accent);
  padding: var(--s4);
  border: 1px solid color-mix(in srgb, var(--note-c) 26%, transparent);
  border-radius: 10px;
  /* 8%, not 10%. The role label is --ink-muted sitting on this tint, and at 10% the
     indigo and accent notes measure 4.49 and 4.46 -- failing AA by a hundredth. 8%
     puts the worst case at 4.61 and is visually indistinguishable. */
  background: color-mix(in srgb, var(--note-c) 8%, var(--paper));
  box-shadow: var(--shadow-sm);
}
.note--a { --note-c: #0E7983; rotate: -1.6deg; }
.note--b { --note-c: #4A4A8F; rotate: 1.2deg; }
.note--c { --note-c: #9F5E00; rotate: -.8deg; }
.note--mine { rotate: 1.6deg; }
@media (prefers-reduced-motion: reduce) { .note { rotate: none; } }

.note__who {
  display: flex; align-items: center; gap: var(--s2);
  font-size: .8125rem; font-weight: 600;
}
.note__who em {
  font-style: normal; font-weight: 500; font-size: .6875rem;
  text-transform: uppercase; letter-spacing: .07em; color: var(--ink-muted);
}
.note__av {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; flex: 0 0 auto;
  border-radius: 6px; background: var(--note-c); color: #FFFFFF;
  font-size: .625rem; font-weight: 600; font-style: normal; letter-spacing: .02em;
}
/* The three guest hues are fixed values, so white holds in both themes (5.15 / 7.87 /
   5.15). Your own avatar is filled with --accent, which flips per theme -- white on the
   dark accent is only 3.16, so it has to use the token that exists for this. */
.note--mine .note__av { color: var(--accent-contrast); }
.note p { margin-top: var(--s2); font-size: .8125rem; line-height: 1.5; color: var(--ink); }

.board__compose {
  display: flex; align-items: center; gap: var(--s2);
  padding-top: var(--s4); border-top: 1px solid var(--line);
}
/* Styled to read as the composer without being one -- this illustration has no <form>
   or endpoint behind it, unlike the real ones now in the request-access trays. See
   the README on the waitlist form that sat live for months capturing nothing, which
   is why a real form did not ship here until an endpoint actually existed. */
.board__field {
  flex: 1; padding: var(--s2) var(--s3);
  border: 1px solid var(--line); border-radius: 8px; background: var(--ground);
  font-size: .8125rem; color: var(--ink-muted);
}
.board__send {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: 0 0 auto;
  border-radius: 8px; background: var(--accent); color: var(--accent-contrast);
}

.collab__points { display: grid; gap: 0; margin: 0; }
/* Ordinarily .collab supplies the top margin via its own margin-top, since
   .collab__points normally sits beside .board in that two-column grid. The privacy
   page uses the list on its own, directly under .prose with no board beside it, so it
   needs the margin .collab would have given it -- scoped to that adjacency rather than
   changed on the base rule, which stays margin:0 for the layout that still needs it. */
.prose + .collab__points { margin-top: var(--s10); }
.collab__points > div { padding-block: var(--s4); border-top: 1px solid var(--line); }
.collab__points > div:first-child { border-top: 0; padding-top: 0; }
@media (min-width: 62rem) { .collab__points > div:first-child { padding-top: var(--s2); } }
.collab__points dt { font-weight: 600; font-size: 1rem; letter-spacing: -.012em; }
.collab__points dd { margin: var(--s2) 0 0; font-size: .9375rem; color: var(--ink-muted); }

/* ── collapsible rows (Questions / the awkward-cases half of Under the hood /
   each comparison page's checklist) ──────────────────────────────────────── */

/* One <details>-per-row mechanism, reused across all three, added 10 Aug 2026 when
   showing every answer fully expanded turned out to be most of why the page read as
   endless. Same no-script disclosure the Compare dropdown and mobile menu already
   use elsewhere on this site, so the chevron already reads as "click to reveal"
   before a visitor reaches one of these. */
.faq__item summary,
.depth__item--collapsible summary,
.matrix__item summary {
  cursor: pointer; list-style: none;
}
.faq__item summary::-webkit-details-marker,
.depth__item--collapsible summary::-webkit-details-marker,
.matrix__item summary::-webkit-details-marker {
  display: none;
}
.disclose-chevron { flex: 0 0 auto; color: var(--ink-faint); transition: transform .15s var(--ease); }
details[open] .disclose-chevron { transform: rotate(180deg); }

/* #questions -- nine FAQ rows, collapsed by default. The JSON-LD FAQPage block in
   index.html's <head> mirrors this section's text verbatim; that stays true here
   since the words themselves are unchanged, only the wrapper (dt/dd -> summary/p). */
.faq { display: grid; gap: 0; }
.prose + .faq { margin-top: var(--s10); }
.faq__item { border-top: 1px solid var(--line); }
.faq__item:first-child { border-top: 0; }
.faq__item summary {
  display: flex; align-items: center; gap: var(--s3);
  padding-block: var(--s4);
  font-weight: 600; font-size: 1rem; letter-spacing: -.012em;
}
.faq__item summary .disclose-chevron { margin-left: auto; }
.faq__item p { margin: 0; padding-bottom: var(--s4); font-size: .9375rem; color: var(--ink-muted); }

/* ── comparison matrix (/vs-lasso) ──────────────────────────────────────── */

/* One criterion per row, both answers stacked under it -- not a three-column table,
   which would need a second, cramped layout below 40rem. A row's dt is the shared
   question; its two answers read as siblings underneath rather than opposite ends of
   a line the eye has to travel. */
/* Collapsed by default as of 10 Aug 2026 -- nine to eleven rows shown fully expanded
   was the single longest stretch of scroll on each comparison page. Each row is now a
   <details>, so the criterion alone is what a visitor scans first and both answers
   land on click -- same mechanism as the #questions and #depth accordions on the
   homepage, see styles.css's collapsible-rows block above. */
.matrix { display: grid; gap: 0; margin-top: var(--s5); }
.matrix__item { display: block; padding-block: var(--s5); border-top: 1px solid var(--line); }
.matrix__item:first-child { border-top: 0; padding-top: 0; }
.matrix__item summary {
  display: flex; align-items: center; gap: var(--s3);
  font-weight: 600; font-size: 1rem; letter-spacing: -.012em;
}
.matrix__item summary .disclose-chevron { margin-left: auto; }
.matrix__answers { display: grid; gap: var(--s3); margin-top: var(--s3); }
@media (min-width: 40rem) { .matrix__answers { grid-template-columns: 1fr 1fr; gap: var(--s5); } }
.matrix__answer {
  padding: var(--s3) var(--s4); border: 1px solid var(--line); border-radius: 8px;
  font-size: .9375rem; color: var(--ink-muted);
}
.matrix__answer strong {
  display: block; margin-bottom: var(--s1);
  font-size: .6875rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-faint);
}
.matrix__answer--ours {
  border-color: color-mix(in srgb, var(--accent) 34%, var(--line));
  background: var(--accent-wash);
  color: var(--ink);
}
.matrix__answer--ours strong { color: var(--accent-strong); }
.matrix__answer a { color: var(--accent-strong); }

/* ── the handoff ────────────────────────────────────────────────────────── */

/* Redrawn from ShareSlideOut.jsx and EventSharePage.jsx. Two panels rather than one,
   because the claim being made is about two organisations -- a single panel would be
   showing collaboration and asking the reader to take the second party on trust. */
.handoff { margin-top: var(--s12); padding-top: var(--s12); border-top: 1px solid var(--line); }
.handoff__title { font-size: clamp(1.25rem, 2.6vw, 1.625rem); letter-spacing: -.02em; }
.handoff__lede { margin-top: var(--s4); color: var(--ink-muted); max-width: 46rem; }

.flow { display: grid; gap: var(--s4); margin-top: var(--s10); align-items: center; }
/* The wire only earns its space once the panels sit side by side. Below that it would
   be a vertical rule between two stacked cards, which reads as a divider, not a path. */
@media (min-width: 56rem) { .flow { grid-template-columns: 1fr auto 1fr; gap: var(--s5); } }

.flow__side { padding: var(--s5); display: grid; gap: var(--s3); align-content: start; }
.flow__head { display: flex; align-items: center; gap: var(--s2); font-size: .8125rem; font-weight: 600; }
.flow__head .ico { color: var(--accent); }
.flow__hint { font-size: .6875rem; color: var(--ink-muted); }

.scope { margin: 0; padding: 0; list-style: none; display: grid; gap: 5px; }
.scope li {
  display: flex; align-items: center; gap: var(--s2);
  font-size: .75rem; color: var(--ink);
}
.scope .ico { color: var(--accent); flex: 0 0 auto; }
/* Amber, matching the one tinted row in the real form -- the notes toggle is the single
   place the product warns you before you share, so flattening it to match the others
   would be redrawing away the only caution in the screen. */
.scope__warn {
  padding: 5px var(--s2); border-radius: 4px;
  border: 1px solid color-mix(in srgb, var(--warn) 25%, transparent);
  background: var(--warn-wash); color: var(--warn);
  font-size: .6875rem; font-weight: 500;
}

.flow__wire { height: 2px; border-radius: 2px; background: var(--line); overflow: hidden; }
@media (min-width: 56rem) { .flow__wire { width: 3.5rem; } }
.flow__wire i { display: block; width: 0; height: 100%; background: var(--gradient); }

.flow__eyebrow {
  font-size: .625rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent);
}
.flow__event { font-size: .9375rem; font-weight: 700; letter-spacing: -.015em; }
.flow__meta { font-size: .6875rem; color: var(--ink-muted); }
.rcards { display: grid; gap: var(--s2); margin-top: var(--s1); }
.rcard {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3); border-radius: 8px;
  border: 1px solid var(--line); background: var(--paper);
  font-size: .75rem; font-weight: 500;
}
.rcard .ico { color: var(--ink-muted); flex: 0 0 auto; }
.flow__foot { margin-top: var(--s1); font-size: .625rem; color: var(--ink-muted); }

/* One pass, matching the hero panel: the wire draws, then the sections land in order.
   A loop would turn a mechanism the reader is meant to follow once into wallpaper. */
.flow__wire i { animation: wire-draw .5s ease-out .1s both; }
@keyframes wire-draw { to { width: 100%; } }
.rcard { opacity: 0; animation: rcard-in .45s cubic-bezier(.2,.7,.3,1) both; }
.rcard:nth-child(1) { animation-delay: .55s; }
.rcard:nth-child(2) { animation-delay: .68s; }
.rcard:nth-child(3) { animation-delay: .81s; }
.rcard:nth-child(4) { animation-delay: .94s; }
.rcard:nth-child(5) { animation-delay: 1.07s; }
@keyframes rcard-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.flow__foot { opacity: 0; animation: rcard-in .45s ease-out 1.2s both; }

@media (prefers-reduced-motion: reduce) {
  .flow__wire i, .rcard, .flow__foot { animation: none !important; opacity: 1 !important; transform: none !important; }
  .flow__wire i { width: 100% !important; }
}

/* ── segments ───────────────────────────────────────────────────────────── */

.segments { display: grid; gap: var(--s4); margin-top: var(--s10); }
@media (min-width: 40rem) { .segments { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 72rem) { .segments { grid-template-columns: repeat(4, 1fr); } }

.segment {
  position: relative; display: flex; flex-direction: column;
  padding: var(--s6);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--paper);
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), transform .2s var(--ease);
}
.segment:hover {
  border-color: color-mix(in srgb, var(--accent) 26%, var(--line));
  box-shadow: var(--shadow-card); transform: translateY(-2px);
}
/* The brand rule sits on top of the card rather than under the heading -- it reads
   as a tab on a folder, which is a stronger grouping cue than a rule floating above
   text, and it survives the card being hovered. */
.segment::before {
  content: ""; position: absolute; inset: -1px auto auto var(--s6);
  width: 40px; height: 3px; border-radius: 0 0 3px 3px; background: var(--gradient);
}
.segment__ico { display: inline-flex; margin: var(--s2) 0 var(--s4); color: var(--accent); }
.segment__ico .ico { width: 24px; height: 24px; }
.segment h3 { margin-bottom: var(--s2); }
.segment p { font-size: .9375rem; color: var(--ink-muted); }

/* ── depth list ─────────────────────────────────────────────────────────── */

/* Not cards. Three card grids in a row would flatten the page into one texture, and
   this section is the most substantive thing on it -- a ruled list reads as reference
   material, which is the register these six items are written in. */
.depth { display: grid; gap: 0; margin-top: var(--s10); }
@media (min-width: 48rem) { .depth { grid-template-columns: 1fr 1fr; column-gap: var(--s12); } }

/* Second list in #depth, added 9 Aug 2026, converted to a collapsed-by-default
   accordion 10 Aug 2026 (see .depth__item--collapsible below) -- eleven items shown
   fully expanded was a large share of why this page read as endless. Same component
   on purpose -- these five still read as a continuation of the six above, not a
   different kind of claim, so a new card style or icon set would be arguing a
   distinction that is not there. The sub-heading takes .depth's usual gap from what
   came before it; .depth itself then sits close underneath its own heading rather
   than repeating that gap twice. */
.depth__sub { margin-top: var(--s10); }
.depth__sub + .depth,
.depth__sub + .collab__points,
.depth__sub + .versus { margin-top: var(--s5); }
/* /security stacks four .depth__sub groups, one of which has an explanatory
   paragraph between the heading and its list rather than going straight into it. */
.depth__sub + .lede { margin-top: var(--s3); }
.lede + .collab__points { margin-top: var(--s6); }

.depth__item {
  display: grid; grid-template-columns: auto 1fr; gap: var(--s2) var(--s4);
  padding-block: var(--s5);
  border-top: 1px solid var(--line);
}
.depth__ico {
  grid-row: span 2; display: inline-flex; padding-top: 2px; color: var(--accent);
}
.depth__ico .ico { width: 22px; height: 22px; }
.depth__item dt { align-self: center; font-weight: 600; font-size: 1rem; letter-spacing: -.012em; }
.depth__item dd { margin: 0; font-size: .9375rem; color: var(--ink-muted); }

/* The awkward-cases half of #depth: a <details> per item instead of the dt/dd grid
   above, so the icon, question and a chevron share one line and the explanation
   only appears on click. Same divider and item padding as the core six -- the
   difference is display: block instead of the two-column dt/dd grid, since a
   <summary> lays its own row out with flex. */
.depth__item--collapsible { display: block; }
.depth__item--collapsible summary { display: flex; align-items: center; gap: var(--s4); }
.depth__item--collapsible summary .depth__ico { padding-top: 0; }
.depth__item--collapsible summary .depth__q { flex: 1; font-weight: 600; font-size: 1rem; letter-spacing: -.012em; }
.depth__item--collapsible p { margin: var(--s3) 0 0; padding-left: calc(22px + var(--s4)); font-size: .9375rem; color: var(--ink-muted); }

/* ── plans ──────────────────────────────────────────────────────────────── */

.plans { display: grid; gap: var(--s4); margin-top: var(--s10); align-items: stretch; }
@media (min-width: 52rem) { .plans { grid-template-columns: repeat(3, 1fr); } }

.plan {
  position: relative; display: flex; flex-direction: column; gap: var(--s4);
  padding: var(--s8) var(--s6);
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg);
}
/* No prices here on purpose -- the tiers are still a proposal, and publishing a
   number would harden it into a public commitment before a single outside buyer has
   seen it. See the README. The featured treatment carries the recommendation instead. */
.plan--featured {
  border-color: color-mix(in srgb, var(--accent) 42%, var(--line));
  box-shadow: var(--shadow-lift);
  overflow: hidden;
}
.plan--featured::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 3px; background: var(--gradient);
}
.plan__name { display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap; }
.plan__name h3 { font-size: 1.25rem; }
.plan__tag {
  padding: 3px var(--s2); border-radius: 5px;
  font-size: .6875rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--accent-strong); background: var(--accent-wash);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
}
.plan__for { font-size: .9375rem; color: var(--ink-muted); }
.plan__list {
  margin: 0; padding: var(--s4) 0 0; list-style: none; display: grid; gap: var(--s3);
  border-top: 1px solid var(--line);
}
.plan__list li { display: grid; grid-template-columns: auto 1fr; gap: var(--s3); align-items: start; font-size: .9375rem; }
.plan__list .ico { margin-top: 4px; color: var(--accent); }
.plan__note { font-size: .8125rem; color: var(--ink-faint); }
.plan__cta {
  margin-top: auto; display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 44px;
  font-size: .9375rem; font-weight: 600; text-decoration: none; color: var(--accent);
}
.plan__cta .ico { transition: transform .2s var(--ease); }
.plan__cta:hover .ico { transform: translateX(3px); }
.plan__cta--strong { color: var(--accent-strong); }

/* ── closing call to action ─────────────────────────────────────────────── */

/* ── the contact tray ───────────────────────────────────────────────────── */

/* Opened with :target, because no script runs on this page and this is the one
   mechanism that gives a real panel without one -- it is addressable, it works with
   the back button, and the close control is a link rather than a handler. It is not
   marked up as a dialog: without script there is no focus trap and no Escape key, and
   claiming aria-modal while neither is true is worse for a screen reader than an
   honest labelled region. */
.tray {
  position: fixed; inset: 0; z-index: 60;
  visibility: hidden; transition: visibility 0s .3s;
}
.tray:target { visibility: visible; transition-delay: 0s; }

.tray__scrim {
  position: absolute; inset: 0;
  background: rgb(25 18 24 / 45%);
  opacity: 0; transition: opacity .3s ease;
}
/* Matches how --shadow-sm and --shadow-deep get their own dark-mode values rather
   than reusing the light ones: a dark background needs more opacity for an overlay
   to register at all, the same reason those shadows go from 4-22% to 45-80%. Pure
   black rather than --ink, which in dark mode is near-white and would scrim toward
   white. */
@media (prefers-color-scheme: dark) {
  .tray__scrim { background: rgb(0 0 0 / 55%); }
}
.tray:target .tray__scrim { opacity: 1; }

.tray__panel {
  position: absolute; inset-block: 0; right: 0;
  width: min(28rem, 100%); overflow-y: auto;
  padding: var(--s8) var(--s6) var(--s10);
  background: var(--paper); border-left: 1px solid var(--line);
  box-shadow: var(--shadow-deep);
  translate: 100% 0; transition: translate .3s cubic-bezier(.2, .7, .3, 1);
}
.tray:target .tray__panel { translate: 0 0; }

.tray__head { display: flex; align-items: start; justify-content: space-between; gap: var(--s4); }
.tray__head h2 { font-size: 1.25rem; letter-spacing: -.02em; }
.tray__close {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; margin: -4px -4px 0 0;
  border-radius: 6px; color: var(--ink-muted); text-decoration: none;
}
.tray__close:hover { background: var(--raised); color: var(--ink); }
.tray__intro { margin-top: var(--s2); font-size: .9375rem; color: var(--ink-muted); }

.field { display: grid; gap: 5px; margin-top: var(--s4); }
.field span { font-size: .8125rem; font-weight: 600; }
.field input, .field textarea, .field select {
  width: 100%; padding: var(--s2) var(--s3);
  border: 1px solid var(--line); border-radius: 6px;
  background: var(--paper); color: var(--ink);
  font: inherit; font-size: .9375rem;
}
.field textarea { min-height: 6rem; resize: vertical; }
.field input:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
}
.field__opt { font-weight: 400; color: var(--ink-muted); }

/* Off-screen rather than display:none, and left in the tab order's blind spot with
   tabindex=-1. A field that is display:none is the one field a bot knows to skip. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.tray__submit { margin-top: var(--s6); width: 100%; justify-content: center; }
.tray__small { margin-top: var(--s4); font-size: .75rem; color: var(--ink-muted); }
.tray__small a { color: var(--accent-strong); }

/* ── outcome pages (thanks / sorry) ────────────────────────────────────────── */

.outcome { min-height: 100dvh; display: grid; place-items: center; padding: var(--s10) 0; }
.outcome__inner { max-width: 32rem; text-align: center; }
.outcome__brand img { width: 150px; margin: 0 auto var(--s10); }
.outcome__mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; margin-bottom: var(--s6);
  border-radius: 999px;
}
.outcome__mark--ok { background: var(--accent-wash); color: var(--accent-strong); }
.outcome__mark--ok .ico { width: 26px; height: 26px; }
.outcome h1 { font-size: clamp(1.5rem, 4vw, 2rem); }
.outcome .lede { margin-top: var(--s4); }
.outcome .btn, .outcome__actions { margin-top: var(--s8); }
.outcome__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s3); }

/* ── close ──────────────────────────────────────────────────────────────── */

.close { background: var(--paper); border-top: 1px solid var(--line); padding-block: var(--s20) var(--s16); }
@media (max-width: 48rem) { .close { padding-block: var(--s12); } }

.close__card {
  position: relative; overflow: hidden;
  padding: clamp(var(--s8), 5vw, var(--s16));
  border-radius: var(--radius-lg);
  background: var(--gradient-cta);
  color: #FFFFFF;
  box-shadow: var(--shadow-deep);
}
@media (prefers-color-scheme: dark) { .close__card { color: #1A0410; } }
/* Bounding every child of the card keeps all copy in the dark half of the 135deg ramp.
   Without this the last paragraph's box ran the full card width, reaching rgb(224,42,111)
   where white is 4.44:1 -- and it carries opacity, which costs more again. Constrain the
   container once rather than policing each element's max-width. */
.close__body { position: relative; z-index: 1; max-width: 46rem; }
/* The woven mark, bled off the right edge -- the same motif the social card uses, so
   the shared link and the page it opens read as one object. */
.close__mark {
  position: absolute; top: 50%; right: -3rem; translate: 0 -50%;
  width: min(26rem, 42%); opacity: .16;
  pointer-events: none; user-select: none;
}
@media (max-width: 60rem) { .close__mark { display: none; } }
.close__card h2 { max-width: 22ch; }
/* Full white, no opacity. White at 94% over this ramp lands at 4.31:1 -- the opacity was
   costing 0.4 of a ratio point to buy a hierarchy that font-size already provides. */
.close__card p { margin-top: var(--s5); max-width: 44rem; font-size: 1.0625rem; }
.close__actions { margin-top: var(--s8); display: flex; flex-wrap: wrap; gap: var(--s3); }
.close__card .btn--onbrand { background: var(--paper); color: var(--accent-strong); box-shadow: var(--shadow-card); }
.close__card .btn--onbrand:hover { background: var(--paper); color: var(--accent); box-shadow: var(--shadow-lift); }
.close__card .btn--outline { background: transparent; border-color: currentColor; color: inherit; }
.close__card .btn--outline:hover { background: rgb(255 255 255 / 14%); color: inherit; }
@media (prefers-color-scheme: dark) {
  .close__card .btn--outline:hover { background: rgb(0 0 0 / 12%); }
}
/* Lives below the card, not inside it. It is a footnote, and the bottom-right of a
   135deg ramp is the brightest point on the page -- the one place small white text
   cannot reach 4.5:1 without either re-angling the brand gradient or dimming it.
   Outside the card it is unambiguously legible and the hierarchy is more honest. */
.close__small {
  max-width: var(--measure); margin-top: var(--s6);
  font-size: .875rem; color: var(--ink-muted);
}

/* ── footer ─────────────────────────────────────────────────────────────── */

.site-foot { background: var(--ground); border-top: 1px solid var(--line); padding-block: var(--s16) var(--s8); }
.site-foot__top { display: grid; gap: var(--s10); }
@media (min-width: 52rem) { .site-foot__top { grid-template-columns: minmax(0, 1fr) auto; gap: var(--s16); } }
/* 200px, above the pack's 160px tagline-legibility floor -- the lockup carries its
   tagline again (see README), so this width is a real constraint, not headroom. Below
   160px, switch to lockup-horizontal-notagline-*.svg rather than shrinking this. */
.site-foot img { width: 200px; }
/* The footer sits on --ground, and ink-faint against --ground is 4.34:1 -- a fail that
   predates this redesign. ink-muted is 4.96:1 there. Nothing in the footer uses
   ink-faint any more; that token is only safe on --paper. */
.site-foot__tag { margin-top: var(--s4); font-size: .875rem; color: var(--ink-muted); max-width: 26rem; }

.site-foot__cols { display: grid; gap: var(--s8); grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 34rem) { .site-foot__cols { grid-template-columns: repeat(3, minmax(8rem, auto)); gap: var(--s12); } }
.site-foot__col { display: grid; gap: var(--s2); align-content: start; }
.site-foot__title {
  margin: 0 0 var(--s1);
  font-size: .6875rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .1em; color: var(--ink-muted);
}
.site-foot__col a { font-size: .875rem; color: var(--ink-muted); text-decoration: none; width: fit-content; }
.site-foot__col a:hover { color: var(--accent); text-decoration: underline; }

.site-foot__base {
  display: flex; flex-wrap: wrap; gap: var(--s3) var(--s6); justify-content: space-between;
  margin-top: var(--s12); padding-top: var(--s6);
  border-top: 1px solid var(--line);
  font-size: .8125rem; color: var(--ink-muted);
}

/* ── on scroll reveals, deliberately absent ─────────────────────────────── */

/* There were scroll-driven fade-ups here, built on `animation-timeline: view()` --
   attractive because the CSP forbids script, so an IntersectionObserver is not an
   option and view() is the only way to do it at all.
 *
 * Removed, and this note is here so it does not get re-added without the same check.
 * The mechanism starts elements at `opacity: 0` with `animation-fill-mode: both`, so
 * anything that fails to drive the timeline leaves real content permanently invisible,
 * and twice while attaching it the renderer stopped responding. It could not be
 * verified either, because the machine this was built on has reduce-motion enabled, so
 * the guarded rule never ran.
 *
 * Unverifiable + failure mode is "the page is blank" + the payoff is a 300ms fade is
 * not a trade worth making on the front door. If it comes back, test it on a profile
 * with reduce-motion OFF, in Chrome and Firefox, and confirm every section is readable
 * with the timeline forced to a non-starting state. Hover and focus transitions are
 * unaffected -- those are ordinary, cheap and verified. */

/* ── /evee ──────────────────────────────────────────────────────────────── */

.evee-hero { display: grid; gap: var(--s10); }
@media (min-width: 56rem) {
  .evee-hero { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--s12); align-items: center; }
}
.evee-art {
  padding: var(--s6);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--paper); box-shadow: var(--shadow-card);
  display: flex; justify-content: center;
}
/* Cutout has a transparent background, so this is a frame around a portrait rather
   than a canvas the art fills -- same card treatment as every other illustration on
   the site, just capped narrower since the source is tall (549x774) and would
   otherwise dominate the hero on a wide screen. */
.evee-art img { display: block; width: 100%; max-width: 320px; height: auto; border-radius: 8px; }

.evee-facts { display: grid; gap: var(--s3); margin-top: var(--s8); }
@media (min-width: 40rem) { .evee-facts { grid-template-columns: repeat(3, 1fr); } }
.evee-more { margin-top: var(--s6); font-size: .9375rem; color: var(--ink-muted); }
.evee-more a { font-weight: 600; color: var(--accent); }
