@font-face{font-family:'BeVietnam';src:url('fonts/bevietnam-500.woff2?v=4ca4b0de') format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:'BeVietnam';src:url('fonts/bevietnam-600.woff2?v=a4759a77') format('woff2');font-weight:600;font-display:swap}
@font-face{font-family:'BeVietnam';src:url('fonts/bevietnam-700.woff2?v=85718a3b') format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:'Geist';src:url('fonts/geist.woff2?v=a147f99c') format('woff2');font-weight:100 900;font-display:swap}
@font-face{font-family:'GeistMono';src:url('fonts/geist-mono.woff2?v=a15f9d56') format('woff2');font-weight:100 900;font-display:swap}

:root{
  --bg:#FFFFFF; --bg-2:#F7F7F8; --ink:#17171A; --ink-2:#26262B;
  --body:#57575E; --muted:#71717A;
  --bg-3:#ECECEF;                     /* the banded sections, one step down from --bg-2 */
  --line:#E6E6E9; --line-2:#D2D2D7; --rule:#D9D9DF;
  --on-cell:#FFFFFF; --on-cell-2:#B4B4BD;   /* text inside the one inverted bento cell */
  --dot:#E4E4E9; --dot-gap:23px;            /* the dot field behind every section */
  --accent:#2456E6;                       /* focus rings and links only */
  /* Two accents, not a spectrum. Each dark is dark enough to carry text on
     white and on its own tint, so nothing here needs a contrast exception. */
  --c-blue:#33518A;  --c-blue-t:#EDF1F8;
  --c-plum:#4A3D60;  --c-plum-t:#EFECF4;
  --col:min(1200px,calc(100vw - 28px));  /* the nav edges and the vertical rules, one width */
  --shell:min(1000px,calc(100vw - 56px));
  --r-nav:18px; --r-btn:11px;             /* rounded rectangles, not pills */
  --section:clamp(52px,6.4vw,80px);
}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:150px}
html,body{overflow-x:hidden;overflow-x:clip}
/* White, so the strip the nav floats in is not a gray band that has to be
   balanced. The nav's border and shadow carry it on their own. */
body{position:relative;margin:0;background:var(--bg);color:var(--body);
  font-family:'Geist',system-ui,sans-serif;font-size:16.5px;line-height:1.62;-webkit-font-smoothing:antialiased}
img,video,svg{display:block;max-width:100%;height:auto}
h1,h2,h3{font-family:'BeVietnam','Geist',sans-serif;color:var(--ink);margin:0;line-height:1.15;letter-spacing:-.028em;font-weight:600}
p{margin:0}
ul{margin:0;padding:0;list-style:none}
a{color:inherit}
button{font:inherit;color:inherit}
::selection{background:var(--ink);color:#fff}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:6px}

/* ---- the rule system ----
   Horizontals run the full width of the window and are section borders.
   Verticals stand on the nav's own left and right edges, share its --col
   width so the two cannot drift, and run the whole height of the page,
   crossing every horizontal. They sit in one absolutely positioned overlay
   rather than on each section, so nothing has to line up by hand. */
.frame{position:relative;width:100%;background:var(--bg);border-top:1px solid var(--rule)}
/* Above the section backgrounds, which is the only way a rule crosses a
   banded section. It sits in the gutter, so it never touches text. */
.rules{position:absolute;top:0;left:0;right:0;height:100%;z-index:3;pointer-events:none}
.rules::before,.rules::after{content:'';position:absolute;top:0;bottom:0;width:1px;background:var(--rule)}
.rules::before{left:calc(50% - var(--col) / 2)}
.rules::after{left:calc(50% + var(--col) / 2)}
/* Everything outside the vertical rules is white. The tint, the dot field and
   any texture live on one band clipped to the reading column, so the exterior
   never picks up a surface it was not given. */
section{position:relative;z-index:2;padding:var(--section) 0;
  border-bottom:1px solid var(--rule);text-align:center;background:var(--bg)}
section::before{content:'';position:absolute;top:0;bottom:0;left:50%;transform:translateX(-50%);
  width:var(--col);z-index:0;pointer-events:none;
  background-color:var(--surface,var(--bg));
  background-image:radial-gradient(var(--dot) 1px,transparent 1px);
  background-size:var(--dot-gap) var(--dot-gap);background-position:center top}
section > *{position:relative;z-index:1}
.shell{width:var(--shell);margin:0 auto}
h2{font-size:clamp(23px,3.3vw,31px);margin-bottom:12px}
.sub{max-width:58ch;margin:0 auto;color:var(--body)}

/* ---- the nav ---- */
/* The bottom margin is the gap between the nav and the first rule. It only
   shows at rest; once the nav sticks it floats over the page as before. */
/* On a phone the reading column was 334px of a 390px screen, which put body
   copy at about 36 characters a line. Comfortable is 45 to 75, and every line
   below that count turns the same words into more lines and more scrolling.
   28px of side margin buys back four characters a line. */
@media (max-width:600px){
  :root{--shell:calc(100vw - 32px)}
}

/* the nav is sticky, so an anchor jump would otherwise land underneath it */
section[id],main[id]{scroll-margin-top:96px}

.nav{position:sticky;top:16px;z-index:60;width:var(--shell);
  margin:16px auto clamp(26px,3.4vw,44px);
  height:64px;background:#fff;border:1px solid var(--line);border-radius:var(--r-nav);
  box-shadow:0 4px 20px rgba(23,23,26,.07);
  display:flex;align-items:center;justify-content:space-between;padding:0 9px 0 22px}
.brand{display:flex;align-items:center;text-decoration:none;flex:0 0 auto;
  min-height:44px;padding:9px 0}
.brand img{height:26px;width:auto}
.nav-mid{position:absolute;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:clamp(2px,.7vw,8px)}
.nav-item{position:relative}
.nav-link{display:inline-flex;align-items:center;gap:5px;text-decoration:none;font-size:.94rem;
  font-family:inherit;color:var(--body);background:none;border:0;border-radius:10px;
  padding:10px 14px;cursor:pointer;transition:background .2s ease,color .2s ease}
.nav-link:hover,.has-menu:hover > .nav-link,.nav-link[aria-expanded="true"]{background:var(--bg-2);color:var(--ink)}
.nav-link[aria-current="page"]{color:var(--ink);background:var(--bg-2)}
.chev{width:13px;height:13px;transition:transform .2s ease}
.nav-link[aria-expanded="true"] .chev{transform:rotate(180deg)}

/* The panel is held open by hover, by focus inside it, and by an explicit
   open state so a tap or the keyboard works the same way a pointer does. */
.menu{position:absolute;top:100%;left:0;margin-top:10px;width:340px;padding:8px;
  background:#fff;border:1px solid var(--line);border-radius:16px;
  box-shadow:0 14px 40px rgba(23,23,26,.13);
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .18s ease,transform .18s ease,visibility .18s}
.menu.wide{width:420px}
/* a grouped mega panel, on the Clay shape: near full width, four labelled
   column groups, each item a title over a one line description */
.menu.mega{width:min(660px,calc(100vw - 40px));left:50%;transform:translateX(-50%) translateY(-6px);
  padding:22px 18px 18px;display:grid;grid-template-columns:repeat(2,1fr);gap:0 14px}
.has-menu:hover > .menu.mega,.has-menu:focus-within > .menu.mega,.menu.mega[data-open]{transform:translateX(-50%) translateY(0)}
.menu-group{display:flex;flex-direction:column;min-width:0}
.menu-label{font-size:.72rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);padding:0 13px;margin:0 0 10px}
.menu.mega a{padding:10px 13px}
.menu.mega a span{margin-top:2px}
@media (max-width:1000px){.menu.mega{grid-template-columns:1fr;width:min(400px,calc(100vw - 40px))}}
.has-menu:hover > .menu,.has-menu:focus-within > .menu,.menu[data-open]{opacity:1;visibility:visible;transform:translateY(0)}
/* the gap between trigger and panel would otherwise drop the hover */
.has-menu::after{content:'';position:absolute;top:100%;left:0;right:0;height:12px}
.menu a{display:block;padding:11px 13px;border-radius:11px;text-decoration:none;
  transition:background .18s ease}
