/* Girard — design system. See ../CLAUDE.md for the rules behind these choices. */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('fonts/Archivo-Variable.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/IBMPlexMono-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/IBMPlexMono-Medium.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/IBMPlexMono-SemiBold.woff2') format('woff2');
}

:root {
  --ink: #14140F;
  --paper: #F1EFE8;
  --paper-green: #EBEFE9;
  --paper-cool: #E9EEF4;
  --green: #1E5B3C;
  --green-soft: rgba(30,91,60,.08);
  --green-line: rgba(30,91,60,.18);
  --grey: #A8A49B;
  --periwinkle: #AEBBF0;
  --amber: #A8721E;
  --error: #C0453B;
  --indigo: #1F2A6E;

  --r-pill: 999px;
  --r-sm: 12px;
  --r-md: 18px;
  --r-lg: 28px;
  --r-xl: 48px;

  --shadow-card: 0 1px 2px rgba(30,91,60,.06), 0 8px 24px -12px rgba(30,91,60,.14);
  --shadow-pop: 0 4px 8px rgba(30,91,60,.08), 0 16px 40px -14px rgba(30,91,60,.22);

  --ease-out: cubic-bezier(.16,1,.3,1);
  --ease-io:  cubic-bezier(.65,0,.35,1);

  --container: 1180px;
  --gutter: clamp(22px, 4.5vw, 48px);
  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Archivo', -apple-system, 'Segoe UI', sans-serif;
  font-size: 16.5px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Safety net for stray horizontal overflow on narrow screens. `clip`
     rather than `hidden`: hidden would make body a scroll container and
     break the sticky nav, clip does not. */
  overflow-x: clip;
}

::selection { background: var(--green); color: var(--paper); }

a { color: inherit; text-decoration: none; }
a:hover { color: var(--green); }
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible {
  outline: 2.5px solid var(--green);
  outline-offset: 3px;
  border-radius: 4px;
}

img, video { max-width: 100%; display: block; }

h1, h2, h3 { font-weight: 800; letter-spacing: -.02em; text-wrap: balance; margin: 0; }
h1 { font-size: clamp(42px, 6.4vw, 82px); line-height: 1.03; letter-spacing: -.032em; max-width: 15ch; }
h2 { font-size: clamp(30px, 4.2vw, 52px); line-height: 1.07; letter-spacing: -.028em; max-width: 24ch; }
h3 { font-size: clamp(22px, 2.6vw, 28px); line-height: 1.22; letter-spacing: -.014em; }
h1, h2, h3 { font-optical-sizing: auto; }

p { margin: 0; }
.lede { font-size: clamp(19px, 1.8vw, 22px); line-height: 1.55; max-width: 42ch; }
.body-copy { font-size: 16.5px; line-height: 1.7; max-width: 58ch; color: rgba(20,20,15,.82); text-wrap: pretty; }
.body-copy + .body-copy { margin-top: 1.1em; }

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

/* Claims: a statement and what it costs you, set as an editorial list. Three
   equal cards would say these are interchangeable; they are not, and the card
   was only ever a container for avoiding the decision. */
.claims { list-style: none; margin: clamp(34px, 4.5vw, 52px) 0 0; padding: 0; }
.claim {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(14px, 3vw, 52px);
  padding: clamp(22px, 2.8vw, 32px) 0;
  border-top: 1px solid rgba(30,91,60,.16);
}
.claim:first-child { border-top: none; padding-top: 0; }
.claim-head {
  font-size: clamp(19px, 1.9vw, 24px); line-height: 1.26; letter-spacing: -.018em;
  font-weight: 700; color: var(--ink); max-width: 20ch;
}
.claim-body {
  align-self: center;
  font-size: 16px; line-height: 1.65; max-width: 54ch;
  color: rgba(20,20,15,.68); text-wrap: pretty;
}
@media (max-width: 760px) {
  .claim { grid-template-columns: 1fr; gap: 9px; }
  .claim-head { max-width: none; }
}

/* ── Browser surfaces ─────────────────────────────────────────────────────
   Selection, caret, focus ring, underline metrics, scrollbar and changing
   numerals all ship with defaults that belong to no design system. Theming
   them is the difference between a page that was built and one assembled. */
::selection { background: rgba(30,91,60,.20); color: var(--ink); }
:root { accent-color: var(--green); caret-color: var(--green); }
:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--green); outline-offset: 3px; border-radius: 4px;
}
:where(.prose, .body-copy, .form-note, .lede) a {
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: rgba(30,91,60,.42);
  transition: text-decoration-color .2s var(--ease-io);
}
:where(.prose, .body-copy, .form-note, .lede) a:hover { text-decoration-color: var(--green); }
@supports (scrollbar-color: auto) {
  html { scrollbar-color: rgba(30,91,60,.3) transparent; scrollbar-width: thin; }
}
/* a number that changes must not shift the text beside it */
.count-badge, .board-n, .rule-num, .error-code, .limit-meta, .ruling-by {
  font-variant-numeric: tabular-nums;
}

.section {
  padding: clamp(70px, 10vh, 116px) 0;
}
.section--tint-green { background: var(--paper-green); }
.section--tint-cool { background: var(--paper-cool); }

.section-head {
  display: flex; flex-direction: column; gap: 18px;
  margin-bottom: clamp(36px, 5vw, 56px);
}

.pill-label {
  display: inline-flex; align-items: center; gap: 8px;
  align-self: flex-start;
  font-family: Archivo, sans-serif;
  font-weight: 600;
  font-size: 13px;
  letter-spacing: -.005em;
  color: var(--green);
  background: var(--green-soft);
  border-radius: var(--r-pill);
  padding: 7px 16px;
}

/* organic background wash — background only, never foreground. See CLAUDE.md. */
.organic-wash { position: relative; overflow: hidden; }
.organic-wash::before {
  content: ''; position: absolute; inset: -10% -10% auto auto; width: 60%; aspect-ratio: 1;
  background: radial-gradient(circle at 30% 30%, rgba(30,91,60,.07), transparent 70%);
  border-radius: 50%; pointer-events: none; z-index: 0;
}
.organic-wash::after {
  content: ''; position: absolute; inset: auto auto -15% -8%; width: 45%; aspect-ratio: 1;
  background: radial-gradient(circle at 60% 60%, rgba(174,187,240,.08), transparent 70%);
  border-radius: 50%; pointer-events: none; z-index: 0;
}
.organic-wash > * { position: relative; z-index: 1; }

/* buttons */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: Archivo, sans-serif; font-weight: 600; font-size: 15px;
  white-space: nowrap;   /* a button label must never wrap into two lines */
  padding: 13px 24px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .3s var(--ease-out), background-color .2s var(--ease-io), box-shadow .3s var(--ease-out), border-color .2s var(--ease-io);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.btn:active { transform: scale(.97); }

/* Specular edge light. The canvas overhangs the button so the rim can bleed
   past the edge; it sits above the button's own background and below the
   label, and never takes a pointer event. */
[data-specular] { position: relative; }
.btn-label { position: relative; z-index: 1; }
.specular-fx { position: absolute; inset: -20px; z-index: 0; pointer-events: none; }
.specular-fx canvas { display: block; width: 100%; height: 100%; }
.btn-primary { background: var(--green); color: var(--paper); box-shadow: var(--shadow-card); }
.btn-primary:hover { background: #184a30; color: var(--paper); box-shadow: var(--shadow-pop); }
.btn-secondary { background: transparent; color: var(--ink); border-color: rgba(20,20,15,.22); }
.btn-secondary:hover { border-color: var(--green); color: var(--green); }
.btn svg { width: 16px; height: 16px; transition: transform .3s var(--ease-out); }
.btn:hover svg { transform: translateX(2px); }

/* stacked button: a lead label with the promise underneath. Each line still
   sets its own nowrap, so this reads as two deliberate lines, never as a
   label that happened to wrap. */
.btn-stacked { align-items: center; padding-top: 10px; padding-bottom: 10px; text-align: left; }
.btn-lines { display: flex; flex-direction: column; gap: 1px; }
.btn-lead { font-size: 15px; font-weight: 600; line-height: 1.25; white-space: nowrap; }
.btn-sub {
  font-size: 12.5px; font-weight: 500; line-height: 1.3; white-space: nowrap;
  color: rgba(20,20,15,.68); transition: color .2s var(--ease-io);
}
.btn-secondary:hover .btn-sub { color: rgba(30,91,60,.72); }

/* demo pill — closes every showcase panel, aligned to the panel's right edge */
.panel-demo { display: flex; justify-content: flex-end; margin-top: clamp(28px, 4vw, 44px); }
/* a panel that also offers the long version puts it opposite the demo pill */
.panel-demo--split { justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap; }
.learn-link {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13.5px; font-weight: 600; letter-spacing: -.005em;
  color: rgba(20,20,15,.68);
  border: 1px solid rgba(20,20,15,.18); border-radius: var(--r-pill);
  padding: 9px 16px;
  transition: color .2s var(--ease-io), border-color .2s var(--ease-io),
              background-color .2s var(--ease-io), transform .3s var(--ease-out);
}
.learn-link svg { width: 14px; height: 14px; transition: transform .3s var(--ease-out); }
.learn-link:active { transform: scale(.97); }
@media (hover: hover) and (pointer: fine) {
  .learn-link:hover {
    color: var(--green); border-color: var(--green-line); background: var(--green-soft);
  }
  .learn-link:hover svg { transform: translateX(2px); }
}
.demo-pill {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13.5px; font-weight: 600; letter-spacing: -.005em;
  color: var(--green); background: var(--green-soft);
  border: 1px solid var(--green-line); border-radius: var(--r-pill);
  padding: 9px 18px;
  transition: background-color .2s var(--ease-io), color .2s var(--ease-io),
              border-color .2s var(--ease-io), transform .3s var(--ease-out),
              box-shadow .3s var(--ease-out);
}
.demo-pill svg { width: 14px; height: 14px; transition: transform .3s var(--ease-out); }
.demo-pill:active { transform: scale(.97); }
@media (hover: hover) and (pointer: fine) {
  .demo-pill:hover {
    background: var(--green); border-color: var(--green); color: var(--paper);
    box-shadow: var(--shadow-card);
  }
  .demo-pill:hover svg { transform: translateX(2px); }
}

/* demo card — the closing section's live-look offer, ahead of the form */
.demo-card {
  display: flex; flex-direction: column; align-items: flex-start;
  margin: 26px 0 4px; max-width: 42ch; padding: 22px 24px;
  border-radius: var(--r-lg); border: 1px solid var(--green-line);
  background:
    linear-gradient(135deg, rgba(30,91,60,.07), rgba(30,91,60,.02) 58%),
    #fff;
  box-shadow: var(--shadow-card);
  transition: transform .3s var(--ease-out), box-shadow .3s var(--ease-out),
              border-color .2s var(--ease-io);
}
.demo-card-title {
  font-size: 21px; font-weight: 700; letter-spacing: -.015em;
  color: var(--ink);
}
.demo-card-copy {
  font-size: 14.5px; line-height: 1.5; color: rgba(20,20,15,.68);
  margin-top: 8px; text-wrap: pretty;
}
.demo-card-go {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 16px;
  font-size: 14px; font-weight: 700; color: var(--green);
}
.demo-card-go svg { width: 15px; height: 15px; transition: transform .3s var(--ease-out); }
.demo-card:active { transform: scale(.995); }
@media (hover: hover) and (pointer: fine) {
  .demo-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-pop); border-color: rgba(30,91,60,.32); }
  .demo-card:hover .demo-card-go svg { transform: translateX(3px); }
}
@media (prefers-reduced-motion: reduce) {
  .demo-card, .demo-pill { transition: background-color .2s, color .2s, border-color .2s; }
  .demo-card:hover { transform: none; }
}

