:root{
  --bg:#ffffff;--bg-2:#f5f5f7;--ink:#1d1d1f;--muted:#6e6e73;--line:#dcdce1;
  /* Between --muted and --ink: for text that is subdued but must stay comfortably readable,
     such as the label on a waiting button. 8.1:1 on --bg-2, where --muted is 4.66:1. */
  --ink-2:#4a4a4f;--line-2:#a8a8b0;
  --accent:#0b6b4b;--accent-ink:#094f38;--live:#0b8a5b;--build:#e08a00;--queued:#b6b6bd;
  --maxw:1080px;--pad:clamp(20px,5vw,40px);
  --sans:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --t-display:clamp(31px,5.2vw,56px);--t-h2:clamp(25px,3.4vw,34px);
  --t-sub:20px;--t-body:17px;--t-small:14px;--t-micro:12px;
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth;overflow-x:clip;scroll-padding-top:64px}
body{background:var(--bg);color:var(--ink);font-family:var(--sans);font-size:var(--t-body);line-height:1.55;-webkit-font-smoothing:antialiased;overflow-x:clip}
a{color:inherit;text-decoration:none}
h1,h2,h3{font-weight:600;letter-spacing:-.02em;line-height:1.1}
img{display:block;max-width:100%}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 var(--pad)}
.skip{position:absolute;left:-999px}.skip:focus{left:16px;top:12px;background:var(--ink);color:#fff;padding:8px 14px;border-radius:8px;z-index:100}
nav{position:sticky;top:0;z-index:50;background:rgba(255,255,255,.82);backdrop-filter:saturate(1.4) blur(18px);border-bottom:1px solid var(--line)}
.nav-in{display:flex;align-items:center;justify-content:space-between;height:56px}
.logo{display:inline-flex;align-items:flex-end;gap:5px;font-weight:600;font-size:var(--t-sub);letter-spacing:-.015em;color:var(--ink)}
.logo .wm{line-height:1}
.logo .cur{width:.60em;height:.18em;margin-bottom:.14em;background:var(--accent);border-radius:1px}
.nav-links{display:flex;gap:26px}
.nav-links a{font-size:var(--t-small);color:var(--muted);transition:color .2s}.nav-links a:hover{color:var(--ink)}
.btn{display:inline-block;background:var(--accent);color:#fff;font-size:var(--t-small);font-weight:600;padding:10px 18px;border-radius:980px;border:0;cursor:pointer;font-family:var(--sans);transition:background .2s}
.btn:hover{background:var(--accent-ink)}
.btn.big{font-size:var(--t-body);padding:15px 30px}
.btn.ghost{background:transparent;color:var(--accent);border:1px solid var(--line)}.btn.ghost:hover{background:var(--bg-2)}
.nav-toggle{display:none;background:none;border:0;font-size:22px;line-height:1;cursor:pointer;color:var(--ink);padding:4px 6px;font-family:var(--sans)}
@media(max-width:760px){
  .nav-toggle{display:block}
  /* Opaque, not .98: the two percent left the page showing through as a ghost behind the
     menu items. The blur is gone with it — this panel sits inside nav, which already has a
     backdrop-filter of its own, so the nested one had nothing left to sample and only cost
     paint work. A menu you can see the page through is a menu that reads as half-open. */
  .nav-links{display:none;position:absolute;top:56px;left:0;right:0;flex-direction:column;background:#fff;border-bottom:1px solid var(--line);padding:6px 0;box-shadow:0 10px 24px -14px rgba(0,0,0,.3)}
  nav.open .nav-links{display:flex}
  .nav-links a{padding:13px var(--pad);font-size:var(--t-body);color:var(--ink)}
}
.hero{text-align:center;padding:clamp(44px,7vw,80px) 0 clamp(36px,6vw,60px)}
.hero h1{font-size:var(--t-display);max-width:18ch;margin:0 auto;letter-spacing:-.025em;line-height:1.07}
.hero p{font-size:var(--t-sub);color:var(--muted);max-width:42ch;margin:22px auto 0;line-height:1.45}
.hero-cta{display:flex;gap:14px;justify-content:center;align-items:center;flex-wrap:wrap;margin-top:30px}
.hero-proof{margin-top:22px;font-size:var(--t-small);color:var(--muted)}.hero-proof b{color:var(--accent);font-weight:600}
/* The offer is the one thing on this screen a visitor can act on, so it reads as something
   clickable rather than as grey small print. Underline on hover only, to keep the line calm. */
/* The offer gets its own line. Run inline after the proof with a separator, it left a
   stranded '·' at the end of a wrapped line on every width that mattered. */
.hero-offer{display:block;margin-top:6px}
.hero-proof a{color:var(--ink);font-weight:600;text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px;text-decoration-color:color-mix(in srgb,var(--accent) 45%,transparent)}
.hero-proof a:hover{text-decoration-color:var(--accent)}
.hero-audience{font-size:var(--t-sub);color:var(--ink);max-width:44ch;margin:16px auto 0;line-height:1.4;font-weight:500}
.youif-h{font-size:var(--t-sub);font-weight:600;color:var(--ink)}
.youif-who{max-width:600px;margin:18px 0 0;font-size:var(--t-small);color:var(--muted);line-height:1.5}
.youif-list{list-style:none;max-width:600px;margin:20px 0 0;display:grid;gap:12px;text-align:left}
.youif-list a{color:var(--ink);text-decoration:none;transition:color .15s}
.youif-list a:hover{color:var(--accent);text-decoration:underline}
.youif-list li{position:relative;padding-left:24px;color:var(--muted);font-size:var(--t-body);line-height:1.5}
.youif-list li::before{content:"";position:absolute;left:5px;top:.55em;width:7px;height:7px;border-radius:50%;background:var(--accent)}
.youif-cta{display:inline-block;margin-top:24px;color:var(--accent);font-weight:600;font-size:var(--t-small)}
section{padding:clamp(52px,8vw,88px) 0}
.divide{border-top:1px solid var(--line)}
.h2{font-size:var(--t-h2);text-wrap:balance}
.lead{font-size:var(--t-sub);color:var(--muted);margin-top:14px;max-width:60ch;line-height:1.45;font-weight:400;letter-spacing:normal}
.sec-top{margin-bottom:clamp(22px,4vw,34px)}
.counter{display:flex;gap:48px;flex-wrap:wrap;margin-top:24px}
.counter .num{font-size:52px;font-weight:600;letter-spacing:-.03em;color:var(--accent);line-height:1}
.counter .cap{font-size:var(--t-small);color:var(--muted);margin-top:6px;font-weight:500}
.counter-note{margin-top:16px;font-size:var(--t-small);color:var(--muted);max-width:60ch}
.bizq{margin:24px 0 0;font-size:var(--t-small);font-weight:600;color:var(--ink)}
.filters{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0 8px}
@media(max-width:560px){.filters{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:6px}.filters .chip{flex:0 0 auto}}
.chip{font-size:var(--t-small);font-weight:500;border:1px solid var(--line);border-radius:980px;padding:8px 15px;color:var(--muted);cursor:pointer;background:none;font-family:var(--sans);transition:.2s}
.chip:hover{color:var(--ink);border-color:var(--ink)}.chip.on{background:var(--ink);color:#fff;border-color:var(--ink)}
.group{margin-top:26px}
.group-h{display:flex;align-items:center;gap:9px;font-size:var(--t-small);font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-bottom:14px}
.board{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
@media(max-width:820px){.board{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:560px){.board{grid-template-columns:minmax(0,1fr)}}
.tile{border:1px solid var(--line);border-radius:16px;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.04);padding:20px;cursor:pointer;transition:.2s;display:flex;flex-direction:column}
.tile:hover{border-color:#b9b9c0;box-shadow:0 6px 20px -12px rgba(0,0,0,.25)}
.tile.open{grid-column:1/-1;cursor:default;border-color:var(--accent)}
.tile h3{font-size:var(--t-sub);margin-bottom:7px}
.tile .hook{font-size:var(--t-small);color:var(--muted);line-height:1.5}
.tile .open-hint{margin-top:auto;padding-top:12px;font-size:var(--t-small);font-weight:600;color:var(--accent)}
.tile .detail{display:none}
.tile.open .detail{display:block;margin-top:16px;padding-top:16px;border-top:1px solid var(--line)}
.tile.open .hook{display:none}.tile.open .open-hint{display:none}
.row{display:flex;gap:12px;margin-bottom:11px;font-size:var(--t-body);line-height:1.45}
.row .k{flex:0 0 118px;font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);padding-top:3px}
.row.sol .k,.row.ai .k{color:var(--accent)}
.aichip{display:inline-block;background:var(--accent);color:#fff;font-size:10px;font-weight:700;padding:2px 7px;border-radius:5px;margin-right:7px;vertical-align:1px;letter-spacing:.03em}
.autochip{display:inline-block;background:#ececed;color:var(--muted);font-size:10px;font-weight:700;padding:2px 7px;border-radius:5px;margin-right:7px;vertical-align:1px;letter-spacing:.03em}
.row .res{color:var(--ink);font-weight:500}
.tile.open .close{margin-top:2px;font-size:var(--t-small);font-weight:600;color:var(--accent);background:none;border:0;cursor:pointer;font-family:var(--sans);padding:4px 0}
.quote{margin-top:30px;background:var(--bg-2);border-radius:18px;padding:clamp(24px,3.5vw,34px)}
.quote p{font-size:var(--t-sub);line-height:1.5;letter-spacing:-.01em}
.quote .by{margin-top:14px;font-size:var(--t-small);color:var(--muted);font-weight:500}
.cta-band{margin-top:30px;display:flex;align-items:center;gap:18px;flex-wrap:wrap;justify-content:center;text-align:center;background:var(--accent);border-radius:18px;padding:26px}
.cta-band p{font-size:var(--t-sub);font-weight:500;color:#fff}
.cta-band .btn{background:#fff;color:var(--accent)}.cta-band .btn:hover{background:#eafff6}
.steps{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;margin-top:8px;align-items:start}
@media(max-width:720px){.steps{grid-template-columns:minmax(0,1fr)}}
.step{background:var(--bg-2);border-radius:16px;padding:26px}
.step .n{font-size:var(--t-small);color:var(--muted);font-weight:600}
.step h3{font-size:var(--t-sub);margin:10px 0 4px}
.step .price{font-size:var(--t-small);color:var(--accent);font-weight:600;margin-bottom:12px}
.step p{color:var(--muted);font-size:var(--t-small);line-height:1.5}
.start-note{margin-top:8px;color:var(--muted);font-size:var(--t-small)}
/* Price bands and the guarantee, added 08/08 with the first figures ever shown on this site.
   Same card language as .step so the section reads as one thing, not a bolted-on price list. */
.bands,.guarantee{margin-top:44px}
.bands-h{font-size:var(--t-sub);margin-bottom:6px}
.bands-lead{color:var(--muted);font-size:var(--t-small);line-height:1.5;margin-bottom:18px}
.band-grid,.g-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;align-items:start}
@media(max-width:860px){.band-grid,.g-grid{grid-template-columns:minmax(0,1fr)}}
.band{background:var(--bg-2);border-radius:16px;padding:24px}
.band h4{font-size:var(--t-small);font-weight:700;margin-bottom:10px;line-height:1.3}
.band-price{font-size:var(--t-sub);color:var(--accent);font-weight:700;letter-spacing:-.01em}
.band-time{font-size:var(--t-micro);color:var(--muted);margin:6px 0 12px;font-weight:600}
.band p{color:var(--muted);font-size:var(--t-small);line-height:1.5}
.bands-note{margin-top:14px;color:var(--muted);font-size:var(--t-small);line-height:1.5}
.g-item{border:1px solid var(--line);border-radius:16px;padding:24px;background:#fff}
.g-item h4{font-size:var(--t-small);font-weight:700;margin-bottom:8px;line-height:1.3;color:var(--accent)}
.g-item p{color:var(--muted);font-size:var(--t-small);line-height:1.5}
/* Who is actually bound by the guarantee. Sits directly under the three cards, in normal ink
   rather than grey, because it is a fact about the party and not a footnote. */
.g-by{color:var(--ink-2)!important;margin-top:16px}
/* The deadline and the entry price, on the first screen. It is a link because the promise is
   worthless if the visitor cannot immediately see what sits behind it. */
.hero-promise{margin-top:14px;font-size:var(--t-small);line-height:1.6;color:var(--ink-2)}
.hero-promise b{color:var(--ink)}
.hero-promise a{color:var(--accent);font-weight:600;white-space:nowrap}
.journal-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px;margin-top:6px}
@media(max-width:720px){.journal-grid{grid-template-columns:minmax(0,1fr)}}
.jitem{border:1px solid var(--line);border-radius:16px;padding:22px;background:#fff}
.jitem .k{font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-bottom:10px}
.jitem h3{font-size:var(--t-sub);margin-bottom:8px;line-height:1.25}
.jitem p{font-size:var(--t-small);color:var(--muted);line-height:1.5}
.jitem .soon{display:inline-block;margin-top:12px;font-size:var(--t-micro);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--accent)}
.journal-note{margin-top:22px;font-size:var(--t-small);color:var(--muted);max-width:62ch}
.faq .qa{border-bottom:1px solid var(--line)}
.faq .qa button{width:100%;background:none;border:0;color:var(--ink);cursor:pointer;text-align:left;display:flex;justify-content:space-between;align-items:center;gap:20px;padding:22px 0;font-family:var(--sans);font-size:var(--t-sub);font-weight:600;letter-spacing:-.01em}
.faq .pm{color:var(--accent);font-size:var(--t-sub);transition:transform .3s;flex-shrink:0}
.faq .qa.open .pm{transform:rotate(45deg)}
.faq .ans{max-height:0;overflow:hidden;transition:max-height .4s ease}
.faq .ans p{color:var(--muted);font-size:var(--t-small);line-height:1.6;max-width:64ch;padding-bottom:22px}
.about{display:grid;grid-template-columns:.8fr 1.2fr;gap:clamp(24px,4vw,52px);align-items:center}
@media(max-width:720px){.about{grid-template-columns:1fr}}
.about .portrait{border-radius:16px;overflow:hidden;background:var(--bg-2);aspect-ratio:4/5}
.about .portrait img{width:100%;height:100%;object-fit:cover}
.about h2{margin-bottom:18px}
.about p{color:var(--muted);font-size:var(--t-body);line-height:1.6;margin-bottom:14px}.about p b{color:var(--ink);font-weight:600}
.contact{text-align:center}
.contact .h2{max-width:20ch;margin:0 auto}.contact .lead{margin:14px auto 0}
.channels{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-top:26px}
.channels a{font-size:var(--t-body);font-weight:500;padding:13px 26px;border-radius:980px;border:1px solid var(--line);transition:.2s}
.channels a.primary{background:var(--accent);color:#fff;border-color:var(--accent)}
.channels a:hover{border-color:var(--ink)}.channels a.primary:hover{background:var(--accent-ink);border-color:var(--accent-ink)}
.contact-note{margin-top:20px;font-size:var(--t-small);color:var(--muted)}
.socials{display:flex;gap:14px;align-items:center}
.soc{display:inline-flex;transition:opacity .2s}
.soc svg{display:block}
.soc:not(.stub){color:var(--muted)}
.soc.stub{color:var(--queued);cursor:default;opacity:.5}
.soc:not(.stub):hover{opacity:.75}
footer{border-top:1px solid var(--line);padding:32px 0 96px;color:var(--muted);font-size:var(--t-small)}
.foot-in{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap}
.sticky{position:fixed;right:18px;bottom:18px;z-index:60;opacity:0;transform:translateY(12px);pointer-events:none;transition:.35s}
.sticky.show{opacity:1;transform:none;pointer-events:auto}
.sticky a{display:inline-flex;align-items:center;gap:8px;background:var(--accent);color:#fff;font-weight:600;font-size:var(--t-small);padding:13px 22px;border-radius:980px;box-shadow:0 10px 30px -8px rgba(11,107,75,.55)}
.sticky a:hover{background:var(--accent-ink)}
/* On a phone the call-to-action becomes a full-width bar, and the scroll-to-top button shares
   its row instead of floating above it. Moving the button to the right edge was not enough:
   the text column runs the full width here, so a button anywhere over it covers words. In one
   row at the very bottom, the only thing behind them is the strip a sticky bar always costs,
   and the reader can scroll it clear. The bar gives up 62px so the button has a place to be. */
@media(max-width:560px){.sticky{left:14px;right:76px}.sticky a{width:100%;justify-content:center}
/* The sticky bar sits wider and taller on a phone, so the footer needs more room there. */
footer{padding-bottom:120px}}
.totop{position:fixed;left:20px;bottom:20px;z-index:60;width:48px;height:48px;border-radius:50%;border:0;background:var(--accent);color:#fff;font-size:22px;line-height:1;cursor:pointer;opacity:0;transform:translateY(10px);pointer-events:none;transition:.3s;box-shadow:0 10px 26px -6px rgba(11,107,75,.55)}
.totop.show{opacity:1;transform:none;pointer-events:auto}
.totop:hover{background:var(--accent-ink)}
/* This button was pinned 20px from the LEFT: empty margin on a desktop, and on a 390px screen
   a solid green circle over the start of every line of text. Moving it to the right edge only
   moved the problem — the column runs full width, so it still landed on words. It now sits in
   the same row as the call-to-action bar, at the bottom edge, over nothing the bar was not
   already covering. Same size as the bar so the row reads as one thing. */
@media(max-width:560px){.totop{bottom:18px;left:auto;right:14px;width:50px;height:50px}}
a:focus-visible,button:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px}

/* blog */
.post{max-width:720px;padding-top:clamp(40px,7vw,72px);padding-bottom:40px}
.post .kicker{font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--accent);margin-bottom:12px}
.post h1{font-size:clamp(28px,4.4vw,44px);letter-spacing:-.02em;line-height:1.12;margin-bottom:12px;font-weight:600}
.post .meta{font-size:var(--t-small);color:var(--muted);margin-bottom:30px}
.post p{font-size:var(--t-body);line-height:1.65;margin-bottom:18px;color:#2b2a28}
.post h2{font-size:var(--t-h2);margin:34px 0 12px}
.post h3{font-size:var(--t-sub);margin:26px 0 10px}
.post ul{margin:0 0 18px 22px}.post li{margin-bottom:8px;line-height:1.6}
.post strong{font-weight:600;color:var(--ink)}
.post a{color:var(--accent);text-decoration:underline}
/* One comparison table per article: the shape an AI search engine can lift whole, and the shape a
   reader skims instead of reading four paragraphs.
   A table is the one thing in an article that cannot be made to reflow — four columns of prose
   will not fit 390px however they are styled. So on a narrow screen the TABLE becomes its own
   scroll box: the page never scrolls sideways, which is the defect already found and fixed once on
   the phone, and the reader drags the table instead. Written on the element rather than on a
   wrapper so the factory's next article gets it without knowing about it. */
.post table{border-collapse:collapse;width:100%;font-size:var(--t-small);line-height:1.5;margin:0 0 22px}
.post thead th{text-align:left;font-weight:600;color:var(--ink);border-bottom:2px solid var(--line-2);padding:10px 14px 8px}
.post tbody td{border-bottom:1px solid var(--line);padding:11px 14px;vertical-align:top;color:#2b2a28}
.post tbody tr:last-child td{border-bottom:0}
.post tbody td:first-child{font-weight:600;color:var(--ink)}
@media (max-width:700px){
  /* Looked at on a real 390px screen 06/08: the table does scroll, and nothing says so. The last
     column is sliced mid-word at the edge and reads as a broken page rather than as more content.
     A written "swipe" hint is wrong here — four of the twelve article tables fit 390px exactly and the
     hint would be a lie on them, and CSS cannot tell the two cases apart. A shadow can: the two
     `local` gradients travel with the content and mask the shadow at whichever end is fully
     reached, so a table that fits shows nothing and a table with more to the right shows an edge.
     Strong on purpose — the first attempt at 12% was invisible on white when it was looked at.
     No wrapper, no script: the factory's next article inherits it. */
  .post table{
    display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;width:auto;
    background:
      linear-gradient(to right,var(--bg) 60%,rgba(255,255,255,0)) left center,
      linear-gradient(to left,var(--bg) 60%,rgba(255,255,255,0)) right center,
      linear-gradient(to right,rgba(0,0,0,.20),rgba(0,0,0,0)) left center,
      linear-gradient(to left,rgba(0,0,0,.20),rgba(0,0,0,0)) right center;
    background-repeat:no-repeat;
    background-size:28px 100%,28px 100%,22px 100%,22px 100%;
    background-attachment:local,local,scroll,scroll;
  }
  .post thead th,.post tbody td{white-space:normal;min-width:9.5em}
}
.post .cta{margin-top:38px;background:var(--bg-2);border-radius:16px;padding:26px}
.post .cta p{margin-bottom:0}
.post .cta a{color:#fff;background:var(--accent);display:inline-block;padding:12px 22px;border-radius:980px;text-decoration:none;font-weight:600;font-size:var(--t-small);margin-top:12px}
.post .cta a:hover{background:var(--accent-ink)}
.bloghead{max-width:760px;padding-top:clamp(40px,7vw,72px)}
.blog-list{max-width:760px;margin-top:8px}
.blog-list .bi{display:block;padding:22px 0;border-top:1px solid var(--line);transition:.2s}
.blog-list .bi:hover{padding-left:6px}
.blog-list .bi .k{font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.blog-list .bi h2{font-size:var(--t-sub);margin:6px 0 6px;font-weight:600}
.blog-list .bi p{font-size:var(--t-small);color:var(--muted);line-height:1.5}

/* contact form */
.contact-form{max-width:460px;margin:26px auto 0;display:flex;flex-direction:column;gap:10px;text-align:left}
.contact-form input,.contact-form textarea,.contact-form select{font-family:var(--sans);font-size:var(--t-body);padding:13px 15px;border:1px solid var(--line);border-radius:12px;background:#fff;color:var(--ink);width:100%}
.contact-form input:focus,.contact-form textarea:focus,.contact-form select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(11,107,75,.12)}
/* Safari renders a native select at a different height from a text input unless the appearance
   is reset, which left the budget field visibly shorter than the two fields above it. */
.contact-form select{appearance:none;-webkit-appearance:none;line-height:1.3;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%236e6e73' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 15px center;padding-right:38px}
/* The select is optional, so :invalid never fires and its placeholder rendered in full-strength
   ink while the three fields around it showed grey placeholder text — it read as already
   answered. :has is the only way to tell "nothing chosen yet" without script; where it is
   unsupported the field simply looks as it did before, which is not a break. */
.contact-form select:has(option[value=""]:checked){color:var(--muted)}
.contact-form select option{color:var(--ink)}
.contact-form textarea{resize:vertical;min-height:100px}
.contact-form .btn{margin-top:4px;cursor:pointer}
/* Consent line under both forms. The width:100% / padding rules above are written for text
   fields, so the checkbox is sized explicitly or it renders as a huge empty box. */
.form-consent{display:flex;align-items:flex-start;gap:9px;font-size:var(--t-small);color:var(--muted);line-height:1.45;text-align:left;cursor:pointer}
.form-consent input[type=checkbox]{flex:none;width:16px;height:16px;min-width:16px;margin:2px 0 0;padding:0;border-radius:4px;accent-color:var(--accent)}
.form-consent a{color:var(--accent);text-decoration:underline}
/* What went wrong, said next to the form instead of on a page the visitor is thrown to with
   an empty form behind it. The marked field keeps its own red edge after the message is read. */
.form-error{margin:2px 0 0;padding:11px 14px;border-radius:12px;background:#fdeeee;border:1px solid #e6b4b4;color:#8c2f2f;font-size:var(--t-small);line-height:1.5;text-align:left}
.form-error[hidden]{display:none}
.contact-form input.bad,.contact-form textarea.bad{border-color:#c94a4a;background:#fffafa}
.form-consent.bad{color:#8c2f2f}
.form-consent.bad input[type=checkbox]{outline:2px solid #c94a4a;outline-offset:2px}
.cf-turnstile{margin:2px 0}
/* Language offer under the nav — one line, never a redirect. Hidden unless the visitor's
   browser asks for the other language and they have not picked one themselves. */
.langbar{background:var(--bg-2);border-bottom:1px solid var(--line)}
.langbar[hidden]{display:none}
.langbar .wrap{padding:9px var(--pad);font-size:var(--t-small);display:flex;align-items:center;justify-content:space-between;gap:12px}
.langbar a{color:var(--accent)}
/* 24x24 minimum: a tap target smaller than this is a miss on a phone (WCAG 2.5.8). */
.langbar-x{background:none;border:0;min-width:24px;min-height:24px;padding:0 4px;font-size:16px;line-height:1;color:var(--muted);cursor:pointer}
.langbar-x:hover{color:var(--ink)}
/* A button that has to look like the links beside it — it changes state, so it must be a
   button for a keyboard and a screen reader, not a link that goes nowhere. */
.linklike{background:none;border:0;padding:0;font:inherit;color:inherit;cursor:pointer;text-decoration:underline}
.linklike:hover{color:var(--accent)}
.hp{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden;opacity:0;pointer-events:none}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.or-line{margin-top:22px;font-size:var(--t-small);color:var(--muted)}
/* thank-you page */
.thanks{max-width:640px;text-align:center;padding:76px 20px 104px}
.thanks h1{margin-bottom:14px}
.thanks p{color:var(--muted);font-size:var(--t-body);line-height:1.55}
.thanks-actions{margin-top:30px;display:flex;gap:12px;justify-content:center;flex-wrap:wrap}

/* cookie consent */
.consent{position:fixed;left:16px;right:16px;bottom:16px;z-index:70;max-width:540px;margin:0 auto;background:#fff;border:1px solid var(--line);border-radius:14px;box-shadow:0 14px 44px -14px rgba(0,0,0,.32);padding:16px 18px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;justify-content:space-between}
.consent[hidden]{display:none}
.consent p{font-size:var(--t-small);color:var(--muted);flex:1 1 240px;line-height:1.45}
.consent p a{color:var(--accent);text-decoration:underline}
.consent-btns{display:flex;gap:8px;flex-shrink:0}
.consent .btn{padding:9px 16px;font-size:var(--t-small)}
/* The consent panel is the first thing every visitor touches, and on a phone it was the
   smallest thing on the page: 37px-tall buttons and a 17px-tall "Details" link. Apple and
   Google both put the floor at 44px. The link grows by padding with a matching negative
   margin, so the tap area gets bigger without the sentence around it moving. Found by
   measuring the live site on an iPhone viewport on 04/08, not by looking at the CSS. */
.consent p a{display:inline-block;padding:12px 6px;margin:-12px -6px}
@media(max-width:540px){.consent{flex-direction:column;align-items:stretch;gap:12px}.consent p{flex:0 0 auto}.consent-btns{justify-content:stretch}.consent-btns .btn{flex:1 1 0;min-height:48px;display:inline-flex;align-items:center;justify-content:center}}
/* The panel is fixed to the bottom of the screen, so it lands on top of whatever the page ends
   with. Measured on a 390px viewport on 06/08: the panel spans 693–828 and the footer's legal
   row spans 704–726, so "Legal notice · Privacy · Cookies · hello@avakyan.ai" was invisible on
   every page to every visitor who had not yet answered it — and answering it is exactly when a
   person might want to read the privacy page. Desktop cleared it by five pixels, which is luck
   rather than a margin. Same family as the sticky bar that hid the same row on 04/08, which is
   why the footer already reserves room for that one. The class is set by the script that shows
   the panel, so the space is handed back the moment a visitor chooses. */
body.consent-up footer{padding-bottom:132px}
@media(max-width:560px){body.consent-up footer{padding-bottom:210px}}

/* legal pages */
.legal{max-width:720px}
.legal h2{font-size:var(--t-sub);margin:28px 0 8px}
.legal ul{margin:0 0 8px 20px}.legal li{margin-bottom:6px;line-height:1.6;color:#2b2a28}
.legal p{color:#2b2a28;line-height:1.65;margin-bottom:6px}
.legal a{color:var(--accent);text-decoration:underline}
.legal .legal-foot{margin-top:26px;font-size:var(--t-small);color:var(--muted)}

/* nav language switch */
.nav-right{display:flex;align-items:center;gap:16px}
.lang{display:flex;gap:8px}
.lang a{font-size:13px;color:var(--muted);font-weight:600}
.lang a.on{color:var(--ink)}
.lang a:hover{color:var(--accent)}

/* case pages */
.post.case .kicker{margin-bottom:14px}
.post.case .kicker a{color:var(--muted);text-decoration:none;font-weight:600;font-size:var(--t-small)}
.post.case .kicker a:hover{color:var(--accent)}
.post.case .meta{text-transform:uppercase;letter-spacing:.05em;font-size:var(--t-micro);font-weight:700;color:var(--accent)}
.post .case-lede{font-size:var(--t-sub);line-height:1.5;color:var(--ink);font-weight:500;margin:0 0 26px}
.post ul.how,.post ul.fits{list-style:none;margin:0 0 20px}
.post ul.how li,.post ul.fits li{position:relative;padding-left:26px;margin-bottom:10px;line-height:1.6;color:#2b2a28}
.post ul.how li::before{content:"→";position:absolute;left:0;top:0;color:var(--accent);font-weight:700}
.post ul.fits li::before{content:"✓";position:absolute;left:0;top:0;color:var(--accent);font-weight:700}
/* A tick means "yes, this". Under a heading like "What it must never do" it means the opposite of
   the sentence next to it, and on a phone people read the icon before the words. Same list, same
   spacing, different mark. Muted rather than red: these are boundaries, not errors. */
.post ul.fits.stop li::before{content:"×";color:var(--muted)}
.post .case-honest{font-size:var(--t-small);color:var(--muted);border-left:2px solid var(--line);padding-left:14px;margin:0 0 24px;line-height:1.6}
.post .case-result{background:var(--bg-2);border-radius:12px;padding:14px 18px;font-weight:600;margin:0 0 24px}
.post .case-result .k{color:var(--accent);text-transform:uppercase;font-size:var(--t-micro);letter-spacing:.06em;font-weight:700;margin-right:10px}
/* tile -> case-page link (inside the opened card) */
.tile-more{display:inline-block;margin-top:4px;margin-right:18px;color:var(--accent);font-weight:600;font-size:var(--t-small);text-decoration:none}
.tile-more:hover{text-decoration:underline}

/* ============ booking calendar ============ */
.bk-hero{text-align:center;padding:clamp(40px,7vw,72px) 0 clamp(20px,3vw,30px)}
.bk-hero .h2{max-width:20ch;margin:0 auto}
.bk-lead{margin:14px auto 0;text-align:center}
.bk-wrap{padding-bottom:clamp(56px,9vw,96px)}
.bk-card{max-width:900px;margin:0 auto;background:#fff;border:1px solid var(--line);border-radius:20px;box-shadow:0 18px 50px -28px rgba(0,0,0,.28);padding:clamp(20px,3.4vw,34px)}
.bk-grid{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:clamp(22px,3.4vw,40px);align-items:start}
@media(max-width:800px){.bk-grid{grid-template-columns:minmax(0,1fr);gap:26px}}
.bk-main{min-width:0}

.bk-step{margin-bottom:28px}
.bk-step:last-child{margin-bottom:0}
.bk-step-h{display:flex;align-items:center;flex-wrap:wrap;gap:6px 10px;font-size:var(--t-body);font-weight:600;letter-spacing:-.01em;margin-bottom:14px}
.bk-step-h>span:nth-child(2){white-space:nowrap}
.bk-num{display:inline-grid;place-items:center;width:24px;height:24px;border-radius:50%;background:rgba(11,107,75,.1);color:var(--accent);font-size:13px;font-weight:700;flex:0 0 auto}
.bk-tz{font-size:var(--t-micro);color:var(--muted);font-weight:400;letter-spacing:0}

/* duration pills */
.bk-durs{display:flex;flex-wrap:wrap;gap:10px}
.bk-dur{padding:10px 18px;border:1px solid var(--line);border-radius:980px;background:#fff;color:var(--ink);font-family:var(--sans);font-size:var(--t-small);font-weight:500;cursor:pointer;transition:.16s}
.bk-dur:hover{border-color:var(--accent);color:var(--accent-ink)}
.bk-dur.on{background:var(--accent);border-color:var(--accent);color:#fff}

/* day rail */
.bk-days-wrap{position:relative;display:flex;align-items:center;gap:6px}
.bk-days{display:flex;gap:10px;overflow-x:auto;scroll-behavior:smooth;scrollbar-width:none;padding:4px 2px;scroll-snap-type:x proximity;flex:1;min-width:0;-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 14px,#000 calc(100% - 14px),transparent 100%);mask-image:linear-gradient(90deg,transparent 0,#000 14px,#000 calc(100% - 14px),transparent 100%)}
.bk-days::-webkit-scrollbar{display:none}
.bk-day{flex:0 0 auto;min-width:74px;display:flex;flex-direction:column;align-items:center;gap:2px;padding:12px 10px;border:1px solid var(--line);border-radius:14px;background:#fff;cursor:pointer;font-family:var(--sans);transition:.18s;scroll-snap-align:start}
.bk-day:hover{border-color:#b9b9c0;transform:translateY(-1px);box-shadow:0 6px 16px -12px rgba(0,0,0,.3)}
.bk-day-wd{font-size:var(--t-micro);color:var(--muted);text-transform:uppercase;letter-spacing:.04em;font-weight:600}
.bk-day-num{font-size:21px;font-weight:600;letter-spacing:-.02em;color:var(--ink);line-height:1.1}
.bk-day-mon{font-size:var(--t-micro);color:var(--muted);text-transform:uppercase;letter-spacing:.04em;font-weight:600}
.bk-day.on{border-color:var(--accent);background:var(--accent)}
.bk-day.on .bk-day-wd,.bk-day.on .bk-day-num,.bk-day.on .bk-day-mon{color:#fff}
.bk-arrow{flex:0 0 auto;width:34px;height:34px;border-radius:50%;border:1px solid var(--line);background:#fff;color:var(--muted);font-size:20px;line-height:1;cursor:pointer;transition:.18s;display:grid;place-items:center;font-family:var(--sans)}
.bk-arrow:hover{border-color:var(--ink);color:var(--ink)}
@media(max-width:800px){.bk-arrow{display:none}}

/* time slots */
.bk-slots{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:2px;min-height:52px}
.bk-slot{padding:12px 8px;border:1px solid var(--line);border-radius:12px;background:#fff;color:var(--ink);font-family:var(--sans);font-size:15px;font-weight:500;cursor:pointer;transition:.16s;min-height:46px}
.bk-slot:hover{border-color:var(--accent);color:var(--accent-ink)}
.bk-slot.on{background:var(--accent);border-color:var(--accent);color:#fff}
.bk-hint{grid-column:1/-1;color:var(--muted);font-size:var(--t-small);padding:14px 2px;line-height:1.5}

/* summary + form (side) */
.bk-side{position:sticky;top:72px}
@media(max-width:800px){.bk-side{position:static}}
.bk-summary{background:var(--bg-2);border:1px solid var(--line);border-radius:16px;padding:22px}
.bk-sum-title{font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.bk-sum-when{font-size:var(--t-sub);font-weight:600;letter-spacing:-.01em;color:var(--ink);margin:8px 0 16px;line-height:1.3;min-height:1.3em}
.bk-sum-when.empty{color:var(--muted);font-weight:500}
.bk-facts{list-style:none;margin:0 0 18px;padding:16px 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line);display:flex;flex-direction:column;gap:11px;transition:opacity .2s}
.bk-facts li{display:flex;align-items:center;gap:10px;font-size:var(--t-small);color:var(--muted)}
.bk-facts li svg{color:var(--accent);flex:0 0 auto}
.bk-summary.pending .bk-facts{opacity:.5}
.bk-form{display:flex;flex-direction:column;gap:12px}
.bk-field{display:flex;flex-direction:column;gap:5px}
.bk-label{font-size:var(--t-micro);font-weight:600;color:var(--muted);letter-spacing:.01em}
.bk-form input,.bk-form textarea{font-family:var(--sans);font-size:var(--t-small);padding:12px 14px;border:1px solid var(--line);border-radius:11px;background:#fff;color:var(--ink);width:100%}
.bk-form input:focus,.bk-form textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(11,107,75,.12)}
.bk-form textarea{resize:vertical;min-height:52px;line-height:1.4}
.bk-confirm{width:100%;margin-top:4px}
/* Disabled, but still legible: --ink-2 on --bg-2 measures 8.09:1, where the old --muted sat
   at 4.66 and read as switched off rather than waiting. The dashed border repeats it without
   relying on colour, which is what a colour-blind visitor has to go on. */
.bk-confirm:disabled{background:var(--bg-2);color:var(--ink-2);border:1px dashed var(--line-2);cursor:not-allowed}
.bk-confirm:disabled:hover{background:var(--bg-2)}
.bk-need{font-size:var(--t-micro);color:var(--ink-2);text-align:center;margin-top:8px;line-height:1.45}
.bk-need:empty{margin:0}
.bk-paynote{font-size:var(--t-micro);color:var(--muted);text-align:center;margin-top:9px;line-height:1.45}

/* done / error panel */
.bk-done{max-width:560px;text-align:center;padding:clamp(36px,6vw,60px) clamp(24px,4vw,44px)}
.bk-done-icon{width:56px;height:56px;border-radius:50%;background:rgba(11,107,75,.1);color:var(--accent);display:grid;place-items:center;font-size:28px;font-weight:700;margin:0 auto 18px}
.bk-done.err .bk-done-icon{background:rgba(224,138,0,.14);color:var(--build)}
.bk-done-p{color:var(--muted);font-size:var(--t-body);line-height:1.55;margin:12px auto 0;max-width:44ch}
.bk-done-actions{margin-top:28px;display:flex;gap:12px;justify-content:center;flex-wrap:wrap}

/* booking journey — guiding the visitor to the calendar */
.step-cta{display:inline-block;margin-top:16px;background:var(--accent);color:#fff;font-weight:600;font-size:var(--t-small);padding:9px 16px;border-radius:980px;transition:background .2s}
.step-cta:hover{background:var(--accent-ink)}
.related{margin-top:36px}
.related ul{list-style:none;display:flex;flex-wrap:wrap;gap:10px;margin-top:14px;padding:0}
.related a{display:inline-block;border:1px solid var(--line);border-radius:980px;padding:8px 15px;font-size:var(--t-small);font-weight:500;color:var(--accent);transition:.2s}
.related a:hover{border-color:var(--accent);background:var(--bg-2)}
.contact-book{margin:24px 0 4px}
.contact-or{margin-top:12px;font-size:var(--t-small);color:var(--muted)}
.thanks-book{margin-top:22px}
.thanks-book a{color:var(--accent);font-weight:600;font-size:var(--t-body)}
.thanks-book a:hover{text-decoration:underline}

/* ============ factory production line (Pipeline.astro) ============ */
/* Design tokens used by the pipeline. Additive — no existing rule references these,
   so defining them here changes nothing that already renders. */
:root{--accent-tint:#e7f2ec;--gate:#9a6b1a;--gate-tint:#f6efe0;--gate-line:#e6d4ad;--shadow:0 1px 2px rgba(0,0,0,.05);--shadow-lg:0 18px 50px -28px rgba(11,107,75,.45)}
.pipe-scroll{overflow-x:auto;padding:6px 2px 2px;margin:0 -2px;container-type:inline-size}
.pipe{display:flex;align-items:stretch;gap:0;min-width:920px}
.pchev{flex:0 0 26px;display:grid;place-items:center;align-self:center;color:var(--accent)}
.pchev svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;opacity:.85}
.pnode{flex:1 1 0;min-width:0;background:var(--bg);border:1px solid var(--line);border-radius:14px;padding:14px 12px;box-shadow:var(--shadow);display:flex;flex-direction:column;transition:transform .25s ease,box-shadow .25s ease,border-color .25s ease}
.pnode:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg);border-color:var(--accent)}
.pnode .ic{width:38px;height:38px;border-radius:11px;background:var(--accent-tint);color:var(--accent);display:grid;place-items:center;flex:none;margin-bottom:11px}
.pnode .ic svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.pnode .kmi{font-size:9px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;color:var(--muted);white-space:nowrap;margin-bottom:5px}
.pnode .role{font-size:var(--t-small);font-weight:600;letter-spacing:-.01em}
.pnode .what{font-size:var(--t-micro);color:#585c60;line-height:1.4;margin-top:5px}
.pnode.cap{background:var(--ink);border-color:var(--ink)}
.pnode.cap .ic{background:var(--accent);color:#fff}
.pnode.cap .kmi{color:rgba(255,255,255,.62)}.pnode.cap .role{color:#fff}.pnode.cap .what{color:rgba(255,255,255,.8)}
.pnode.check{background:var(--gate-tint);border-color:var(--gate-line)}
.pnode.check:hover{border-color:var(--gate)}
.pnode.check .ic{background:rgba(154,107,26,.15);color:var(--gate)}
.pnode.check .kmi{color:var(--gate)}
@container (max-width:900px){
  .pipe{flex-direction:column;align-items:stretch;min-width:0}
  .pchev{flex:none;height:18px;transform:rotate(90deg)}
  .pnode{flex:none;flex-direction:row;align-items:flex-start;gap:14px}
  .pnode .ic{margin-bottom:0}
  .pnode .txt{display:flex;flex-direction:column}
}
.pipe-tag{font-size:var(--t-small);color:var(--muted);margin-top:22px}
.pipe-tag b{color:var(--ink);font-weight:600}

/* ============ CLAD architecture (Architecture.astro) ============ */
/* Copied 1:1 from the locked design mockup. Additive — new class names only, reusing the tokens
   already defined above (--gate/--gate-tint/--gate-line/--accent-tint/--shadow/--shadow-lg plus the
   base --bg/--bg-2/--ink/--muted/--line/--accent). Nothing existing references these selectors. */
.arch{display:flex;flex-direction:column}
.band{border:1px solid var(--line);border-radius:16px;background:var(--bg);box-shadow:var(--shadow);padding:18px 20px}
.arrow{height:26px;display:grid;place-items:center}
.arrow svg{width:18px;height:18px;stroke:var(--accent);fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;opacity:.85}
.blab{font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.12em;color:var(--muted);margin-bottom:12px;display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.cpill{font-size:9px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--gate);background:var(--gate-tint);border:1px solid var(--gate-line);border-radius:980px;padding:3px 9px;flex:none}
.cnote{font-size:var(--t-micro);color:var(--muted);text-transform:none;letter-spacing:normal;font-weight:400}
.srcs{display:flex;gap:9px;flex-wrap:wrap}
.src{font-size:var(--t-small);color:var(--ink);background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:8px 13px}
.tiers{display:flex;gap:10px}
@media(max-width:560px){.tiers{flex-direction:column}}
.tier{flex:1;border:1px solid var(--line);border-radius:14px;padding:14px 13px;background:var(--bg-2)}
.tier b{font-size:var(--t-small);display:block}
.tier span{font-size:var(--t-micro);color:var(--muted);line-height:1.4;display:block;margin-top:3px}
.golden{margin-top:12px;border:1px solid var(--line);border-radius:14px;padding:14px 16px;background:var(--bg);display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px}
.golden b{font-size:var(--t-small)}.golden .g-desc{font-size:var(--t-micro);color:var(--muted)}
.ai-band{border:1px solid var(--accent);border-radius:16px;background:var(--accent);color:#fff;padding:20px;box-shadow:var(--shadow-lg)}
.ai-band .blab{color:rgba(255,255,255,.8)}
.ai-band .aihead{font-size:var(--t-sub);font-weight:600;letter-spacing:-.01em;margin-bottom:14px;color:#fff}
.ai-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
@media(max-width:720px){.ai-grid{grid-template-columns:1fr}}
.ai-card{background:rgba(0,0,0,.15);border:1px solid rgba(255,255,255,.16);border-radius:14px;padding:14px}
.ai-card b{font-size:var(--t-small);display:block;color:#fff}
.ai-card span{font-size:var(--t-micro);color:rgba(255,255,255,.97);line-height:1.45;display:block;margin-top:3px}
.outs{display:flex;gap:9px;flex-wrap:wrap}
.out{font-size:var(--t-small);color:var(--ink);background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:8px 13px}
.arch .arch-note, .change .arch-note{font-size:var(--t-small);color:var(--muted);margin-top:16px;text-wrap:balance}
.arch-note b{color:var(--ink);font-weight:600}

/* Before/after proof figure inside blog articles (scoped .cf-ba; additive, no collisions). */
.cf-ba{margin:34px 0}
.cf-ba-cap{font-size:var(--t-small);color:var(--muted);margin:0 0 14px;line-height:1.5}
.cf-ba-ai{display:inline-block;font-size:11px;font-weight:600;color:var(--accent);border:1px solid var(--line);border-radius:999px;padding:1px 9px;margin-left:4px;vertical-align:middle;white-space:nowrap}
.cf-ba-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.cf-ba-item{display:flex;flex-direction:column;gap:6px;margin:0}
.cf-ba-item img{width:100%;height:auto;border-radius:10px;border:1px solid var(--line);display:block}
.cf-ba-before img{outline:2px solid var(--accent);outline-offset:-2px}
.cf-ba-tag{font-size:var(--t-micro);color:var(--muted)}
@media(max-width:640px){.cf-ba-grid{grid-template-columns:repeat(2,1fr)}}

/* Block 5 — the project hub and the author page. Both reuse the existing page furniture
   (.wrap, .sec-top, .counter, .quote, .cta-band, .post) so they inherit every earlier fix:
   the type scale, the mobile paddings and the link colours. Only what is genuinely new is
   declared here. */
.hub{padding:clamp(38px,6vw,72px) var(--pad) clamp(48px,7vw,86px)}
.hub-kicker{font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--accent);margin-bottom:12px}
.hub-h1{font-size:clamp(30px,5vw,50px);letter-spacing:-.02em;line-height:1.1;font-weight:600}
.hub-filter{margin-top:18px}
.hub-filter a,.hub-link{color:var(--accent);font-weight:600;font-size:var(--t-small)}
.hub-filter a:hover,.hub-link:hover{text-decoration:underline}
.hub-group{margin-top:clamp(34px,5vw,54px)}
.hub-gh{font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);padding-bottom:10px;border-bottom:1px solid var(--line)}
.hub-list{list-style:none;padding:0;margin:18px 0 0;display:grid;grid-template-columns:repeat(2,1fr);gap:16px}
@media(max-width:720px){.hub-list{grid-template-columns:1fr}}
.hub-card{background:var(--bg-2);border-radius:16px;padding:20px 22px}
.hub-card h3{font-size:var(--t-sub);font-weight:600;letter-spacing:-.01em;line-height:1.25}
.hub-card h3 a{color:var(--ink)}
.hub-card h3 a:hover{color:var(--accent)}
.hub-hook{margin-top:8px;line-height:1.55;color:#2b2a28;font-size:var(--t-body)}
.hub-res,.hub-who{margin-top:10px;font-size:var(--t-small);color:var(--muted);line-height:1.5}
.hub-res .k,.hub-who .k{color:var(--accent);text-transform:uppercase;font-size:var(--t-micro);letter-spacing:.06em;font-weight:700;margin-right:8px}
.hub-more{display:inline-block;margin-top:14px;color:var(--accent);font-weight:600;font-size:var(--t-small)}
.hub-more:hover{text-decoration:underline}
.hub-quote{margin-top:clamp(34px,5vw,54px)}
.hub-reading-lead{margin-top:14px;color:var(--muted);font-size:var(--t-small);max-width:60ch;line-height:1.5}
.hub-reading{list-style:none;padding:0;margin:16px 0 0;display:grid;gap:12px}
.hub-reading a{color:var(--accent);font-weight:600}
.hub-reading a:hover{text-decoration:underline}
.hub-reading-d{display:block;color:var(--muted);font-size:var(--t-small);line-height:1.5;margin-top:3px}
/* The author page is an article, so it borrows .post wholesale; the portrait beside the
   opening paragraph is the only thing the article layout has no rule for. */
.about-top{display:grid;grid-template-columns:.55fr 1.45fr;gap:clamp(18px,3vw,32px);align-items:center;margin-bottom:30px}
/* On a phone the columns stack, and at full width the portrait is 438px tall — it filled the
   first screen and pushed the one sentence that says who he is and what he does down to the
   bottom edge, where the cookie banner covers it on a first visit. Measured, not guessed: the
   opening line started at 626px of an 844px screen. Capped, it starts at about 390px. */
@media(max-width:640px){.about-top{grid-template-columns:1fr}.about-top .portrait{width:150px}}
.about-top .portrait{border-radius:16px;overflow:hidden;background:var(--bg-2);aspect-ratio:4/5}
.about-top .portrait img{width:100%;height:100%;object-fit:cover;display:block}
.about-page .case-lede{margin:0}
.foot-nav{display:flex;gap:8px;flex-wrap:wrap}
.hub-glead{margin-top:12px;color:var(--muted);font-size:var(--t-small);line-height:1.55;max-width:70ch}

/* Block B — the architecture diagram on a selling page.
   Rebuilt twice. The reference is a tweet Sergey had bookmarked (@franpradasAI, 03/08); the
   second rebuild came after watching the video in it properly rather than three stills, and the
   thing the stills hid is the whole point: the board is COMPACT and FIXED. Every part is on one
   screen, nothing moves when you pick a different situation, and the panel beside it carries the
   words. My first attempt put a paragraph in every box, which turned ten boxes into a page you
   scroll — and a diagram you scroll is a list with extra steps.
   Adapted, not copied: the reference is a dark developer tool full of file paths, this is a
   light page a plumber reads. No library either — the boxes stay ordinary markup, so they stack
   on a phone, every word is real text for a search engine and a screen reader, and nothing is
   fetched. Only the connecting line is drawn. */
.arch{margin-top:44px}
.arch-legend{display:flex;flex-wrap:wrap;gap:8px 18px;margin:14px 0 6px}
.arch-key{display:inline-flex;align-items:center;gap:7px;font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
.arch-key::before{content:"";width:9px;height:9px;border-radius:50%;background:var(--live)}
.arch-key-new::before{background:transparent;border:1.5px solid var(--line-2)}

/* Board and rail are one row on a wide screen. The rail never scrolls out of reach and the
   board never moves, which is what makes switching situations feel like one object responding
   rather than a page rebuilding itself. */
/* `align-items:start` matters more than it looks: without it the board stretches to the height
   of the panel beside it, and the written-out path is long, so the board grew a screen and a
   half of empty grey. */
.arch-stage{display:grid;grid-template-columns:minmax(0,1fr);gap:18px;margin-top:18px;align-items:start}
.arch-board{position:relative;border:1px solid var(--line);border-radius:18px;background:linear-gradient(180deg,#fbfbfc,#f6f7f8);padding:20px 18px}
.arch-links{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;z-index:0}
.arch-link{fill:none;stroke:var(--accent);stroke-width:1.7;stroke-linecap:round;opacity:.8}
.arch-dot{fill:var(--accent)}
.arch-dot-t{fill:#fff;font-size:10px;font-weight:700;font-family:var(--sans);text-anchor:middle;dominant-baseline:central}
@keyframes arch-draw{to{stroke-dashoffset:0}}
@keyframes arch-fade{from{opacity:0}to{opacity:1}}
.arch-lanes{position:relative;z-index:1;display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;align-items:start}
.arch .arch-lane-h{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--line-2);margin:0 0 9px;line-height:1.3}
.arch-nodes{list-style:none;margin:0;padding:0;display:grid;gap:0}

/* A box is a label, not a paragraph. `.arch-d` carries the full sentence for a search engine
   and a screen reader; a sighted reader gets it in the panel and on hover. */
.arch-node{position:relative;border:1px solid var(--line);border-left:3px solid var(--line-2);border-radius:10px;padding:9px 11px;background:#fff;transition:opacity .18s,border-color .18s,box-shadow .18s}
.arch-node.is-live{border-left-color:var(--live)}
.arch-node + .arch-node{margin-top:18px}
.arch-node + .arch-node::before{content:"";position:absolute;left:50%;top:-15px;width:1px;height:9px;background:var(--line)}
.arch-node + .arch-node::after{content:"";position:absolute;left:50%;top:-7px;transform:translateX(-50%);border:4px solid transparent;border-top-color:var(--line)}
.arch-node b{display:block;font-size:13px;font-weight:600;line-height:1.25;color:var(--ink)}
.arch-node i{display:block;font-style:normal;font-size:11px;line-height:1.35;color:var(--muted);margin-top:3px}
.arch .arch-d{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.arch a.arch-from{display:inline-block;margin-top:6px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--live);text-decoration:none}
.arch a.arch-from:hover{text-decoration:underline}
.arch-node.dim{opacity:.3}
.arch-node.lit{border-color:var(--accent);border-left-color:var(--accent);background:color-mix(in srgb,var(--live) 6%,#fff);box-shadow:0 6px 18px -12px rgba(11,107,75,.8);animation:arch-pop .3s ease var(--d,0s) both}
@keyframes arch-pop{from{transform:translateY(4px);opacity:.5}to{transform:none;opacity:1}}

/* The rail. Situations on top, the chosen path in words underneath — both always in view. */
.arch-rail{display:grid;gap:14px;align-content:start}
.arch-flows h3,.arch .arch-steps-h{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--line-2);margin:0 0 9px}
.arch-flow-row{display:flex;flex-wrap:wrap;gap:7px}
.arch-flow{font-family:var(--sans);font-size:13px;font-weight:600;color:var(--ink);background:#fff;border:1px solid var(--line);border-radius:999px;padding:8px 14px;cursor:pointer;text-align:left;transition:background .15s,border-color .15s,color .15s}
.arch-flow:hover{border-color:var(--accent);color:var(--accent)}
.arch-flow[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:#fff}
.arch-clear{font-family:var(--sans);font-size:13px;font-weight:600;color:var(--muted);background:none;border:1px solid transparent;border-radius:999px;padding:8px 12px;cursor:pointer;text-decoration:underline}
.arch-clear:hover{color:var(--ink)}
.arch .arch-hint{font-size:var(--t-micro);color:var(--muted);margin-top:9px;line-height:1.45}
.arch-steps{border:1px solid var(--line);border-radius:16px;padding:16px 18px;background:var(--bg-2);animation:arch-fade .25s ease both}
.arch-steps-list{list-style:none;margin:0;padding:0;display:grid;gap:11px}
.arch-steps-list li{position:relative;padding-left:30px}
.arch-steps-list b{display:block;font-size:13px;font-weight:600;line-height:1.3}
.arch-steps-list span{display:block;color:var(--muted);font-size:var(--t-small);line-height:1.5;margin-top:2px}
.arch span.arch-num{position:absolute;top:0;left:0;z-index:2;width:22px;height:22px;border-radius:50%;background:var(--accent);color:#fff;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1;margin:0}

/* The board steps out of the 720px reading column and takes the rail beside it. Fixed pixels,
   not vw — a vw breakout counts the scrollbar and invents sideways overflow. */
@media(min-width:1160px){
  .arch-stage{grid-template-columns:minmax(0,1fr) 290px;margin-left:-180px;margin-right:-180px}
  /* The path in words is the longest thing here and it must not be what sets the height of the
     section. It scrolls inside the panel, the way the reference does it. */
  .arch-steps{max-height:60vh;overflow-y:auto}
}
/* Five stages need room. On a wide screen the board takes more than the site's own container,
   in fixed pixels — measured against the viewport below, never in vw, which counts the scrollbar. */
@media(min-width:1400px){.arch-stage{margin-left:-260px;margin-right:-260px}}
@media(max-width:1159px){.arch-lanes{grid-template-columns:repeat(3,minmax(0,1fr))}}
/* Below 760 the stages stack and the drawn curve is not attempted — arch.js checks the same
   number — because a curve between two boxes in one column crosses everything between them.
   The numbers move onto the boxes there, since there is no line to put them on. */
@media(max-width:759px){
  .arch-lanes{grid-template-columns:minmax(0,1fr);gap:0}
  .arch-lane + .arch-lane{margin-top:22px}
  .arch-node b{font-size:15px}
  .arch-node i{font-size:13px}
  .arch span.arch-num{top:-11px;left:-9px;width:24px;height:24px;font-size:12px;box-shadow:0 0 0 2px #fff}
  .arch .arch-steps-list span.arch-num{top:0;left:0;box-shadow:none}
}
@media(prefers-reduced-motion:reduce){
  .arch-node.lit,.arch-steps{animation:none}
  .arch-link{animation:none !important;stroke-dasharray:none !important;stroke-dashoffset:0 !important}
}
}
.arch .arch-note, .change .arch-note{margin-top:18px;font-size:var(--t-small);color:var(--muted);line-height:1.55}
.sell-price{font-size:var(--t-h2);font-weight:700;color:var(--accent);letter-spacing:-.02em;margin-top:10px}
.sell-time{font-size:var(--t-small);font-weight:600;color:var(--ink-2);margin:6px 0 14px}

/* The selling block on a solution page. Everything a decided buyer needs, before anything that
   talks him out of it: what he gets, what it costs, what is guaranteed, and a box to type in. */
.sell{margin:30px 0 8px;border:1px solid color-mix(in srgb,var(--accent) 30%,var(--line));border-radius:18px;padding:clamp(22px,3vw,32px);background:var(--bg-2);box-shadow:0 14px 34px -22px rgba(11,107,75,.35)}
.sell h2{margin-top:0}
.sell .sell-lead{font-size:var(--t-sub);color:var(--ink-2);line-height:1.45;margin-top:10px}
/* The arithmetic of the pain, on the first screen. A formula the reader fills with his own
   numbers, so it reads as a calculation rather than a claim about a client that does not exist. */
.sell-pain{margin-top:14px;padding:12px 14px;border-left:3px solid var(--accent);background:color-mix(in srgb,var(--accent) 6%,#fff);border-radius:0 10px 10px 0;font-size:var(--t-small);line-height:1.5;color:var(--ink-2);font-weight:600}
/* The offer, complete, before the form: price and the one promise that removes the risk. The
   full band with its reasoning still sits below the form — this is the anchor, not the detail. */
.sell-price-line{margin:14px 0 0;padding:12px 14px;border:1px solid color-mix(in srgb,var(--accent) 30%,var(--line));border-radius:12px;background:#fff;display:grid;gap:4px}
.sell-price-line .sell-price{font-size:clamp(22px,3vw,30px);margin-top:0;line-height:1.1}
.sell-price-line .sell-guar-line{font-size:var(--t-small);color:var(--ink-2);font-weight:600}
.sell-urgency{margin-top:14px;font-size:var(--t-small);color:var(--muted);line-height:1.5}
.sell-gets{list-style:none;margin:18px 0 0;padding:0;display:grid;gap:9px}
.sell-gets li{position:relative;padding-left:24px;color:var(--ink-2);font-size:var(--t-small);line-height:1.5}
.sell-gets li::before{content:"";position:absolute;left:4px;top:.55em;width:8px;height:8px;border-radius:50%;background:var(--live)}
.sell-money{margin-top:22px;padding-top:20px;border-top:1px solid var(--line)}
/* One column. A two-column grid here put the longest paragraph in the narrow half, wrapped
   the headline price onto two lines and, once the ratios were changed, collapsed the
   guarantee column to nothing. Measured at 390, 1024 and 1440. A money block is the last
   thing on a selling page that may depend on a width. */
/* Two declarations lived here and did nothing: a margin-top on .sell-guar overridden by the
   margin:0 three lines down, and grid columns on a .sell-money that stopped being a grid when
   this became one column. Measured, both, before deleting. Stale intent in a file people read
   is how the next person reintroduces the two-column bug. */
.sell-price{font-size:clamp(28px,4vw,40px);font-weight:700;color:var(--accent);letter-spacing:-.02em;line-height:1}
.sell-time{font-size:var(--t-small);font-weight:600;color:var(--ink-2);margin-top:8px;line-height:1.4}
.sell-guar{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.sell-guar li{font-size:var(--t-small);color:var(--muted);line-height:1.5}
.sell-guar b{color:var(--ink)}
.sell-form{margin-top:24px;padding-top:22px;border-top:1px solid var(--line)}
.sell-form h3{font-size:var(--t-sub)}
.sell-form > p{color:var(--muted);font-size:var(--t-small);line-height:1.5;margin:8px 0 14px}
.sell-form .contact-form{display:grid;gap:10px;max-width:none}
.sell-two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
@media(max-width:560px){.sell-two{grid-template-columns:minmax(0,1fr)}}
.sell-or{margin-top:12px;font-size:var(--t-small)}
.sell-or a{color:var(--accent);font-weight:600}
/* Now → After. The buyer's Monday, not the system's parts list. */
.change{margin-top:44px}
.change-grid{display:grid;gap:14px;margin-top:18px}
.change-row{border:1px solid var(--line);border-radius:16px;padding:20px;background:#fff}
.change-when{font-size:var(--t-body);font-weight:600;line-height:1.35;margin-bottom:14px}
.change-pair{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
@media(max-width:640px){.change-pair{grid-template-columns:minmax(0,1fr);gap:10px}}
.change-now,.change-after{border-radius:12px;padding:14px 16px}
.change-now{background:var(--bg-2)}
.change-after{background:color-mix(in srgb,var(--live) 8%,#fff);border:1px solid color-mix(in srgb,var(--live) 30%,transparent)}
.change-now span,.change-after span{display:block;font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px}
.change-now span{color:var(--muted)}
.change-after span{color:var(--live)}
.change-now p,.change-after p{font-size:var(--t-small);line-height:1.5;color:var(--ink-2)}
/* The one piece of proof a studio with no client logos actually has: which already-running
   system this is assembled from, and how many there are. It sits with the offer, not in a
   section further down that a decided buyer never reaches. */
.sell .sell-proof{margin-top:16px;padding:14px 16px;border-left:3px solid var(--live);background:#fff;border-radius:0 12px 12px 0;font-size:var(--t-small);line-height:1.55;color:var(--ink-2)}
/* The parts list, folded. Proof for whoever wants the machine; out of the way for whoever does
   not. Open it and the diagram behaves exactly as before. */
.arch-fold > summary{cursor:pointer;font-size:var(--t-small);font-weight:600;color:var(--accent);padding:12px 0;list-style:none}
.arch-fold > summary::-webkit-details-marker{display:none}
.arch-fold > summary::before{content:"+ ";font-weight:700}
.arch-fold[open] > summary::before{content:"− "}
/* A name and a face beside the box he types into. */
.sell-who{display:flex;gap:14px;align-items:center;margin-top:16px;padding-top:16px;border-top:1px solid var(--line)}
/* The flex item is the <picture>, not the <img> inside it — sizing the img alone let the
   wrapper shrink and the portrait rendered 18px wide inside a 56px circle. Measured, not
   guessed: 18x56 at 390px and 34x56 at 1440px before this. */
.sell-who picture{flex:0 0 56px;width:56px;height:56px;display:block}
.sell-who img{width:56px;height:56px;border-radius:50%;object-fit:cover;object-position:50% 18%}
.sell-who p{font-size:var(--t-small);color:var(--muted);line-height:1.5}
.sell-who b{color:var(--ink)}
.sell-who a{color:var(--accent);font-weight:600;white-space:nowrap}
.sell .sell-why{font-size:var(--t-small);color:var(--muted);line-height:1.5;margin-top:12px}
/* The rule that used to pull the situation buttons above the boxes on a phone is gone with the
   rail it fixed: they now sit above the board at every width, which is what it was reaching for.
   Kept as a note because the defect it cured was real — a tap once changed eight of ten boxes
   1,658px above the reader, measured. */