.menu a:hover{background:var(--bg-2)}
.menu a strong{display:block;font-family:'BeVietnam','Geist',sans-serif;font-weight:600;
  font-size:.95rem;color:var(--ink);letter-spacing:-.01em}
.menu a span{display:block;font-size:.86rem;color:var(--body);margin-top:3px;line-height:1.5}
.menu .menu-foot{border-top:1px solid var(--line);border-radius:0 0 11px 11px;margin-top:4px;
  padding-top:13px;font-size:.9rem;font-weight:500;color:var(--ink)}
/* the last panel would otherwise run off the right edge */
#menu-blog{left:auto;right:0}
.nav-cta{display:inline-flex;align-items:center;gap:9px;text-decoration:none;background:var(--ink);color:#fff;
  border-radius:var(--r-btn);padding:11px 14px 11px 20px;font-size:.94rem;font-weight:500;flex:0 0 auto;transition:background .2s}
.nav-cta:hover{background:var(--ink-2)}
.nav-cta .dot{width:17px;height:17px;border-radius:999px;background:#fff;color:var(--ink);
  display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}
.nav-cta .dot svg{width:9px;height:9px}

/* ---- mobile navigation ----
   Below 1000px .nav-mid used to be display:none with nothing put in its place,
   which left a phone with the logo and one button and no way to reach any other
   page. It now becomes a panel that the menu button opens. Submenus toggle
   through the same data-open attribute the desktop dropdowns already use, so
   this needs no second set of handlers. */
.nav-burger{display:none;flex-direction:column;align-items:center;justify-content:center;
  flex:0 0 auto;width:44px;height:44px;padding:0;margin-right:4px;background:transparent;
  border:0;border-radius:11px;cursor:pointer;-webkit-tap-highlight-color:transparent}
.nav-burger:hover{background:var(--bg-2)}
.nav-burger span{display:block;width:18px;height:2px;border-radius:2px;background:var(--ink);
  transition:transform .22s ease,opacity .16s ease}
.nav-burger span + span{margin-top:4px}
.nav-burger[aria-expanded="true"] span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.nav-burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav-burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}
.nav-cta-panel{display:none}