/* nav */
.site-nav {
  position: sticky; top: 0; z-index: 40;
  background: rgba(241,239,232,.86);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid rgba(20,20,15,.1);
}
.site-nav .wrap { position: relative; display: flex; align-items: center; justify-content: space-between; height: 78px; gap: 24px; }
.brand { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 20px; letter-spacing: -.01em; line-height: 1; }
.brand img { width: auto; height: 34px; display: block; flex: none; }
.footer-row .brand img { height: 26px; }
.nav-links { display: flex; align-items: center; gap: 6px; list-style: none; margin: 0; padding: 0; }
.nav-links a {
  padding: 9px 14px; border-radius: var(--r-md); font-weight: 600; font-size: 14.5px;
  transition: background-color .2s var(--ease-io), color .2s var(--ease-io);
}
.nav-links a:hover { background: var(--green-soft); color: var(--green); }
.nav-links a[aria-current="page"] { background: var(--green-soft); color: var(--green); }
.nav-cta { display: flex; align-items: center; gap: 10px; }
.nav-toggle { display: none; }
@media (max-width: 860px) {
  .nav-links { display: none; }
  /* the toggle sets .open — without this rule the menu button did nothing
     and the nav was unreachable on every phone */
  .nav-links.open {
    display: flex; flex-direction: column; align-items: stretch; gap: 2px;
    position: absolute; left: 0; right: 0; top: calc(100% + 8px);
    background: var(--paper);
    border: 1px solid rgba(20,20,15,.12); border-radius: var(--r-lg);
    padding: 10px; box-shadow: var(--shadow-pop); z-index: 50;
  }
  .nav-links.open a { padding: 13px 14px; font-size: 16px; }
  .nav-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 42px; height: 42px; border-radius: var(--r-md); border: 1px solid rgba(20,20,15,.18);
    background: transparent;
  }
  .nav-cta .btn { font-size: 14px; padding: 11px 16px; }
}
/* Below this the wordmark, CTA and toggle stop fitting on one line. The mark
   carries the brand on its own, so the wordmark yields rather than the CTA —
   dropping the primary action would cost more than dropping the lettering. */
@media (max-width: 460px) {
  .site-nav .brand { font-size: 0; gap: 0; }
  .nav-cta .btn { font-size: 13.5px; padding: 10px 14px; }
  .site-nav .wrap { height: 68px; gap: 10px; }
}

/* hero */
.hero { position: relative; overflow: hidden; padding-top: clamp(48px, 7vh, 80px); padding-bottom: clamp(48px, 5vw, 72px); }
.hero-field {
  position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
  /* Full-bleed behind the hero, but faded out across the headline column: the
     wash is the page's ground on the right and simply absent on the left, so
     nothing changes the surface the h1 is read against. */
  /* Present at both edges and receding across the headline column, so the wash
     frames the hero from either side rather than banking on one. The trough is
     6%: at that strength even the deepest forest region is a hint on the paper,
     which keeps the h1 reading against effectively plain ground. */
  --hero-mask: linear-gradient(96deg,
    rgba(0,0,0,.30) 0%, rgba(0,0,0,.12) 15%, rgba(0,0,0,.05) 34%,
    rgba(0,0,0,.14) 52%, rgba(0,0,0,.55) 64%, #000 76%, #000 100%);
  -webkit-mask-image: var(--hero-mask);
          mask-image: var(--hero-mask);
}
.hero-field canvas { display: block; width: 100%; height: 100%; }
@media (max-width: 900px) {
  .hero-field {
    -webkit-mask-image: linear-gradient(180deg, transparent 0, transparent 34%, #000 70%);
            mask-image: linear-gradient(180deg, transparent 0, transparent 34%, #000 70%);
  }
}
@media (max-width: 640px) { .hero-field { display: none; } }
.hero .wrap { position: relative; z-index: 1; }
.hero-grid { display: grid; grid-template-columns: 1.15fr .85fr; gap: clamp(32px, 5vw, 64px); align-items: start; }
@media (max-width: 900px) { .hero-grid { grid-template-columns: 1fr; } }
.hero h1 { margin-bottom: 22px; }

/* Hero label. No pill: the words carry it, with a rule for weight. */
.hero-eyebrow { margin: 0 0 20px; }
.hero-eyebrow-line {
  display: inline-block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: clamp(11.5px, 1.05vw, 13px);
  font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  color: var(--green);
  padding-bottom: 10px;
  border-bottom: 2px solid var(--green-line);
}
/* Typed reveal. The full string is in the markup and is only clipped, so a
   scripting-off visitor and a screen reader get the whole line either way.
   main.js measures the natural width once and hands it over, which is what
   lets the caret sit exactly at the last glyph rather than near it. */
html.js .hero-eyebrow-line[data-type][style*="--type-w"] {
  overflow: hidden; white-space: nowrap; vertical-align: bottom;
  /* the declared width is the finished state, so if the animation never runs
     the line is full rather than invisible; the backwards fill supplies the 0 */
  width: var(--type-w); max-width: 100%;
  /* transparent is the resting value, so when the caret animation finishes it
     reverts to nothing rather than leaving a bar parked after the last glyph. */
  border-right: 2px solid transparent;
  /* Longhands rather than the shorthand so the step count and duration can come
     from custom properties: every page has a different label, and one step per
     character is what makes it read as typing rather than as a wipe. The caret
     runs three blinks over exactly the typing duration, so it stops with it. */
  animation-name: hero-type, hero-caret;
  animation-duration: var(--type-dur, 1.2s), calc(var(--type-dur, 1.2s) / 3);
  animation-timing-function: steps(var(--type-steps, 24), end), step-end;
  animation-delay: .25s, .25s;
  animation-iteration-count: 1, 3;
  animation-fill-mode: both, none;
}
@keyframes hero-type { from { width: 0; } to { width: var(--type-w); } }
@keyframes hero-caret {
  0%, 100% { border-right-color: var(--green); }
  50%      { border-right-color: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  html.js .hero-eyebrow-line[data-type][style*="--type-w"] {
    width: auto; animation: none; border-right-color: transparent;
  }
}
/* No breakpoint guess for whether the label fits: main.js measures the line
   against the space actually available and only sets --type-w when it fits on
   one line. If it does not, nothing here arms and the label simply wraps, which
   is what a narrow phone gets for the longest label on the site. */
@media (max-width: 460px) { .hero-eyebrow-line { letter-spacing: .1em; } }

/* Headline spotlight.
   The h1's own text is never touched: it stays solid ink, real, selectable,
   and immune to any paint failure. Over it sits a copy of the words in green,
   aria-hidden, masked to a small disc that follows the pointer.
   The glow radiates from the glyphs themselves via text-shadow rather than
   from a rectangle behind them. A box would need a radius larger than its own
   height to read as soft, and the gradient then gets clipped at the box edges,
   which is exactly the square corners this replaces.
   Pointer-only: a touch device has no hover to leave, so it would latch on. */
.hero-title { position: relative; }
/* Containment is unconditional. If it lived only inside the hover media query,
   a pointer-type change after the layer was built (device emulation, a touch
   laptop, a window moved to a touchscreen) would drop these declarations and
   the copy would fall back into normal flow as a second visible headline.
   Out here it stays invisible and out of flow no matter what matches. */
.hero-title-tint {
  position: absolute; inset: 0; opacity: 0;
  pointer-events: none; visibility: hidden;
}
@media (hover: hover) and (pointer: fine) {
  .hero-title-tint {
    visibility: visible;
    /* The layer is grown by --bleed on every side and padded back by the same
       amount, so (box-sizing is border-box) the text lands exactly where the
       h1's own text is while the glow has room to fade out well inside the
       box. Two things were drawing a straight edge at the text margin:
         - mask-repeat defaults to `repeat`, so the disc tiled at the box
           boundary and left a seam there. Hence no-repeat.
         - the 46px bloom reached past a box that was flush with the text, and
           a mask never paints outside its own box. Hence the bleed, which is
           larger than the widest shadow.
       The mask centre is offset by the same --bleed because --wx/--wy are
       measured from the h1, not from this enlarged layer. */
    --bleed: 64px;
    position: absolute; inset: calc(var(--bleed) * -1); padding: var(--bleed);
    pointer-events: none;
    color: var(--green);
    text-shadow:
      0 0 6px rgba(30,91,60,.45),
      0 0 22px rgba(47,143,94,.35),
      0 0 46px rgba(47,143,94,.18);
    opacity: 0;
    transition: opacity .26s var(--ease-io);
    --spot: radial-gradient(circle 3.2em
      at calc(var(--wx, 50%) + var(--bleed)) calc(var(--wy, 50%) + var(--bleed)),
      #000 0%, rgba(0,0,0,.85) 30%, rgba(0,0,0,.35) 58%, transparent 78%);
    -webkit-mask-image: var(--spot);
            mask-image: var(--spot);
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
  }
  .hero-title.is-washed .hero-title-tint { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .hero-title-tint { transition: none; } }
.hero-ctas { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }
.hero-aside { display: flex; flex-direction: column; gap: 18px; height: 100%; }
.diagram-card {
  position: relative; overflow: hidden;
  background: linear-gradient(180deg, #fff 0%, #fdfdfb 100%);
  border-radius: var(--r-xl); box-shadow: var(--shadow-pop);
  border: 1px solid rgba(30,91,60,.12);
  padding: clamp(22px, 2.4vw, 32px);
  display: flex; flex-direction: column;
  min-height: clamp(440px, 50vh, 600px);
  justify-content: space-between;
}
.diagram-card::before {
  content: ''; position: absolute; inset: -30% -20% auto auto; width: 70%; aspect-ratio: 1;
  background: radial-gradient(circle, rgba(30,91,60,.1), transparent 65%);
  border-radius: 50%; pointer-events: none;
  animation: cardglow 14s ease-in-out infinite;
}
.diagram-card::after {
  content: ''; position: absolute; inset: auto -15% -25% auto; width: 55%; aspect-ratio: 1;
  background: radial-gradient(circle, rgba(174,187,240,.14), transparent 65%);
  border-radius: 50%; pointer-events: none;
  animation: cardglow 18s ease-in-out infinite reverse;
}
@keyframes cardglow {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(-6%, 8%) scale(1.12); }
}
.diagram-card > * { position: relative; z-index: 1; }
.diagram-card .room-row .status::before {
  content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; margin-right: 6px; vertical-align: middle;
  animation: pulsedot 2.2s ease-out infinite;
}
@keyframes pulsedot {
  0% { box-shadow: 0 0 0 0 currentColor; opacity: 1; }
  70% { box-shadow: 0 0 0 6px transparent; opacity: .6; }
  100% { box-shadow: 0 0 0 0 transparent; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .diagram-card::before, .diagram-card::after, .diagram-card .room-row .status::before { animation: none; }
}
.diagram-caption { font-size: 13.5px; color: rgba(20,20,15,.68); margin-top: 14px; }

.typing-flow {
  display: flex; flex-direction: column; gap: 12px;
  margin-top: 20px; padding-top: 18px;
  border-top: 1px solid rgba(30,91,60,.14);
}
/* The three lines are one thought in sequence, so they take turns rather than
   stacking: three seconds each, looping. Stacking every row into a single grid
   cell means the block is exactly as tall as its tallest line, with no magic
   number to keep in sync and no reflow as the text swaps.
   Gated on html.js so a scripting-off visitor keeps all three in normal flow,
   which is also the reduced-motion fallback below. */
html.js .typing-flow { display: grid; gap: 0; }
html.js .typing-flow > .typing-row {
  grid-area: 1 / 1;
  opacity: 0;
  animation: typing-cycle 9s var(--ease-io) infinite;
}
html.js .typing-flow > .typing-row:nth-child(2) { animation-delay: 3s; }
html.js .typing-flow > .typing-row:nth-child(3) { animation-delay: 6s; }
@keyframes typing-cycle {
  0%             { opacity: 0; transform: translateY(5px); }
  4%, 29%        { opacity: 1; transform: none; }
  34%, 100%      { opacity: 0; transform: translateY(-5px); }
}
@media (prefers-reduced-motion: reduce) {
  html.js .typing-flow { display: flex; gap: 12px; }
  html.js .typing-flow > .typing-row { opacity: 1; animation: none; transform: none; }
}
.typing-row { display: flex; gap: 14px; align-items: baseline; }
.typing-label {
  flex: 0 0 92px; font-weight: 700; font-size: 12px; letter-spacing: .01em;
  color: var(--green); text-transform: uppercase;
}
.typing-text { font-size: 13.5px; line-height: 1.5; color: rgba(20,20,15,.68); }
.typing-text em { font-style: normal; color: var(--ink); font-weight: 600; }

/* floating role cursors — see CLAUDE.md: transform/opacity only, never left/top */
.floating-cursor {
  position: absolute; left: 0; top: 0; display: flex; align-items: center; gap: 6px;
  pointer-events: none; z-index: 2; will-change: transform;
}
.floating-cursor svg { width: 15px; height: 15px; flex: none; filter: drop-shadow(0 2px 4px rgba(20,20,15,.18)); }
.floating-cursor .cursor-tag {
  font-family: Archivo, sans-serif; font-weight: 700; font-size: 10.5px; letter-spacing: .04em;
  padding: 4px 9px; border-radius: var(--r-pill); color: #fff; white-space: nowrap;
  box-shadow: 0 2px 6px rgba(20,20,15,.16);
}
.cursor-finance { color: var(--green); left: 6%; top: 20%; animation: curmove1 16s ease-in-out infinite; }
.cursor-finance .cursor-tag { background: var(--green); }
.cursor-legal { color: var(--indigo); left: 58%; top: 12%; animation: curmove2 19s ease-in-out infinite; }
.cursor-legal .cursor-tag { background: var(--indigo); }
.cursor-security { color: var(--amber); left: 30%; top: 58%; animation: curmove3 21s ease-in-out infinite; }
.cursor-security .cursor-tag { background: var(--amber); }
@keyframes curmove1 {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(64px, 34px); }
  50% { transform: translate(30px, 96px); }
  75% { transform: translate(-18px, 52px); }
}
@keyframes curmove2 {
  0%, 100% { transform: translate(0, 0); }
  30% { transform: translate(-56px, 58px); }
  60% { transform: translate(-92px, 14px); }
  85% { transform: translate(-30px, -20px); }
}
@keyframes curmove3 {
  0%, 100% { transform: translate(0, 0); }
  35% { transform: translate(58px, -30px); }
  65% { transform: translate(96px, 10px); }
  90% { transform: translate(24px, 40px); }
}
@media (prefers-reduced-motion: reduce) {
  .floating-cursor { animation: none !important; }
}
@media (max-width: 900px) {
  .floating-cursor { display: none; }
}

/* chips / tags */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: var(--r-sm); border: 1px solid rgba(20,20,15,.14);
  padding: 8px 12px; font-size: 13.5px; font-weight: 600; background: #fff;
}
.chip .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green); flex: none; }

/* ticker — cascading question cards, revealed on hover (see emil-design-eng skill) */
.ticker-band {
  position: relative; background: var(--green); color: var(--paper); overflow: hidden;
}
.ticker-label {
  position: absolute; left: 50%; top: 50%; z-index: 2; pointer-events: none;
  transform: translate(-50%, -50%) scale(1.5);
  font-family: Archivo, sans-serif; font-weight: 600; font-size: 12.5px;
  letter-spacing: .04em; color: rgba(241,239,232,.9); white-space: nowrap;
  opacity: 1;
  transition: opacity .9s var(--ease-io), transform .9s var(--ease-io);
}
.ticker-viewport {
  padding: 22px 0 34px;
  opacity: 0; transform: scale(.96);
  transition: opacity .85s var(--ease-out), transform .85s var(--ease-out);
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 9%, #000 91%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, #000 9%, #000 91%, transparent 100%);
}
.ticker-track {
  display: flex; align-items: center; width: max-content;
  animation: tickm 62s linear infinite; animation-play-state: paused;
}
/* even number of unique cards → the duplicated half repeats the same odd/even
   translateY pattern, so the -50% loop point never shows a vertical jump */
@keyframes tickm { from { transform: translateX(0); } to { transform: translateX(-50%); } }

@media (hover: hover) and (pointer: fine) {
  .ticker-band:hover .ticker-label { opacity: 0; transform: translate(-50%, -50%) scale(1.3); }
  /* questions only start appearing once the label has fully faded out (.9s) */
  .ticker-band:hover .ticker-viewport {
    opacity: 1; transform: scale(1);
    transition: opacity .85s var(--ease-out) .9s, transform .85s var(--ease-out) .9s;
  }
  .ticker-band:hover .ticker-track { animation-play-state: running; }
}
/* touch/no-hover devices can't trigger :hover — reveal by default so content isn't stranded */
@media (hover: none) {
  .ticker-label { opacity: 0; }
  .ticker-viewport { opacity: 1; transform: scale(1); }
  .ticker-track { animation-play-state: running; }
}

.q-card {
  display: flex; align-items: center; gap: 11px;
  background: #fff; border-radius: var(--r-lg);
  padding: 12px 20px 12px 12px;
  margin-right: 18px; flex: none; white-space: nowrap;
  box-shadow: 0 6px 16px rgba(14,30,20,.16), 0 1px 3px rgba(14,30,20,.1);
}
.q-card:nth-child(odd) { transform: translateY(-7px); }
.q-card:nth-child(even) { transform: translateY(7px); }
.q-card .avatar {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 12.5px; letter-spacing: -.01em;
}
.q-card .q-role { color: var(--grey); font-weight: 600; }
.q-card .q-text { font-size: 15px; font-weight: 500; color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
  .ticker-track { animation: none; }
  .ticker-label, .ticker-viewport { transition: none; }
  .ticker-label { opacity: 0; }
  .ticker-viewport { opacity: 1; transform: none; }
}
@media (max-width: 640px) {
  .q-card .q-text { font-size: 13.5px; }
  .q-card { padding: 10px 16px 10px 10px; }
}

/* showcase — the seven core sections as one tabbed block. The strip scrolls
   the active pill to centre and the panel below cascades in. Progressive
   enhancement: the strip is hidden until JS adds `js` to <html>, and panels
   are only collapsed by the `hidden` attribute that JS sets, so with scripting
   off every panel renders stacked and the copy stays in the raw HTML. */
.showcase { padding: clamp(70px, 10vh, 116px) 0; background: var(--paper-green); }

.showcase-tabs-wrap { display: none; margin-bottom: clamp(30px, 4.5vw, 50px); }
html.js .showcase-tabs-wrap { display: block; }
.showcase-tabs {
  /* Full-bleed revolver belt. JS clones the pill set either side, so there is
     always content past both edges and the strip can wrap without a seam —
     no side padding needed, the clones do that job. */
  display: flex; gap: 10px; overflow-x: auto;
  padding: 6px 0;
  overscroll-behavior-x: contain;
  scrollbar-width: none; -ms-overflow-style: none;
  /* deep falloff — the belt reads as continuing well past the edges, with the
     outer pills dropping away early rather than sitting there at half strength */
  -webkit-mask-image: linear-gradient(to right, transparent 0, rgba(0,0,0,.06) 10%, rgba(0,0,0,.32) 22%, #000 40%, #000 60%, rgba(0,0,0,.32) 78%, rgba(0,0,0,.06) 90%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, rgba(0,0,0,.06) 10%, rgba(0,0,0,.32) 22%, #000 40%, #000 60%, rgba(0,0,0,.32) 78%, rgba(0,0,0,.06) 90%, transparent 100%);
}
.showcase-tabs::-webkit-scrollbar { display: none; }
.showcase-tab {
  flex: none; white-space: nowrap; cursor: pointer;
  font-family: Archivo, sans-serif; font-weight: 600; font-size: 14.5px;
  color: rgba(20,20,15,.6);
  background: rgba(20,20,15,.05); border: 1px solid transparent;
  border-radius: var(--r-sm); padding: 11px 20px;
  transition: background-color .3s var(--ease-io), color .3s var(--ease-io),
              border-color .3s var(--ease-io), transform .3s var(--ease-out);
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) and (pointer: fine) {
  .showcase-tab:hover { color: var(--ink); background: rgba(20,20,15,.09); }
}
.showcase-tab:active { transform: scale(.97); }
/* .is-active carries the styling because the belt's clones must not claim
   aria-selected — they are hidden from assistive tech. */
.showcase-tab[aria-selected="true"],
.showcase-tab.is-active {
  background: var(--green); border-color: var(--green); color: var(--paper);
}

/* the cascade itself — panel lifts in, its [data-cascade] children stagger */
html.js .showcase-panel.is-entering {
  animation: panelin .55s var(--ease-out) both;
}
@keyframes panelin {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}
/* no JS: panels stack, so they need the spacing a section would have given */
html:not(.js) .showcase-panel + .showcase-panel { margin-top: clamp(70px, 10vh, 116px); }
@media (prefers-reduced-motion: reduce) {
  html.js .showcase-panel.is-entering { animation: none; }
  .showcase-tab { transition: none; }
}
@media (max-width: 640px) {
  /* taller than the desktop pill so it clears a comfortable touch target */
  .showcase-tab { font-size: 13.5px; padding: 13px 16px; }
}

/* two-col feature block (replaces 3-col icon grids — see CLAUDE.md ban #4) */
.feature-block { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 64px); align-items: center; }
.feature-block.reverse { direction: rtl; }
.feature-block.reverse > * { direction: ltr; }
@media (max-width: 900px) { .feature-block, .feature-block.reverse { grid-template-columns: 1fr; direction: ltr; } }
.feature-media {
  border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow-card);
  border: 1px solid rgba(30,91,60,.12); background: #fff;
  position: relative;
}
.feature-media video, .feature-media img { width: 100%; height: auto; display: block; }
.play-btn {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(20,20,15,.28); border: none; cursor: pointer;
  transition: background-color .25s var(--ease-io);
}
.play-btn:hover { background: rgba(20,20,15,.4); }
.play-btn .ring {
  width: 68px; height: 68px; border-radius: 50%; background: var(--paper);
  display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow-pop);
  transition: transform .3s var(--ease-out);
}
.play-btn:hover .ring { transform: scale(1.06); }
.play-btn svg { width: 22px; height: 22px; margin-left: 3px; }

/* pull quote */
.pull-quote {
  font-size: clamp(22px, 2.6vw, 30px); font-weight: 600; letter-spacing: -.01em;
  line-height: 1.35; max-width: 26ch; color: var(--green);
  padding: 28px 0; border-top: 1px solid var(--green-line); margin-top: clamp(36px,5vw,56px);
}

/* card grid (asymmetric, not uniform 3-col — used for specialist roster) */
.card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr)); gap: 16px; }
.spec-card {
  background: #fff; border-radius: var(--r-lg); border: 1px solid rgba(30,91,60,.1);
  box-shadow: var(--shadow-card); padding: 22px;
  transition: transform .3s var(--ease-out), box-shadow .3s var(--ease-out);
}
.spec-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-pop); }
.spec-card h3 { font-size: 16px; font-weight: 700; letter-spacing: normal; margin: 0 0 8px; }
.spec-card p { font-size: 14.5px; color: rgba(20,20,15,.68); margin: 0 0 14px; }
.spec-card .owner { font-size: 12.5px; font-weight: 600; color: var(--green); }
.spec-card.ghost {
  border-style: dashed; border-color: rgba(30,91,60,.3); background: transparent;
  box-shadow: none; display: flex; align-items: center; justify-content: center;
  text-align: center; color: var(--green); font-weight: 600; cursor: pointer;
  transition: background-color .28s var(--ease-io), color .28s var(--ease-io),
              border-color .28s var(--ease-io), transform .3s var(--ease-out),
              box-shadow .3s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .spec-card.ghost:hover {
    background: var(--green); border-color: var(--green); border-style: solid;
    color: #fff; box-shadow: var(--shadow-pop);
  }
}
.spec-card.ghost:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }

/* the compose step the ghost card turns into, and the seat it leaves behind */
.spec-card--compose { display: flex; flex-direction: column; }
.spec-card--compose .compose-hint {
  font-size: 13.5px; color: rgba(20,20,15,.68); margin: 0 0 14px; line-height: 1.45;
}
.compose-row { display: flex; gap: 8px; margin-top: auto; flex-wrap: wrap; }
.compose-input {
  flex: 1 1 130px; min-width: 0; font-size: 15px; padding: 10px 13px;
  border-width: 1.5px; border-color: rgba(20,20,15,.14); background: #FBFAF7;
}
.compose-go { padding: 10px 18px; font-size: 14px; flex: none; }
/* entering elements: ease-out, short, and never from nothing */
.spec-card--compose, .spec-card--seated {
  animation: seat-in .24s var(--ease-out) both;
}
@keyframes seat-in {
  from { opacity: 0; transform: scale(.97); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .spec-card--compose, .spec-card--seated { animation: none; }
}

/* ── page aura ────────────────────────────────────────────────────────────
   One forest-green wash that travels with the reader. It sits above the flat
   section fills and below every `.wrap`, so it tints the ground behind each
   section title and never touches a glyph. Driven by a scroll timeline rather
   than a scroll listener: it runs on the compositor, so there is no per-frame
   work on the main thread and nothing to throttle.
   The grain is inlined fractal noise, which keeps the CSP as it is. */
/* ── Deal Skills Pack ─────────────────────────────────────────────────────
   The six skills are a disclosure list rather than six identical tiles: the
   teaser is the whole row until you ask for the rest, so the page reads as a
   contents page first and a reference second. */
.skills-list { display: flex; flex-direction: column; margin-top: clamp(34px, 4.5vw, 52px); }
.skills-list details {
  border-top: 1px solid rgba(30,91,60,.16);
  transition: background-color .24s var(--ease-io);
}
.skills-list details:first-of-type { border-top: none; }
.skills-list details[open] { background: rgba(255,255,255,.5); }
.skills-list summary {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr) 20px;
  gap: clamp(10px, 3vw, 44px); align-items: baseline;
  padding: clamp(20px, 2.6vw, 28px) 0; cursor: pointer; list-style: none;
}
.skills-list summary::-webkit-details-marker { display: none; }
.skills-list summary:focus-visible { outline: 2px solid var(--green); outline-offset: -2px; border-radius: 6px; }
.skills-list summary h3 {
  font-size: clamp(18px, 1.8vw, 22px); line-height: 1.28; letter-spacing: -.016em;
  font-weight: 700; color: var(--ink); margin: 0; max-width: 22ch;
}
.skills-list .teaser { font-size: 15px; line-height: 1.6; color: rgba(20,20,15,.68); }
/* the chevron is drawn, not a glyph */
.skills-list summary::after {
  content: ''; width: 11px; height: 11px; align-self: center; justify-self: end;
  border-right: 1.8px solid var(--green); border-bottom: 1.8px solid var(--green);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .32s var(--ease-out);
}
.skills-list details[open] summary::after { transform: rotate(225deg) translate(-2px, -2px); }
@media (hover: hover) and (pointer: fine) {
  .skills-list summary:hover h3 { color: var(--green); }
}
.skills-list .body { padding: 0 0 clamp(22px, 3vw, 30px); max-width: 74ch; }
.skills-list .desc { font-size: 16px; line-height: 1.7; color: rgba(20,20,15,.82); margin: 0 0 16px; text-wrap: pretty; }
.skills-list .meta { display: flex; flex-direction: column; gap: 10px; }
.skills-list .meta > div {
  font-size: 14.5px; line-height: 1.6; color: rgba(20,20,15,.68);
  padding-left: 14px; border-left: 1px solid var(--green-line);
}
.skills-list .meta b { color: var(--green); font-weight: 700; }
@media (max-width: 760px) {
  .skills-list summary { grid-template-columns: 1fr 20px; }
  .skills-list summary h3 { max-width: none; grid-column: 1; }
  .skills-list .teaser { grid-column: 1 / -1; }
}
@media (prefers-reduced-motion: reduce) {
  .skills-list details, .skills-list summary::after { transition: none; }
}

/* the closing lists are claims with a tighter rhythm: short pairs, not essays */
.skills-who .claim, .skills-next .claim { padding: 16px 0; }
.skills-who .claim:first-child, .skills-next .claim:first-child { padding-top: 0; }
.skills-next .claim-head a { color: inherit; text-decoration-color: rgba(30,91,60,.42); }
.skills-next .claim-head a:hover { color: var(--green); }

/* the three claims beside the capture card carry no heading of their own */
.skills-value .claim-body { max-width: 46ch; }
.skills-values .claim { grid-template-columns: 1fr; padding: 14px 0; }
.skills-values .claim:first-child { padding-top: 0; }

/* install steps: numbered because the order is the instruction */
.skills-steps { list-style: none; counter-reset: step; margin: 0; padding: 0; }
.skills-steps li {
  counter-increment: step; position: relative;
  padding: 14px 0 14px 40px; border-top: 1px solid rgba(20,20,15,.08);
}
.skills-steps li:first-child { border-top: none; padding-top: 0; }
.skills-steps li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute; left: 0; top: 14px;
  font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; font-weight: 600;
  color: var(--green); letter-spacing: .04em;
}
.skills-steps li:first-child::before { top: 0; }
.skills-steps b { display: block; font-size: 15px; margin-bottom: 4px; }
.skills-steps span { font-size: 14px; line-height: 1.6; color: rgba(20,20,15,.68); }
.skills-steps code {
  font-family: 'IBM Plex Mono', monospace; font-size: 12.5px;
  background: var(--green-soft); color: var(--green);
  padding: 2px 6px; border-radius: 5px;
}

/* capture card, and the link it turns into */
.skills-capture .note { font-size: 14px; color: rgba(20,20,15,.68); margin: 6px 0 18px; }
.skills-capture h2 { font-size: clamp(22px, 2.4vw, 28px); }
.skills-capture select {
  font-family: Archivo, sans-serif; font-size: 16px; padding: 13px 16px;
  border-radius: var(--r-sm); border: 1.5px solid rgba(20,20,15,.18); background: #fff;
  color: var(--ink); width: 100%;
}
.skills-capture select:focus { border-color: var(--green); box-shadow: 0 0 0 4px var(--green-soft); outline: none; }
.skills-capture .done { display: none; }
.skills-capture .done.on { display: block; animation: decide-in .34s var(--ease-out) both; }
.skills-capture .done:focus { outline: none; }
.skills-capture #formview[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .skills-capture .done.on { animation: none; } }