@media (max-width:1000px){
  .nav-burger{display:inline-flex}
  /* the bar cannot hold the wordmark and a 247px button at phone widths, so the
     call to action moves into the panel rather than overlapping the logo */
  .nav > .nav-cta{display:none}
  .nav-cta-panel{display:inline-flex;justify-content:center;margin:8px 2px 2px;padding:13px 18px}

  .nav-mid{display:none;position:absolute;top:calc(100% + 10px);left:0;right:0;
    transform:none;flex-direction:column;align-items:stretch;gap:2px;
    background:#fff;border:1px solid var(--line);border-radius:var(--r-nav);
    box-shadow:0 14px 38px rgba(23,23,26,.14);padding:10px;
    max-height:calc(100dvh - 132px);overflow-y:auto;overscroll-behavior:contain}
  .nav[data-open] .nav-mid{display:flex}

  .nav-item{display:flex;flex-direction:column;align-items:stretch}
  .nav-mid .nav-link{width:100%;justify-content:space-between;min-height:48px;
    font-size:1rem;padding:0 14px;border-radius:12px}

  /* panels become inline sections instead of floating over the page */
  .nav-mid .menu,.nav-mid .menu.mega,.nav-mid .menu.mega.has-cards{
    position:static;display:none;transform:none;opacity:1;visibility:visible;
    width:auto;min-width:0;left:auto;right:auto;margin:0;padding:2px 0 10px;
    border:0;box-shadow:none;background:transparent;grid-template-columns:1fr}
  .nav-mid .menu[data-open]{display:block}
  .nav-mid .menu.mega[data-open],.nav-mid .menu.mega.has-cards[data-open]{display:grid}
  .nav-mid .menu a{min-height:46px;padding:10px 14px;display:flex;flex-direction:column;
    justify-content:center}
  /* thumbnails are decoration the phone menu does not have room for */
  .nav-mid .menu-cards{display:none}
  .has-menu::after{display:none}
}

/* ---- buttons ---- */
.btn{display:inline-flex;align-items:center;justify-content:center;text-decoration:none;
  border:1px solid transparent;border-radius:var(--r-btn);padding:12px 24px;font-size:.98rem;font-weight:500;
  cursor:pointer;white-space:nowrap;transition:background .2s,border-color .2s,color .2s}
.btn-dark{background:var(--ink);color:#fff;border-color:var(--ink)}
.btn-dark:hover{background:var(--ink-2);border-color:var(--ink-2)}
.btn-line{background:#fff;color:var(--ink);border-color:var(--line-2)}
.btn-line:hover{border-color:var(--ink)}

/* the small link above the headline */
.eyebrow-link{display:inline-flex;align-items:center;gap:9px;margin-bottom:22px;
  padding:9px 17px;border:1px solid var(--line-2);border-radius:var(--r-btn);background:var(--bg-2);
  color:var(--ink);text-decoration:none;font-size:.92rem;font-weight:500;
  transition:background .2s,border-color .2s}
.eyebrow-link:hover{background:#fff;border-color:var(--ink)}
.eyebrow-link svg{width:15px;height:15px;transition:transform .25s ease}
.eyebrow-link:hover svg{transform:translateX(4px)}

/* the rotating word */
.rot{display:block;position:relative;height:1.32em;overflow:hidden}
.rot .rw{position:absolute;left:0;right:0;top:0;opacity:0;transform:translateY(115%);
  transition:transform .75s cubic-bezier(.24,1.25,.36,1),opacity .45s ease}
.rot .rw.past{transform:translateY(-115%)}
.rot .rw.now{opacity:1;transform:translateY(0)}
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* Motion is decoration here. Under reduce, every one of these collapses to its
   resting state and the rotation stops in the script. */
@media (prefers-reduced-motion:reduce){
  .btn,.btn-t,.btn-h,.btn-fill,.eyebrow-link svg,.rot .rw,.demo{transition:none}
  .btn:hover .btn-fill,.btn:focus-visible .btn-fill{transform:none}
  .btn:hover .btn-t,.btn:focus-visible .btn-t{transform:none}
  .btn:hover .btn-h,.btn:focus-visible .btn-h{transform:none}
  .demo{transform:none}
}

/* ---- hero ---- */
.hero{padding-top:clamp(46px,6vw,72px)}
.hero h1{font-size:clamp(33px,5.4vw,56px);font-weight:700;letter-spacing:-.038em;margin:0 auto;text-wrap:balance}
.hero .sub{margin-top:18px;font-size:1.06rem;max-width:56ch}
.cta{margin-top:26px;display:flex;flex-wrap:wrap;gap:10px;justify-content:center}
.cta.start{justify-content:flex-start}

/* ---- install: the command gets the whole width, on one line ---- */
.install{margin:30px auto 0;width:100%;border:1px solid var(--line-2);border-radius:12px;
  background:var(--bg-3);overflow:hidden;text-align:left}
.install-head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:10px 10px 10px 16px;border-bottom:1px solid var(--line-2);
  font-size:.84rem;color:var(--body)}   /* --muted only reaches 4.1 on --bg-3 */
.copy{border:1px solid var(--line-2);background:var(--bg);color:var(--ink);border-radius:8px;
  padding:6px 15px;font-size:.83rem;cursor:pointer;transition:background .2s,border-color .2s,color .2s}
.copy:hover{border-color:var(--ink)}
.copy.done{border-color:#0E7C70;color:#0E7C70}
.install-body{padding:15px 16px;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}
.install-body::-webkit-scrollbar{display:none}
.install code{font-family:'GeistMono',ui-monospace,monospace;font-size:clamp(7px,calc((100vw - 96px) / 60),13.6px);
  line-height:1.5;color:var(--ink);white-space:nowrap;display:block}
@media (max-width:700px){
  .install-body{overflow-x:visible}
  .install code{white-space:pre-wrap;overflow-wrap:anywhere;font-size:12.5px;line-height:1.65}
}
.spec{margin-top:13px;font-size:.88rem;color:var(--muted)}

/* ---- demo ---- */
/* The card starts tilted back and flattens as it rises into the viewport. The
   perspective lives on the wrapper so the card itself only carries transform. */
.demo-stage{margin-top:44px;perspective:1400px;perspective-origin:50% 0%}
.demo{border-radius:12px;overflow:hidden;border:1px solid var(--line-2);background:var(--bg-3);line-height:0;
  transform-origin:50% 0%;transform:rotateX(var(--tilt,0deg)) scale(var(--sc,1));
  box-shadow:0 var(--sh-y,0px) var(--sh-b,0px) rgba(23,23,26,.10);will-change:transform}
.demo video{width:100%;height:auto;display:block}
.caption{margin-top:12px;font-size:.87rem;color:var(--muted)}

/* ---- steps ---- */
.tint{--surface:var(--bg-2);--dot:#DEDEE4}
.steps{margin:26px auto 0;max-width:620px;text-align:left;border-top:1px solid var(--line)}
.steps li{display:grid;grid-template-columns:30px 1fr;gap:14px;align-items:baseline;
  padding:13px 0;border-bottom:1px solid var(--line)}
.steps .n{font-family:'BeVietnam',sans-serif;font-weight:600;color:var(--muted);font-size:.92rem}
.steps .t{color:var(--ink)}
/* the component name is the link, so each stage points at the section of the
   architecture document that describes it */
/* flex, not block and not inline-flex. The global reset makes every svg a
   block, so on a block parent the arrow drops to its own line; inline-flex
   fixes that but pulls the whole link up onto the end of the sentence. A
   block level flex box keeps the link on its own line with the arrow beside
   its label, and fit-content keeps the hit area on the text. */
.steps .comp{display:flex;width:fit-content;align-items:center;gap:5px;margin-top:7px;
  font-size:.86rem;font-weight:500;color:var(--c-blue);text-decoration:none}
.steps .comp svg{width:11px;height:11px;flex:0 0 auto;opacity:.65}
.steps .comp:hover{text-decoration:underline}

/* On a phone the seven stages are the longest unbroken run of text on the page.
   The first three carry the shape of the loop and the rest are one tap away.
   The collapsed state is set by script, so with scripting off all seven show. */
.steps-toggle{display:none;align-items:center;justify-content:center;gap:8px;width:100%;
  min-height:46px;margin-top:14px;padding:0 16px;background:var(--bg-2);
  border:1px solid var(--line);border-radius:12px;color:var(--ink);
  font-family:'Geist',sans-serif;font-size:.94rem;font-weight:500;cursor:pointer;
  -webkit-tap-highlight-color:transparent}
.steps-toggle:hover{background:var(--bg-3,var(--bg-2))}
.steps-toggle svg{width:15px;height:15px;flex:0 0 auto;transition:transform .22s ease}
.steps-toggle[aria-expanded="true"] svg{transform:rotate(180deg)}
@media (max-width:700px){
  .steps-toggle:not([hidden]){display:inline-flex}
  .steps[data-collapsed] > li:nth-child(n+4){display:none}
  .steps[data-collapsed] > li:nth-child(3){border-bottom:0}
}
.steps-more{display:inline-flex;align-items:center;gap:8px;margin-top:22px;
  font-size:.92rem;font-weight:500;color:var(--ink);text-decoration:none}
.steps-more svg{width:15px;height:15px;transition:transform .25s ease}
.steps-more:hover svg{transform:translateX(4px)}

/* ---- the banded section: one step of gray, not an inversion ---- */
.band{--surface:var(--bg-3);--dot:#DADAE1}
/* A small bento: two wide cells and two narrow ones on a three-column grid,
   collapsing to one column on a phone. One cell is inverted so the block has
   a focal point without needing an image. */
.bento{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;text-align:left;margin-top:30px}
.cell{border:1px solid var(--line-2);border-radius:14px;padding:24px;background:var(--bg);
  display:flex;flex-direction:column;transition:border-color .25s ease,transform .25s ease}
.cell:hover{border-color:var(--ink);transform:translateY(-2px)}
.cell.wide{grid-column:span 2}
.cell.full{grid-column:1 / -1}
.cell.dark{background:var(--ink);border-color:var(--ink)}
.cell.dark h3{color:var(--on-cell)}
.cell.dark p{color:var(--on-cell-2)}
.cell h3{font-size:1.08rem;margin-bottom:15px}
.cell.dark h3{color:var(--on-cell)}
.cell p{font-size:.95rem}
@media (max-width:820px){
  .bento{grid-template-columns:1fr 1fr}
  .cell.wide{grid-column:span 2}
.cell.full{grid-column:1 / -1}
}
@media (max-width:600px){
  .bento{grid-template-columns:1fr}
  .cell.wide{grid-column:span 1}
}

/* ---- tiers ---- */
/* The three cards share one set of row lines, so the rule above each price
   lands at the same height whatever the copy does. Subgrid is what makes that
   true rather than approximately true; without it the cards fall back to
   bottom-aligned prices, which is untidy but not broken. */
.tiers{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;text-align:left;margin-top:28px}
.tier{border:1px solid var(--line);border-radius:12px;padding:24px;background:#fff;
  display:flex;flex-direction:column}
.tier .price{margin-top:auto}
@supports (grid-template-rows:subgrid){
  .tiers{grid-template-rows:auto auto auto auto}
  .tier{display:grid;grid-row:span 4;grid-template-rows:subgrid}
  .tier .who{min-height:0}
  .tier .price{margin-top:0}
}
@media (max-width:760px){
  .tiers{grid-template-columns:1fr;grid-template-rows:none}
  .tier{display:flex;flex-direction:column;grid-row:auto}
  .tier .price{margin-top:auto}
}
.tier.mid{border-color:var(--ink);box-shadow:0 4px 18px rgba(23,23,26,.06)}
.tier h3{font-size:1.1rem;margin-bottom:6px}
.tier .who{font-size:.86rem;color:var(--accent);margin-bottom:14px;min-height:2.6em}
.tier .what{font-size:.93rem;margin-bottom:16px}
.tier .price{padding-top:14px;border-top:1px solid var(--line);font-size:.87rem;color:var(--muted)}

/* ---- honest ---- */
.honest{max-width:60ch;margin:0 auto}
.honest .sub + .sub{margin-top:14px}

/* ---- contact ---- */
form{margin:26px auto 0;max-width:520px;display:grid;gap:12px;text-align:left}
.field label{display:block;font-size:.88rem;font-weight:500;color:var(--ink);margin-bottom:6px}
.field input,.field textarea{width:100%;background:#fff;border:1px solid var(--line-2);border-radius:9px;
  padding:11px 12px;color:var(--ink);font-family:'Geist',sans-serif;font-size:.96rem;transition:border-color .2s,box-shadow .2s}
.field input::placeholder,.field textarea::placeholder{color:var(--muted);opacity:1}
.field input:focus,.field textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(36,86,230,.12)}
.field textarea{min-height:92px;resize:vertical}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media (max-width:520px){.row2{grid-template-columns:1fr}}
#submit{justify-self:stretch}
#submit[disabled]{opacity:.6;cursor:progress}
#status{min-height:1.4em;font-size:.9rem;text-align:center}
#status.ok{color:#0E7C70}
#status.err{color:#BE1550}

/* ---- footer ---- */
footer{padding:30px 0 38px;text-align:center}
.foot{display:flex;flex-wrap:wrap;gap:14px 26px;align-items:center;justify-content:center}
.foot img{height:20px;opacity:.75}
.foot p,.foot a{font-size:.85rem;color:var(--muted)}
.foot a{text-decoration:none}
.foot a:hover{color:var(--ink)}
.foot nav{display:flex;gap:20px;flex-wrap:wrap;justify-content:center}

@media (pointer:coarse){
  .btn,.copy,.nav-cta{min-height:44px}
  /* iOS zooms the whole page when a focused field is under 16px, which then
     leaves the layout scrolled sideways. This is the only reason for the size. */
  .field input,.field textarea{min-height:44px;font-size:16px}
  .foot nav a{display:inline-flex;align-items:center;justify-content:center;min-height:44px;min-width:44px;padding:0 6px}
  .comp,.steps-more,.back,.more,.cell-link{min-height:44px;display:inline-flex;align-items:center}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms !important;transition-duration:.001ms !important}
}

/* ---- blog ---- */
.posts{display:grid;gap:16px;margin-top:32px;text-align:left}
.post-card{display:grid;grid-template-columns:1fr auto;gap:8px 26px;align-items:baseline;
  border:1px solid var(--line-2);border-radius:14px;padding:22px 24px;background:var(--bg);
  text-decoration:none;transition:border-color .25s ease,transform .25s ease}
.post-card:hover{border-color:var(--ink);transform:translateY(-2px)}
.post-card h3{font-size:1.14rem;margin:0}
.post-card time{font-size:.86rem;color:var(--muted);white-space:nowrap}
.post-card p{grid-column:1 / -1;font-size:.95rem;margin-top:2px}
.post-card .more{grid-column:1 / -1;display:inline-flex;align-items:center;gap:8px;
  margin-top:12px;font-size:.9rem;font-weight:500;color:var(--ink)}
.post-card .more svg{width:15px;height:15px;transition:transform .25s ease}
.post-card:hover .more svg{transform:translateX(4px)}
@media (max-width:560px){
  .post-card{grid-template-columns:1fr}
  .post-card time{grid-row:1}
}
.empty{border:1px dashed var(--line-2);border-radius:14px;padding:34px 26px;margin-top:30px;
  background:var(--bg);color:var(--muted);font-size:.96rem}

/* an article body, the one place on the site that runs long prose */
.article{max-width:68ch;margin:0 auto;text-align:left}
.article .meta{display:flex;flex-wrap:wrap;gap:10px 16px;align-items:center;
  font-size:.88rem;color:var(--muted);margin-bottom:26px}
.badge{border:1px solid var(--line-2);border-radius:999px;padding:3px 11px;font-size:.78rem;
  font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--body);background:var(--bg-2)}
.article h2{font-size:clamp(19px,2.3vw,23px);margin:38px 0 12px}
.article p{margin-bottom:18px}
.article ul{margin:0 0 18px;padding-left:0}
.article ul li{position:relative;padding-left:22px;margin-bottom:9px}
.article ul li::before{content:'';position:absolute;left:4px;top:.62em;width:6px;height:6px;
  border-radius:6px;background:var(--line-2)}
.article .lede{font-size:1.08rem;color:var(--ink)}
.back{display:inline-flex;align-items:center;gap:9px;font-size:.92rem;font-weight:500;
  color:var(--body);text-decoration:none;margin-bottom:26px;transition:color .2s}
.back:hover{color:var(--ink)}
.back svg{width:15px;height:15px;transition:transform .25s ease}
.back:hover svg{transform:translateX(-4px)}

/* ---- a shell that widens for the comparison table ---- */
.wide-shell{width:var(--col)}

/* ---- use cases ----
   Four cards of equal height. The pill, the title and the link sit on the same
   baselines across all four, which only holds because the copy is written to
   the same length. Grid rows do the rest. */
.uses{display:grid;grid-template-columns:repeat(2,1fr);grid-auto-rows:1fr;gap:16px;text-align:left;margin-top:30px}
@media (max-width:700px){.uses{grid-template-columns:1fr}}
.use{position:relative;display:grid;grid-template-rows:auto auto 1fr auto;overflow:hidden;
  text-decoration:none;border:1px solid var(--line-2);border-radius:14px;
  padding:24px 24px 22px 26px;background:var(--bg);
  transition:border-color .25s ease,transform .25s ease,box-shadow .25s ease}
.use .use-accent{position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--c-plum)}
.use:hover{transform:translateY(-2px);border-color:var(--c-plum);box-shadow:0 8px 24px rgba(23,23,26,.07)}
.use h3{font-size:1.06rem;margin-bottom:13px}
.use p{font-size:.95rem;color:var(--body)}
.use .more{display:inline-flex;align-items:center;gap:8px;margin-top:16px;
  font-size:.9rem;font-weight:500;color:var(--ink)}
.use .more svg{width:15px;height:15px;transition:transform .25s ease}
.use:hover .more svg{transform:translateX(4px)}

/* ---- the three way comparison ----
   Column rules and centred marks, in the shape of the supplied grid, but built
   on a real table so a screen reader announces each mark with its row and
   column header. Type comes from the same scale as every card on the site. */
.cmp-wrap{margin-top:34px;overflow-x:auto;border-top:1px solid var(--line-2);background:var(--bg);
  -webkit-overflow-scrolling:touch;scroll-snap-type:x proximity}
.cmp thead th,.cmp tbody td{scroll-snap-align:end}
.cmp{width:100%;border-collapse:collapse;text-align:left;min-width:820px}
.cmp thead th{width:22%;padding:24px 20px;vertical-align:top;background:var(--bg-2);
  border-bottom:1px solid var(--line-2);border-left:1px solid var(--line)}
/* The corner is a real cell with a real label. Left empty it reads as a hole,
   and filled with tone it reads as a box; naming the axis solves both. */
.cmp thead th.cmp-blank{background:var(--bg-2);border-left:0}
.cmp thead th.cmp-blank .cmp-name{font-size:1rem;color:var(--body);min-height:0;margin-bottom:6px}
.cmp thead th.cmp-blank .cmp-note{min-height:0}
.cmp thead th.own{background:var(--bg-2)}
.cmp-name{display:block;font-family:'BeVietnam','Geist',sans-serif;font-weight:600;
  font-size:1.12rem;line-height:1.3;letter-spacing:-.018em;color:var(--ink);
  min-height:2.6em;margin-bottom:8px}
.cmp thead .own .cmp-name{color:var(--ink)}
.cmp-note{display:block;font-weight:400;font-size:.88rem;line-height:1.55;color:var(--body);
  min-height:4.8em}
.cmp-cta{display:inline-flex;margin-top:18px;padding:9px 18px;font-size:.9rem}
.cmp tbody th{padding:0 20px;height:52px;white-space:nowrap;font-weight:400;font-size:.95rem;
  color:var(--ink);width:34%;border-bottom:1px solid var(--line)}
.cmp tbody td{padding:0 20px;height:52px;text-align:center;border-bottom:1px solid var(--line);
  border-left:1px solid var(--line)}

.cmp tbody tr:last-child th,.cmp tbody tr:last-child td{border-bottom:0}
.mk-i{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px}
.mk-i svg{width:15px;height:15px}
.cmp .yes .mk-i{color:var(--c-blue)}
.cmp .no .mk-i{color:var(--line-2)}
@media (max-width:700px){
  .cmp thead th{padding:18px 14px}
  .cmp tbody th,.cmp tbody td{padding:0 14px}
}

/* Every mark is an icon, so the three verdict columns need almost no width.
   Fixing the layout fits all four columns on screen, which beats scrolling a
   sixteen row matrix sideways and losing the row label off the left edge. The
   table stops overflowing at 820px, so the treatment has to start above that. */
@media (max-width:900px){
  .cmp{min-width:0;width:100%;table-layout:fixed}
  .cmp thead th{width:18%;padding:14px 8px}
  .cmp thead th.cmp-blank{width:46%;padding-left:0}
  .cmp thead th .cmp-name{font-size:.86rem;line-height:1.25;min-height:0;hyphens:auto}
  .cmp thead th .cmp-note{font-size:.78rem;line-height:1.45;min-height:0}
  /* the buttons cannot wrap into a column this narrow, and the nav reaches the
     same pages */
  .cmp thead th .cmp-cta{display:none}
  .cmp tbody th{white-space:normal;line-height:1.3;height:auto;font-size:.9rem;
    padding:11px 10px 11px 0}
  .cmp tbody td{height:auto;min-height:52px;padding:11px 4px}
}
/* below this the verdict columns are too narrow to carry a sentence */
@media (max-width:700px){
  .cmp thead th .cmp-note{display:none}
  .cmp thead th .cmp-name{font-size:.8rem}
  .cmp thead th.cmp-blank .cmp-name{font-size:.88rem}
  .cmp tbody th{font-size:.86rem}
}
}