/* screen-reader-only announcement text */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; overflow: hidden; white-space: nowrap;
  clip: rect(0 0 0 0); clip-path: inset(50%);
}

/* queue / board widgets */
.panel {
  background: #fff; border-radius: var(--r-xl); border: 1px solid rgba(30,91,60,.1);
  box-shadow: var(--shadow-card); padding: clamp(22px, 3vw, 36px);
}
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 20px; flex-wrap: wrap; }
.panel-title { font-weight: 700; font-size: 15px; }
.count-badge {
  font-family: 'IBM Plex Mono', monospace; font-weight: 600; font-size: 13px;
  background: var(--green-soft); color: var(--green); border-radius: var(--r-sm); padding: 4px 10px;
}
.queue-list { display: flex; flex-wrap: wrap; gap: 10px; }
.queue-chip { background: var(--paper-green); border-radius: var(--r-sm); padding: 10px 14px; font-size: 13.5px; }
.queue-chip b { display: block; font-size: 14px; margin-bottom: 2px; }
.queue-chip span { color: rgba(20,20,15,.68); font-size: 12px; }

.room-list { display: flex; flex-direction: column; gap: 8px; }
/* the hero card carries eleven rows; a little tighter there keeps it compact
   without touching the same component inside the showcase panels */
.diagram-card .room-list { gap: 6px; }
.diagram-card .room-row { padding: 8px 13px; }
.room-row { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-radius: var(--r-sm); background: var(--paper-green); font-size: 14px; font-weight: 600; }
.room-row.you { background: var(--ink); color: var(--paper); }
.room-row .status { font-size: 12px; font-weight: 600; color: var(--green); }
.room-row.you .status { color: var(--periwinkle); }
.room-row.open { border-style: dashed; border: 1px dashed rgba(30,91,60,.35); background: transparent; }
/* "agent" tag ahead of the room status */
.room-row .status-kind {
  color: var(--green); font-weight: 700;
  letter-spacing: .02em; text-transform: uppercase; font-size: 10.5px;
}
/* 10.5px uppercase is under the comfortable floor on a phone */
@media (max-width: 640px) { .room-row .status-kind { font-size: 11.5px; } }
/* the live indicator breathes so the panel reads as a running deal */
.live-dot { position: relative; animation: liveglow 2.4s ease-in-out infinite; }
@keyframes liveglow {
  0%, 100% { color: var(--green); text-shadow: 0 0 0 rgba(30,91,60,0); }
  50%      { color: #2c7d54; text-shadow: 0 0 9px rgba(44,125,84,.65); }
}
@media (prefers-reduced-motion: reduce) {
  .live-dot { animation: none; }
}

.board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
@media (max-width: 700px) { .board { grid-template-columns: 1fr; } }
.board-col { background: var(--paper-green); border-radius: var(--r-md); padding: 14px; }
.board-col h3 { font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; font-weight: 600; letter-spacing: .04em; margin: 0 0 10px; display: flex; justify-content: space-between; gap: 8px; white-space: nowrap; color: rgba(20,20,15,.68); }
.board-col ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.board-col li { font-size: 13.5px; background: #fff; border-radius: 8px; padding: 8px 10px; }
.board-status { display: flex; align-items: center; gap: 10px; margin-top: 16px; font-family: 'IBM Plex Mono', monospace; font-size: 12.5px; font-weight: 600; }
.deal-live { display: inline-flex; align-items: center; gap: 9px; color: var(--green); }
.deal-live-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--green); flex: none;
  animation: dealpulse 2s ease-out infinite;
}
@keyframes dealpulse {
  0%   { box-shadow: 0 0 0 0 rgba(30,91,60,.55), 0 0 6px 1px rgba(30,91,60,.5); }
  70%  { box-shadow: 0 0 0 9px rgba(30,91,60,0),  0 0 12px 3px rgba(30,91,60,.75); }
  100% { box-shadow: 0 0 0 0 rgba(30,91,60,0),    0 0 6px 1px rgba(30,91,60,.5); }
}

/* board pills in motion — see the FLIP sequence in main.js */
.board-col li { position: relative; will-change: transform; }
.board-col li.is-landing {
  animation: landpop .5s var(--ease-out);
  box-shadow: 0 8px 20px -8px rgba(30,91,60,.5);
}
@keyframes landpop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.07); }
  100% { transform: scale(1); }
}
.board-col h3 span { display: inline-block; }
.count-bump { animation: countbump .5s var(--ease-out); }
@keyframes countbump {
  0%   { transform: scale(1); color: inherit; }
  40%  { transform: scale(1.42); color: var(--green); }
  100% { transform: scale(1); color: inherit; }
}
@media (prefers-reduced-motion: reduce) {
  .deal-live-dot, .board-col li.is-landing, .count-bump { animation: none; }
  .board-col li.is-landing { box-shadow: none; }
}

/* branch diagram (how an answer happens) */
.branch { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
@media (max-width: 800px) { .branch { grid-template-columns: 1fr; } }
.branch-col {
  background: #fff; border-radius: var(--r-lg); border: 1px solid rgba(30,91,60,.1);
  box-shadow: var(--shadow-card); padding: 24px;
}
/* .branch-col is a direct child of [data-cascade], whose `> *` reveal rule has
   equal specificity and lands later — so the hover transition has to outrank it
   or box-shadow and border-color would snap instead of easing. opacity stays in
   the list so these cards still fade in with the cascade rather than popping. */
.branch > .branch-col {
  transition: opacity .6s var(--ease-out), transform .38s var(--ease-out),
              box-shadow .38s var(--ease-out), border-color .28s var(--ease-io);
}
@media (hover: hover) and (pointer: fine) {
  .branch > .branch-col:hover {
    transform: translateY(-4px);
    border-color: rgba(30,91,60,.42);
    box-shadow: 0 2px 6px rgba(30,91,60,.10),
                0 22px 50px -16px rgba(30,91,60,.42),
                0 0 0 4px rgba(30,91,60,.07);
  }
}
@media (prefers-reduced-motion: reduce) {
  .branch > .branch-col { transition: none; }
  .branch > .branch-col:hover { transform: none; }
}
.branch-step { padding: 12px 0; border-top: 1px solid rgba(20,20,15,.08); }
.branch-step:first-of-type { border-top: none; padding-top: 0; }
/* Rows that each answer one question, so each is its own object to look at.
   The same lift the limit cards use, so the gesture means the same thing here. */
.branch-col--rows .branch-step {
  padding: 12px 14px; margin: 0 -14px; border-radius: var(--r-sm);
  transition: background-color .24s var(--ease-io), transform .3s var(--ease-out),
              box-shadow .3s var(--ease-out);
}
.branch-col--rows .branch-step b { transition: color .24s var(--ease-io); }
@media (hover: hover) and (pointer: fine) {
  .branch-col--rows .branch-step:hover {
    background: var(--green-soft); transform: translateY(-2px); box-shadow: var(--shadow-card);
  }
  .branch-col--rows .branch-step:hover b { color: var(--green); }
}
@media (prefers-reduced-motion: reduce) {
  .branch-col--rows .branch-step { transition: background-color .24s var(--ease-io); }
  .branch-col--rows .branch-step:hover { transform: none; }
}
.branch-step b { display: block; font-size: 14.5px; margin-bottom: 3px; }
.branch-step span { font-size: 13.5px; color: rgba(20,20,15,.65); }
.branch-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.mini-btn { font-size: 12.5px; font-weight: 600; padding: 7px 12px; border-radius: var(--r-pill); border: 1px solid rgba(20,20,15,.18); background: var(--paper); }

/* the decision controls — darker than the read-only chips beside them, and
   genuinely pressable. Scoped to button so the plain <span> chips in the other
   column keep their lighter treatment. */
button.mini-btn {
  background: rgba(20,20,15,.10);
  border-color: rgba(20,20,15,.28);
  color: var(--ink);
  cursor: pointer;
  font-family: Archivo, sans-serif;
  transition: background-color .22s var(--ease-io), color .22s var(--ease-io),
              border-color .22s var(--ease-io), transform .28s var(--ease-out),
              box-shadow .28s var(--ease-out);
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) and (pointer: fine) {
  button.mini-btn:hover {
    background: rgba(20,20,15,.18);
    border-color: rgba(20,20,15,.4);
  }
}
button.mini-btn:active { transform: scale(.96); }
button.mini-btn[aria-pressed="true"] {
  background: var(--green); border-color: var(--green); color: var(--paper);
  box-shadow: 0 6px 16px -8px rgba(30,91,60,.65);
}
@media (max-width: 640px) {
  /* Approve / Hold / Counter are pressable, so they need a real touch target */
  button.mini-btn { padding: 11px 16px; font-size: 13.5px; }
}
@media (prefers-reduced-motion: reduce) {
  button.mini-btn { transition: none; }
  button.mini-btn:active { transform: none; }
}

/* the inert social placeholder left in place while that account is paused */

/* formula (how it gets good) */
.formula { display: flex; flex-wrap: wrap; align-items: stretch; gap: 14px; }
.formula-block { flex: 1 1 220px; background: #fff; border-radius: var(--r-lg); border: 1px solid rgba(30,91,60,.1); box-shadow: var(--shadow-card); padding: 20px; }
.formula-block h3 { font-size: 13px; font-weight: 700; letter-spacing: .01em; color: var(--green); margin: 0 0 8px; }
.formula-block p { font-size: 13.5px; color: rgba(20,20,15,.7); margin: 0; }
.formula-op { display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: 700; color: var(--grey); flex: 0 0 auto; }
.progress-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-top: 20px; }
@media (max-width: 700px) { .progress-row { grid-template-columns: 1fr; } }
.progress-card { padding: 16px; border-radius: var(--r-md); background: var(--paper-green); }
.progress-card b { display: block; font-size: 13.5px; margin-bottom: 4px; }
.progress-card span { font-size: 13px; color: rgba(20,20,15,.68); }

/* outcomes (who it's for) */
.outcomes { display: flex; flex-direction: column; gap: 18px; margin-top: 28px; }
.outcome-row { display: flex; gap: 14px; align-items: flex-start; padding: 18px 0; border-top: 1px solid rgba(20,20,15,.1); }
.outcome-row:first-child { border-top: none; padding-top: 0; }
.outcome-row .num { font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--grey); flex: none; padding-top: 3px; }
.outcome-row p { font-size: 17px; line-height: 1.5; max-width: 48ch; }
.outcome-row em { font-style: normal; color: var(--green); font-weight: 700; }

/* ruling — an attributed decision: the statement, then who ruled it and when.
   The whole product turns on answers carrying a name, so the attribution is
   part of the component rather than a caption underneath it. */