/* the comparison runs to the section edge, with no band beneath it */
#difference{padding-bottom:0}

/* ---- use case pages ----
   A reading column, left aligned, at the same measure as the blog article.
   The earlier rules for this were lost in an edit, which left long prose
   centred across the full shell. */
.uc-page .shell{text-align:left}
.uc-wrap{max-width:70ch;margin:0 auto;text-align:left}
.uc-page h1{font-size:clamp(30px,3.7vw,44px);font-weight:700;letter-spacing:-.03em;
  margin-bottom:18px;text-wrap:balance}
.uc-page .lede{font-size:1.06rem;color:var(--body)}
.uc-body{max-width:70ch;margin:0 auto;text-align:left}
.uc-body h2{font-size:clamp(19px,2.3vw,23px);margin:38px 0 12px}
.uc-body h2:first-child{margin-top:0}
.uc-body p{margin-bottom:18px}
.uc-body ul{margin:0 0 18px;padding:0;list-style:none}
.uc-body li{position:relative;padding-left:24px;margin-bottom:10px}
.uc-body li::before{content:'';position:absolute;left:5px;top:.62em;width:6px;height:6px;
  border-radius:6px;background:var(--c-plum)}
.uc-next{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:28px;text-align:left}
@media (max-width:700px){.uc-next{grid-template-columns:1fr}}
.next-card{position:relative;display:block;overflow:hidden;text-decoration:none;
  border:1px solid var(--line-2);border-radius:14px;padding:22px 24px 20px 26px;background:var(--bg);
  transition:border-color .25s ease,transform .25s ease,box-shadow .25s ease}