.ruling-list { display: flex; flex-direction: column; gap: 14px; }
.ruling {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  background: #fff; border: 1px solid rgba(30,91,60,.12); border-radius: var(--r-md);
  padding: 16px 18px; box-shadow: var(--shadow-card);
}
.ruling-text { font-size: 15px; line-height: 1.5; margin: 0; color: var(--ink); }
.ruling-text b { font-weight: 700; }
.ruling-by {
  font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .01em;
  line-height: 1.45; color: rgba(20,20,15,.68); margin: 8px 0 0;
}
.ruling-ini {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--green-soft); color: var(--green);
  font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; font-weight: 600;
}

/* ── the board: a position that fills in rather than a table that is already
   full. Columns arrive left to right, then a term crosses from open to given
   and both counters follow it. */
.board-n { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }
.board-col li { transition: background-color .3s var(--ease-io), color .3s var(--ease-io); }
.board-empty {
  margin: 0; font-size: 12.5px; color: rgba(20,20,15,.68);
  font-style: normal; transition: opacity .3s var(--ease-io);
}
.board-empty[hidden] { display: none; }
.board-col li[data-board-move] { position: relative; z-index: 1; }
/* a term that has just crossed reads as settled, not as new */
.board-col li[data-grab] {
  cursor: grab; touch-action: none; -webkit-tap-highlight-color: transparent;
  /* see the coarse-pointer override below: on touch these are tapped, not
     dragged, so they must not swallow a scroll gesture */
  transition: background-color .24s var(--ease-io), box-shadow .24s var(--ease-out),
              transform .3s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .board-col li[data-grab]:hover {
    box-shadow: 0 1px 2px rgba(30,91,60,.08), 0 6px 16px -8px rgba(30,91,60,.28);
    transform: translateY(-1px);
  }
}
.board-col li[data-grab]:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
@media (pointer: coarse) {
  .board-col li[data-grab] { touch-action: manipulation; cursor: pointer; }
}
/* the chip under the pointer: out of flow, tracking 1:1 */
.board-col li.is-dragging {
  position: fixed; z-index: 60; margin: 0; cursor: grabbing;
  box-shadow: 0 10px 30px -8px rgba(20,30,22,.34), 0 2px 6px rgba(20,30,22,.12);
  transition: none;
}
/* the space it left, held open so the column never jumps */
.board-ghost { border-radius: 8px; background: rgba(30,91,60,.05); }
.board-col { transition: background-color .24s var(--ease-io), box-shadow .24s var(--ease-io); }
.board-col.is-target { background: var(--green-soft); box-shadow: inset 0 0 0 1px var(--green-line); }
.board-col li.is-given {
  background: var(--green-soft);
  box-shadow: inset 0 0 0 1px var(--green-line);
}
html.js [data-board] .board-col { opacity: 0; transform: translateX(-14px); }
html.js [data-board].is-running .board-col {
  opacity: 1; transform: none;
  transition: opacity .5s var(--ease-out), transform .5s var(--ease-out);
}
html.js [data-board].is-running [data-board-col="2"] { transition-delay: .18s; }
html.js [data-board].is-running [data-board-col="3"] { transition-delay: .36s; }
@media (prefers-reduced-motion: reduce) {
  html.js [data-board] .board-col,
  html.js [data-board].is-running .board-col { opacity: 1; transform: none; transition: none; }
}

/* ── the decision: three ways to answer, one of them yours */
.decide { margin-top: 18px; padding-top: 16px; border-top: 1px solid rgba(30,91,60,.14); }
.decide-q {
  margin: 0 0 12px; font-size: 14px; font-weight: 600; color: var(--ink);
  letter-spacing: -.005em;
}
.decide-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.decide-actions[hidden] { display: none; }
.decide-btn {
  flex: 1 1 auto; padding: 10px 14px; border-radius: var(--r-pill);
  border: 1px solid rgba(30,91,60,.28); background: #fff; color: var(--green);
  font-family: Archivo, sans-serif; font-size: 13.5px; font-weight: 600;
  letter-spacing: -.005em; cursor: pointer; touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .18s var(--ease-io), color .18s var(--ease-io),
              border-color .18s var(--ease-io), transform .18s var(--ease-out);
}
.decide-btn:active { transform: scale(.97); }
@media (hover: hover) and (pointer: fine) {
  .decide-btn:hover { background: var(--green); border-color: var(--green); color: var(--paper); }
}
.decide-out[hidden] { display: none; }
.decide-out { animation: decide-in .34s var(--ease-out) both; }
@keyframes decide-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.decide-back {
  margin-top: 12px; display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px 7px 9px; border-radius: var(--r-pill);
  border: 1px solid transparent; background: transparent;
  color: rgba(20,20,15,.68); font-family: Archivo, sans-serif;
  font-size: 12.5px; font-weight: 600; cursor: pointer;
  transition: color .18s var(--ease-io), background-color .18s var(--ease-io);
}
.decide-back svg { width: 13px; height: 13px; }
@media (hover: hover) and (pointer: fine) {
  .decide-back:hover { color: var(--green); background: var(--green-soft); }
}
@media (prefers-reduced-motion: reduce) { .decide-out { animation: none; } }

/* ── the limits: the rule is the whole card until you ask who set it */
.limit-list { display: flex; flex-direction: column; gap: 12px; }
.limit {
  position: relative; overflow: hidden;
  background: #fff; border: 1px solid rgba(30,91,60,.12); border-radius: var(--r-md);
  padding: 18px 20px; box-shadow: var(--shadow-card); cursor: default;
  transition: box-shadow .32s var(--ease-out), border-color .24s var(--ease-io),
              transform .32s var(--ease-out);
}
.limit-rule {
  margin: 0; font-size: 15.5px; font-weight: 600; line-height: 1.45;
  letter-spacing: -.008em; color: var(--ink);
}
.limit-meta {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .34s var(--ease-out), opacity .24s var(--ease-io);
  opacity: 0;
}
.limit-meta > span:last-child { overflow: hidden; }
.limit-meta span { display: block; }
.limit-meta b {
  display: block; font-weight: 700; font-size: 12.5px; color: var(--green);
  letter-spacing: .005em; margin: 12px 0 2px;
}
.limit-meta > span:last-child {
  font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; line-height: 1.5;
  letter-spacing: .01em; color: rgba(20,20,15,.68);
}
.limit-ini {
  position: absolute; top: 16px; right: 18px;
  width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--green-soft); color: var(--green);
  font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; font-weight: 600;
  opacity: 0; transform: scale(.9);
  transition: opacity .24s var(--ease-io), transform .3s var(--ease-out);
}
.limit:hover, .limit:focus-visible { border-color: rgba(30,91,60,.3); box-shadow: var(--shadow-pop); }
.limit:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
.limit:hover .limit-meta, .limit:focus-visible .limit-meta { grid-template-rows: 1fr; opacity: 1; }
.limit:hover .limit-ini, .limit:focus-visible .limit-ini { opacity: 1; transform: none; }
@media (hover: hover) and (pointer: fine) {
  .limit:hover { transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
  .limit, .limit-meta, .limit-ini { transition: none; }
  .limit:hover { transform: none; }
}
/* no hover on touch, so the authority is simply always shown */
@media (hover: none) {
  .limit-meta { grid-template-rows: 1fr; opacity: 1; }
  .limit-ini { opacity: 1; transform: none; }
}


/* closing call to action on the standalone pages */
.page-cta { max-width: 60ch; }
.page-cta h2 { font-size: clamp(26px, 3.4vw, 38px); }
.page-cta .body-copy { margin-top: 16px; }
.page-cta .hero-ctas { margin-top: 26px; }

/* reusable lift-and-glow, matching the branch cards */
.hover-glow {
  transition: transform .38s var(--ease-out), box-shadow .38s var(--ease-out),
              border-color .28s var(--ease-io);
}
@media (hover: hover) and (pointer: fine) {
  .hover-glow:hover {
    transform: translateY(-4px);
    border-color: rgba(30,91,60,.42);
    box-shadow: 0 2px 6px rgba(30,91,60,.10),
                0 22px 50px -16px rgba(30,91,60,.42),
                0 0 0 4px rgba(30,91,60,.07);
  }
}
@media (prefers-reduced-motion: reduce) {
  .hover-glow { transition: none; }
  .hover-glow:hover { transform: none; }
}

/* trust rules (why trust it) */
.rules-list { display: flex; flex-direction: column; gap: 0; }
/* padded and pulled back out, so the hover card can fill a rounded block
   without the text shifting when it appears */
.rule-row {
  display: grid; grid-template-columns: 56px 1fr; gap: 18px;
  padding: 26px 20px; margin: 0 -20px;
  border-top: 1px solid rgba(20,20,15,.1);
  border-radius: var(--r-lg);
}
.rule-row:first-child { border-top: none; }
/* .rule-row is a direct child of [data-cascade]; its `> *` rule has equal
   specificity and lands later, so this has to outrank it to transition at all */
.rules-list > .rule-row {
  transition: background-color .3s var(--ease-io), box-shadow .38s var(--ease-out),
              border-top-color .3s var(--ease-io), opacity .6s var(--ease-out),
              transform .6s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .rules-list > .rule-row:hover {
    background: #fff;
    border-top-color: transparent;
    box-shadow: 0 2px 6px rgba(30,91,60,.08),
                0 18px 42px -18px rgba(30,91,60,.38),
                0 0 0 1px rgba(30,91,60,.10);
  }
  .rules-list > .rule-row:hover + .rule-row { border-top-color: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .rules-list > .rule-row { transition: none; }
}
.rule-num { font-size: 26px; font-weight: 800; color: var(--green); }
.rule-row h3 { font-size: 17px; letter-spacing: normal; margin: 0 0 6px; }
.rule-row p { font-size: 15px; color: rgba(20,20,15,.68); max-width: 56ch; }

/* form */
.form-panel { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
@media (max-width: 640px) { .form-panel { grid-template-columns: 1fr; } }
.field { display: flex; flex-direction: column; gap: 6px; position: relative; }
.field.full { grid-column: 1 / -1; }
label { font-size: 12.5px; font-weight: 600; letter-spacing: .02em; color: rgba(20,20,15,.65); }
input, textarea {
  font-family: Archivo, sans-serif; font-size: 16px; padding: 13px 16px;
  border-radius: var(--r-sm); border: 1.5px solid rgba(20,20,15,.18); background: #fff;
  transition: border-color .2s var(--ease-io), box-shadow .2s var(--ease-io);
  touch-action: manipulation;
}
input:focus, textarea:focus { border-color: var(--green); box-shadow: 0 0 0 4px var(--green-soft); outline: none; }
input::placeholder, textarea::placeholder { color: rgba(20,20,15,.68); }
input.invalid, textarea.invalid { border-color: var(--error); }
textarea { resize: vertical; min-height: 96px; }
.field .check { position: absolute; right: 14px; top: 38px; color: var(--green); opacity: 0; transition: opacity .2s var(--ease-io); }
.field.valid .check { opacity: 1; }
.form-note { font-size: 13px; color: rgba(20,20,15,.68); margin-top: 16px; max-width: 60ch; }
.form-msg { font-size: 14px; font-weight: 600; margin-top: 14px; border-radius: var(--r-sm); padding: 12px 16px; display: none; }
.form-msg.show { display: block; }
/* An author `display:block` outranks the UA rule for [hidden], so a message
   that is hidden by attribute rather than by class would still paint. This
   sits after .show deliberately: equal specificity, later wins. */
.form-msg[hidden] { display: none; }
.form-msg.ok { background: var(--green-soft); color: var(--green); }
.form-msg.err { background: rgba(192,69,59,.1); color: var(--error); }
.shake { animation: shakex .4s var(--ease-io); }
@keyframes shakex { 0%,100%{transform:translateX(0)} 30%{transform:translateX(-5px)} 70%{transform:translateX(5px)} }
@media (prefers-reduced-motion: reduce) { .shake { animation: none; } }
.socials { display: flex; gap: 10px; margin: 18px 0 28px; }

/* The label and the icons are one thing, so they sit close; the group is a
   different thing from the demo card above it, so it sits apart. The spacing
   used to say the opposite: 28px inside the group, 4px outside it. */
.connect { margin-top: 30px; }
.connect-label {
  font-size: 13px; font-weight: 600; letter-spacing: .01em;
  color: rgba(20,20,15,.68); margin: 0 0 9px;
}
.connect .socials { margin: 0; }
.social-btn { width: 42px; height: 42px; border-radius: 50%; border: 1px solid rgba(20,20,15,.18); display: flex; align-items: center; justify-content: center; transition: border-color .2s var(--ease-io), color .2s var(--ease-io); }
.social-btn:hover { border-color: var(--green); }
.social-btn svg { width: 18px; height: 18px; }
.badge-line { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--green); background: var(--green-soft); border-radius: var(--r-pill); padding: 8px 16px; margin-bottom: 22px; }

/* ── stack: the last three sections cascade over one another ──────────────
   Pure CSS sticky, so scrolling back up reverses the effect for free. Each
   card is opaque and rounds its top edge so the one below reads as sliding
   underneath the next. */
.stack { position: relative; }
.stack-card {
  position: sticky; top: 0;
  min-height: 100svh;
  display: flex; align-items: center;
  padding: clamp(64px, 8vh, 104px) 0;
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  box-shadow: 0 -18px 44px -22px rgba(14,30,20,.4);
}
.stack-card--shift   { background: var(--green); color: var(--paper); z-index: 1; }
.stack-card--data    { background: var(--paper-green); z-index: 2; }
.stack-card--request { background: var(--paper); z-index: 3; }
.stack-inner { width: 100%; }
.stack-inner--centre { max-width: 760px; text-align: center; }
.stack-inner--centre .pill-label { align-self: center; }
.stack-inner--centre .body-copy { margin-left: auto; margin-right: auto; }
/* the last card must not be sticky-trapped above the footer */
.stack-card--request { position: relative; }
@media (prefers-reduced-motion: reduce) {
  .stack-card { position: relative; min-height: 0; }
}
@media (max-width: 700px) {
  .stack-card { min-height: 0; border-radius: var(--r-lg) var(--r-lg) 0 0; }
}

/* pill label on the dark card */
.pill-label--onDark { color: var(--paper); background: rgba(241,239,232,.14); }

/* slow breathing halo — a tint of --green, never a neon ring (see CLAUDE.md) */
.pill-label--glow {
  position: relative;
  animation: pillbreathe 4.2s var(--ease-io) infinite;
}
@keyframes pillbreathe {
  0%, 100% { box-shadow: 0 0 0 0 rgba(30,91,60,.26), 0 0 0 0 rgba(30,91,60,0); }
  50%      { box-shadow: 0 0 0 6px rgba(30,91,60,.07), 0 0 18px 2px rgba(30,91,60,.22); }
}
@media (prefers-reduced-motion: reduce) {
  .pill-label--glow { animation: none; box-shadow: 0 0 14px 1px rgba(30,91,60,.2); }
}

/* ── skyline: flat stencil backdrop for the request card ────────────────
   San Francisco on the left, New York on the right. Decorative only — it
   sits behind the content and rises from the card's bottom edge on reveal. */
.stack-card--request { position: relative; overflow: hidden; }
.stack-card--request > .wrap { position: relative; z-index: 1; }
.skyline {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: min(52%, 430px);
  z-index: 0; pointer-events: none;
  display: block;
}
.skyline .sky-solid { fill: var(--green); }
/* bridge cables, hangers and window details — too fine to read as fills */
.skyline .sky-line {
  fill: none; stroke: var(--green); stroke-width: 2.4;
  stroke-linecap: round; stroke-linejoin: round;
}
/* the rise. Hidden state is only applied when JS can animate it back. */
html.js .skyline { transform: translateY(100%); opacity: 0; }
html.js .skyline.is-up {
  transform: translateY(0); opacity: .13;
  transition: transform 1.5s var(--ease-out), opacity 1.1s var(--ease-out);
}
html:not(.js) .skyline { opacity: .13; }
@media (prefers-reduced-motion: reduce) {
  html.js .skyline { transform: none; opacity: .13; }
  html.js .skyline.is-up { transition: none; }
}
@media (max-width: 700px) {
  .skyline { height: min(38%, 240px); }
}

/* ── the shift: converge diagram ─────────────────────────────────────────
   Replicates the old site's behaviour — nodes fade in staggered, connector
   lines draw downward, then the core lights up as they land — restyled to
   the green/paper world and set in Archivo (CLAUDE.md keeps mono to the
   negotiation board). */
.shift-head {
  margin-top: 20px; max-width: 22ch;
  font-size: clamp(30px, 4.2vw, 56px); line-height: 1.08; letter-spacing: -.028em;
}
.shift-svg { width: 100%; display: block; margin-top: clamp(40px, 5.5vw, 68px); overflow: visible; }

.shift-line {
  fill: none; stroke: rgba(174,187,240,.5); stroke-width: 1.2;
}
.shift-node circle { stroke-width: 1.5; }
.shift-node text {
  font-family: Archivo, sans-serif; font-size: 12px; font-weight: 600;
  letter-spacing: .01em;
}
.shift-node--human circle { fill: var(--paper); stroke: var(--paper); }
.shift-node--human text   { fill: var(--paper); }
.shift-node--agent circle { fill: var(--periwinkle); stroke: var(--periwinkle); }
.shift-node--agent text   { fill: rgba(174,187,240,.92); }

.shift-core rect {
  fill: none; stroke: rgba(241,239,232,.55); stroke-width: 1.4;
}
.shift-core text {
  font-family: Archivo, sans-serif; font-size: 13px; font-weight: 700;
  letter-spacing: .06em; fill: var(--paper);
}
/* One-shot glow as the lines land. It deliberately resolves back to the
   resting stroke rather than using `forwards`, so the hover state below is
   free to take over the same properties once the glow is done. */
.shift-core.is-lit rect { animation: coreglow 1.5s var(--ease-out) 1; }
@keyframes coreglow {
  0%   { stroke: rgba(241,239,232,.55); filter: none; }
  35%  { stroke: var(--periwinkle); filter: drop-shadow(0 0 14px rgba(174,187,240,.95)); }
  100% { stroke: rgba(241,239,232,.55); filter: drop-shadow(0 0 0 rgba(174,187,240,0)); }
}
/* interactive once it has landed */
.shift-core.is-lit { cursor: pointer; }
.shift-core rect, .shift-core text {
  transition: fill .28s var(--ease-io), stroke .28s var(--ease-io);
}
@media (hover: hover) and (pointer: fine) {
  .shift-core.is-lit:hover rect { fill: rgba(9,32,20,.55); stroke: var(--periwinkle); }
  .shift-core.is-lit:hover text { fill: #fff; }
}
/* Phones get a real HTML version instead. The SVG is 1000 units wide, so on a
   390px screen it scales to ~0.33 and its labels rendered at 5px — unreadable.
   Exactly one of the two is in the DOM flow at any width, so the diagram is
   never announced twice. */
.shift-mobile { display: none; }
@media (max-width: 640px) {
  .shift-svg { display: none; }
  .shift-mobile { display: block; margin-top: clamp(30px, 6vw, 44px); }
  .shift-chips {
    list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px;
  }
  .shift-chip {
    border-radius: var(--r-sm); padding: 12px 14px;
    font-size: 14px; font-weight: 600; line-height: 1.25;
    background: rgba(241,239,232,.12); color: rgba(241,239,232,.92);
    border: 1px solid rgba(241,239,232,.2);
  }
  .shift-chip--human {
    grid-column: 1 / -1;
    background: var(--paper); color: var(--green); border-color: var(--paper);
  }
  .shift-funnel {
    width: 2px; height: 34px; margin: 14px auto 0;
    background: linear-gradient(to bottom, rgba(174,187,240,.15), rgba(174,187,240,.85));
  }
  .shift-core-m {
    margin: 14px auto 0; max-width: 300px; text-align: center;
    border: 1.5px solid rgba(241,239,232,.55); border-radius: var(--r-pill);
    padding: 14px 20px; font-size: 14px; font-weight: 700;
    letter-spacing: .04em; text-transform: uppercase; color: var(--paper);
  }
  .shift-core-m.is-lit { animation: coreglow 1.5s var(--ease-out) 1; }
}

/* ── your data ───────────────────────────────────────────────────────── */
.data-head {
  margin-top: 18px;
  font-size: clamp(24px, 3.2vw, 38px); line-height: 1.12; letter-spacing: -.025em;
  max-width: 20ch; margin-left: auto; margin-right: auto;
}
.data-body { margin-top: 16px; max-width: 56ch; }

/* ── ask box ─────────────────────────────────────────────────────────── */
.ask {
  margin-top: clamp(28px, 4vw, 40px); text-align: left;
  background: #fff; border: 1px solid rgba(30,91,60,.14);
  border-radius: var(--r-lg); box-shadow: var(--shadow-card);
  padding: 18px 18px 14px;
  transition: border-color .25s var(--ease-io), box-shadow .3s var(--ease-out);
}
.ask:focus-within { border-color: var(--green); box-shadow: var(--shadow-pop); }
.ask-label {
  display: block; font-size: 12.5px; font-weight: 600;
  color: rgba(20,20,15,.68); margin-bottom: 8px;
}
.ask-field {
  width: 100%; border: none; padding: 0; background: transparent;
  font-family: Archivo, sans-serif; font-size: 17px; line-height: 1.5; color: var(--ink);
  resize: none;
}
.ask-field:focus { outline: none; box-shadow: none; }
.ask-foot {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 14px; margin-top: 16px; flex-wrap: nowrap;
}
/* chips wrap inside their own column so the send button stays pinned right */
.ask-chips { display: flex; flex-wrap: wrap; gap: 8px; flex: 1 1 auto; min-width: 0; }
.ask-chip {
  font-family: Archivo, sans-serif; font-size: 13px; font-weight: 600;
  color: rgba(20,20,15,.66); background: var(--paper-green);
  border: 1px solid transparent; border-radius: var(--r-pill);
  padding: 8px 14px; cursor: pointer; text-align: left;
  transition: background-color .2s var(--ease-io), color .2s var(--ease-io),
              border-color .2s var(--ease-io), transform .3s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .ask-chip:hover { color: var(--green); border-color: rgba(30,91,60,.35); }
}
.ask-chip:active { transform: scale(.97); }
.ask-chip[aria-pressed="true"] { background: var(--green); color: var(--paper); }
.ask-send {
  flex: none; width: 46px; height: 46px; border-radius: 50%;
  background: var(--green); color: var(--paper); border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background-color .2s var(--ease-io), transform .3s var(--ease-out);
}
.ask-send:hover { background: #184a30; }
.ask-send:active { transform: scale(.94); }
.ask-send svg { width: 18px; height: 18px; }
@media (max-width: 640px) {
  /* 32px is below a usable touch target */
  .ask-chip { padding: 11px 14px; }
}
@media (prefers-reduced-motion: reduce) {
  .ask-chip, .ask-send, .ask { transition: none; }
  .shift-core.is-lit rect { animation: none; }
}

/* cascade reveal */
[data-cascade] > * {
  opacity: 0;
  /* a little more travel plus a barely-there scale, so each line arrives
     rather than just fading — nothing starts from nothing */
  transform: translateY(24px) scale(.985);
  transition: opacity .72s var(--ease-out), transform .72s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 90ms);
}
[data-cascade].in > * { opacity: 1; transform: none; }
/* Scripting off means nothing ever adds .in, which would leave every cascaded
   block invisible. Written as an override rather than by gating the rule above,
   so the specificity of the base rule stays put — other components scope their
   own transitions against it. */
html:not(.js) [data-cascade] > * { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-cascade] > * { transition: none; opacity: 1; transform: none; }
}

/* footer — brand block on the left, grouped link columns stacked on the right */
.site-footer { padding: 64px 0 56px; border-top: 1px solid rgba(20,20,15,.1); }
.footer-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  flex-wrap: wrap; gap: 40px clamp(32px, 6vw, 96px);
}
.footer-brand { display: flex; flex-direction: column; gap: 14px; max-width: 34ch; }
.footer-brand .brand { font-size: 18px; }
.footer-blurb { margin: 0; font-size: 14px; line-height: 1.55; color: rgba(20,20,15,.68); text-wrap: pretty; }
.footer-nav { display: flex; flex-wrap: wrap; gap: 32px clamp(24px, 3.2vw, 48px); }
/* even column rhythm: the widest label (Privacy Policy) sets the floor */
.footer-col { min-width: 132px; }
.footer-col-title {
  font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; color: rgba(20,20,15,.68);
  margin: 0 0 14px;
}
.footer-links {
  display: flex; flex-direction: column; gap: 10px;
  list-style: none; margin: 0; padding: 0; font-size: 14px; font-weight: 500;
}
.footer-links a { color: rgba(20,20,15,.65); transition: color .2s var(--ease-io); }
.footer-links a:hover { color: var(--ink); }
@media (max-width: 720px) {
  .footer-row { gap: 34px; }
  .footer-nav { gap: 28px 32px; }
  .footer-col { min-width: 118px; }
  .footer-brand { max-width: none; }
}

/* intro loader — ivory field, outlined wordmark filling green, then the whole
   plate slides up off the top to reveal the page. Hidden unless JS arms it
   (see the inline script in index.html) so no-JS visitors are never blocked. */
.loader { display: none; }
html.is-loading .loader {
  display: flex;
  position: fixed; inset: 0; z-index: 200;
  background: var(--paper);
  align-items: flex-end; justify-content: flex-end;
  padding: clamp(30px, 5vw, 76px);
  transform: translateY(0);
  /* ease-out on the way up: the curtain leaves fast and settles, so the page
     underneath feels like it arrives immediately rather than being waited on */
  transition: transform 1s var(--ease-out);
  will-change: transform;
}
html.is-loading .loader.is-leaving { transform: translateY(-100%); }
html.is-loading body { overflow: hidden; }

.loader-word { position: relative; line-height: .82; }
.loader-outline,
.loader-fill {
  display: block;
  font-family: Archivo, sans-serif;
  font-size: clamp(58px, 12vw, 168px);
  font-weight: 800;
  letter-spacing: -.035em;
}
.loader-outline {
  color: transparent;
  -webkit-text-stroke: 1.6px var(--ink);
}
.loader-fill {
  position: absolute; inset: 0;
  color: var(--green);
  -webkit-text-stroke: 1.6px var(--green);
  /* fills from the baseline upward as the top inset retracts */
  clip-path: inset(100% 0 0 0);
  transition: clip-path 1.7s var(--ease-io);
  will-change: clip-path;
}
html.is-loading .loader.is-filling .loader-fill { clip-path: inset(0 0 0 0); }

/* skip link */
/* Touch targets. Everything interactive clears 44px on a coarse pointer;
   desktop keeps its tighter, more composed sizing. */
@media (pointer: coarse) {
  .decide-btn, .compose-go, .mini-btn { min-height: 44px; }
  .decide-back { min-height: 44px; padding-left: 12px; padding-right: 14px; }
  .board-col li[data-grab] { min-height: 44px; display: flex; align-items: center; }
  .social-btn { width: 46px; height: 46px; }
  .learn-link, .demo-pill { min-height: 44px; }
  .nav-links a { padding-top: 12px; padding-bottom: 12px; }
}
.skip-link {
  position: absolute; left: 12px; top: 12px; z-index: 100;
  background: var(--ink); color: var(--paper); padding: 10px 18px; border-radius: var(--r-sm);
  /* transform, not top — animating a layout property is banned (CLAUDE.md) */
  transform: translateY(-200%);
  transition: transform .2s var(--ease-out); font-weight: 600; font-size: 14px;
}
.skip-link:focus { transform: translateY(0); }

/* simple content pages (about/contact/privacy/terms/404) */
/* vertical only — the shorthand's `0` used to wipe out .wrap's gutter, which
   both broke alignment against the prose below and pushed the hero text to the
   screen edge on narrow viewports */
.page-hero {
  padding-top: clamp(56px, 8vh, 96px);
  padding-bottom: clamp(32px, 5vh, 56px);
}
.page-hero .lede { margin-top: 16px; }
/* a breath between the label and the headline it introduces */
.page-hero h1 { margin-top: 14px; }
/* a second lede line: same size, so hierarchy comes from weight and colour
   rather than another step down the scale (Apple: build hierarchy from
   weight + size + leading as a set, not size alone) */
.lede-quiet { color: rgba(20,20,15,.68); max-width: 52ch; }
/* the section label carries more weight on a standalone page than inline */
.page-hero .pill-label { font-size: 15px; padding: 10px 22px; letter-spacing: 0; }
.lede-hl { color: var(--green); font-weight: 700; }
.prose { max-width: 68ch; }
.prose h2 { font-size: clamp(22px, 2.6vw, 28px); margin: 2.2em 0 .6em; letter-spacing: -.01em; }
.prose h2:first-child { margin-top: 0; }
.prose p { font-size: 16px; line-height: 1.75; color: rgba(20,20,15,.82); margin: 0 0 1.1em; }
.prose ul { padding-left: 1.2em; margin: 0 0 1.1em; }
.prose li { margin-bottom: .5em; font-size: 16px; line-height: 1.7; color: rgba(20,20,15,.82); }
.back-link { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; font-size: 14px; color: var(--green); margin-bottom: 24px; }
.back-link svg { width: 14px; height: 14px; flex: none; transition: transform .3s var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .back-link:hover svg { transform: translateX(-2px); }
}

/* ── Legal documents ──────────────────────────────────────────────────────
   Numbered clauses stay: a policy is cited by clause, so the sequence is
   information the reader needs, not decoration. What was missing was a way to
   see what the document contains and to jump into it. */
.doc-nav {
  margin: 0 0 2.4em;
  padding: 20px 22px;
  border: 1px solid rgba(30,91,60,.14);
  border-radius: var(--r-md);
  background: var(--green-soft);
}
.doc-nav-title {
  font-family: 'IBM Plex Mono', monospace; font-size: 11px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: rgba(20,20,15,.62);
  margin: 0 0 12px;
}
.doc-nav ul {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px clamp(16px, 3vw, 40px);
}
@media (max-width: 620px) { .doc-nav ul { grid-template-columns: 1fr; } }
.doc-nav a {
  display: block; font-size: 14.5px; line-height: 1.4; color: var(--green);
  font-weight: 600; letter-spacing: -.005em;
  font-variant-numeric: tabular-nums;
  text-decoration-thickness: 1px; text-underline-offset: 3px;
  text-decoration-color: transparent;
  transition: text-decoration-color .2s var(--ease-io);
}
.doc-nav a:hover { text-decoration-color: rgba(30,91,60,.5); }
/* the nav is sticky, so an anchored clause must clear it instead of hiding under */
.prose h2[id] { scroll-margin-top: 96px; }
.meta-line { font-family: 'IBM Plex Mono', monospace; font-size: 12px; color: rgba(20,20,15,.68); margin-bottom: 8px; }

.contact-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: start; }
@media (max-width: 800px) { .contact-grid { grid-template-columns: 1fr; } }
.contact-card { background: #fff; border-radius: var(--r-lg); border: 1px solid rgba(30,91,60,.1); box-shadow: var(--shadow-card); padding: 26px; }
.contact-card h3 { font-size: 15px; margin-bottom: 6px; }
.contact-card p { font-size: 14.5px; color: rgba(20,20,15,.65); }
.contact-card a.email { font-weight: 700; color: var(--green); font-size: 16px; }
/* stacked so each address is its own tap target rather than one run of text */
.email-list { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }

/* 404 */
.error-code { font-size: clamp(64px, 12vw, 140px); font-weight: 900; color: var(--green-soft); line-height: 1; }