.next-card::before{content:'';position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--c-plum)}
.next-card:hover{transform:translateY(-2px);border-color:var(--c-plum);box-shadow:0 8px 24px rgba(23,23,26,.07)}
.next-card h3{font-size:1.04rem;margin-bottom:6px}
.next-card p{font-size:.93rem;color:var(--body)}
.next-card .more{display:inline-flex;align-items:center;gap:8px;margin-top:14px;
  font-size:.9rem;font-weight:500;color:var(--ink)}
.next-card .more svg{width:15px;height:15px;transition:transform .25s ease}
.next-card:hover .more svg{transform:translateX(4px)}

/* ---- figures and the flow diagram ----
   A run is a loop, and a row of four cards with a return arrow says that
   faster than three paragraphs do. Built from the same card, rule and type
   scale as the rest of the site so it does not read as an inserted graphic. */
.fig{margin:34px 0 0;padding:0}
.flow{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;position:relative}
@media (max-width:900px){.flow{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.flow{grid-template-columns:1fr}}
.step-card{position:relative;border:1px solid var(--line-2);border-radius:14px;
  padding:20px 18px;background:var(--bg);display:grid;grid-template-rows:auto auto 1fr}
.step-card.is-end{background:var(--ink);border-color:var(--ink)}
.step-card.is-end h4,.step-card.is-end p,.step-card.is-end .step-n{color:var(--on-cell)}
.step-card.is-end p{color:var(--on-cell-2)}
.step-n{font-family:'Geist',system-ui,sans-serif;font-weight:400;font-size:.82rem;
  color:var(--muted);margin-bottom:10px;letter-spacing:.04em}
.step-card h4{font-family:'BeVietnam','Geist',sans-serif;font-weight:600;font-size:1rem;
  color:var(--ink);letter-spacing:-.015em;margin:0 0 7px}
.step-card p{font-size:.9rem;line-height:1.55;color:var(--body);margin:0}
/* the arrow between steps, and the return arrow underneath */
.flow .step-card:not(:last-child)::after{content:'';position:absolute;right:-12px;top:50%;
  width:12px;height:1px;background:var(--line-2)}
@media (max-width:900px){.flow .step-card::after{display:none}}
.flow-return{position:relative;margin-top:14px;padding-top:14px;border-top:1px solid var(--line-2);
  font-size:.84rem;color:var(--muted);text-align:center}
.fig-cap{margin-top:14px;font-size:.86rem;color:var(--muted);text-align:left}
.fig-note{margin-top:16px;font-size:.95rem;color:var(--body)}

/* ---- the repeated triplet, one shape for every sub case ---- */
.tri{display:grid;gap:14px;margin-top:26px}
.tri-item{border-top:1px solid var(--line);padding-top:20px}
.tri-item h3{font-size:1.08rem;margin-bottom:12px}
.tri-item dl{display:grid;gap:8px;margin:0}
.tri-item dt{font-weight:600;color:var(--ink);font-size:.95rem;white-space:nowrap}
.tri-item dd{margin:0 0 6px;font-size:.95rem;color:var(--body)}
@media (min-width:760px){
  .tri-item dl{grid-template-columns:max-content 1fr;gap:10px 26px;align-items:start}
  .tri-item dd{margin-bottom:0}
}

/* ---- three principles, side by side ---- */
.principles{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:26px}
@media (max-width:820px){.principles{grid-template-columns:1fr}}
.principle h3{font-size:1.02rem;margin-bottom:7px}
.principle p{font-size:.94rem;color:var(--body)}

/* ---- kickers: a label above the title, larger than it and lighter than it ---- */
.cell-tag{display:block;font-family:'Geist',system-ui,sans-serif;font-weight:300;
  font-size:1.2rem;line-height:1.3;letter-spacing:-.01em;text-transform:none;
  color:var(--muted);background:none;border:0;padding:0;border-radius:0;margin-bottom:22px}
.cell.dark .cell-tag{color:var(--on-cell-2)}
.use .uc-pill{display:block;font-family:'Geist',system-ui,sans-serif;font-weight:300;
  font-size:1.2rem;line-height:1.3;letter-spacing:-.01em;text-transform:none;
  color:var(--muted);background:none;border:0;padding:0;border-radius:0;margin-bottom:22px}
.uc-kicker{display:block;font-family:'Geist',system-ui,sans-serif;font-weight:300;
  font-size:1.2rem;line-height:1.3;letter-spacing:-.01em;text-transform:none;
  color:var(--muted);background:none;border:0;padding:0;border-radius:0;margin-bottom:22px}
.sec-badge{display:block;font-family:'Geist',system-ui,sans-serif;font-weight:300;
  font-size:1.2rem;line-height:1.3;letter-spacing:-.01em;text-transform:none;
  color:var(--muted);background:none;border:0;padding:0;border-radius:0;margin-bottom:22px}

/* ---- textured surfaces ----
   The scrim is a real layer, not an opacity on the image, so the contrast
   underneath the text is fixed rather than dependent on what the photograph
   happens to be doing in that spot. */
.band .cell{background:rgba(255,255,255,.72);backdrop-filter:blur(3px)}
.band .cell.dark{background:var(--ink);border-color:var(--ink);backdrop-filter:none}


/* article images, with a caption that carries the point */
.figimg{margin:30px 0;padding:0}
.figimg img{width:100%;height:auto;max-height:380px;object-fit:cover;
  border-radius:14px;display:block;border:1px solid var(--line-2)}
.figimg figcaption{margin-top:11px;font-size:.86rem;color:var(--muted)}

/* ---- the blog panel gets image cards, like a highlights column ---- */
.menu.mega.has-cards{width:min(820px,calc(100vw - 40px));grid-template-columns:1fr 1.2fr}
@media (max-width:1000px){.menu.mega.has-cards{grid-template-columns:1fr;width:min(400px,calc(100vw - 40px))}
  .menu-cards{grid-template-columns:1fr 1fr}}
.menu-cards{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:0 6px}
.menu-card{display:block;text-decoration:none;border-radius:11px;overflow:hidden;
  border:1px solid var(--line);background:var(--bg);transition:border-color .2s ease,transform .2s ease}
.menu-card:hover{border-color:var(--ink);transform:translateY(-2px)}
.menu-card .thumb{height:88px;overflow:hidden;background:var(--bg-2)}
.menu-card .thumb img{width:100%;height:100%;object-fit:cover;display:block}
.menu-card .meta{padding:10px 11px 12px}
.menu-card strong{display:block;font-family:'BeVietnam','Geist',sans-serif;font-weight:600;
  font-size:.86rem;line-height:1.35;color:var(--ink)}
.menu-card span{display:block;font-size:.78rem;color:var(--muted);margin-top:4px}

/* ---- blog index cards carry a thumbnail ---- */
.post-card{grid-template-columns:120px 1fr auto;align-items:start;gap:10px 22px}
.post-card .pthumb{grid-row:1 / span 4;width:120px;height:84px;border-radius:10px;overflow:hidden;
  background:var(--bg-2);border:1px solid var(--line)}
.post-card .pthumb img{width:100%;height:100%;object-fit:cover;display:block}
@media (max-width:560px){
  .post-card{grid-template-columns:1fr}
  .post-card .pthumb{grid-row:auto;width:100%;height:120px}
}

/* the last panel would run off the right edge if it centred on its trigger */
#menu-blog{left:auto;right:0;transform:translateY(-6px)}
.has-menu:hover > #menu-blog,.has-menu:focus-within > #menu-blog,#menu-blog[data-open]{transform:translateY(0)}



/* ---- the evidence scale ----
   An ordered scale drawn as one, so the point that evidence is graded rather
   than binary is made by the shape before the caption explains it. */
.scale{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;margin-top:8px}
@media (max-width:640px){.scale{grid-template-columns:1fr}}
.scale-step{border:1px solid var(--line-2);border-radius:10px;padding:14px 14px 16px;background:var(--bg)}
.scale-step .bar{height:5px;border-radius:5px;background:var(--line-2);margin-bottom:12px}
.scale-step.l1 .bar{background:linear-gradient(90deg,var(--c-blue) 8%,var(--line-2) 8%)}
.scale-step.l2 .bar{background:linear-gradient(90deg,var(--c-blue) 32%,var(--line-2) 32%)}
.scale-step.l3 .bar{background:linear-gradient(90deg,var(--c-blue) 56%,var(--line-2) 56%)}
.scale-step.l4 .bar{background:linear-gradient(90deg,var(--c-blue) 78%,var(--line-2) 78%)}
.scale-step.l5 .bar{background:var(--c-blue)}
.scale-step h4{font-family:'BeVietnam','Geist',sans-serif;font-weight:600;font-size:.95rem;
  color:var(--ink);margin:0 0 6px;letter-spacing:-.012em}
.scale-step p{font-size:.86rem;line-height:1.5;color:var(--body);margin:0}
.scale-note{margin-top:14px;padding-top:14px;border-top:1px solid var(--line-2);
  font-size:.86rem;color:var(--muted)}

/* ---- textured sections ----
   The image is a ground for text, never a block of its own. A scrim layer sets
   the contrast so the copy does not depend on what the photograph happens to
   be doing behind any given line. */
/* A ground paints its texture on the same band, so image, tint and dots all
   stop at the vertical rules together. */
.ground::before{background-size:cover;background-position:center;background-repeat:no-repeat}
.ground-lime::before{background-image:linear-gradient(rgba(252,252,253,.90),rgba(250,250,251,.94)),url('tex-lime.jpg')}
.ground-paper::before{background-image:linear-gradient(105deg,rgba(253,253,254,.93),rgba(250,250,251,.88)),url('tex-paper.jpg')}
.ground-alu::before{background-image:linear-gradient(105deg,rgba(253,253,254,.92),rgba(250,250,251,.86)),url('tex-alu.jpg')}
