/* ---- style.css ---- */
/* Well and Good Growth: Lake & Marigold on paper.
   Tokens, type, and components. Motion lives in site-growth/motion/NN-name.css,
   which the build appends after this file (docs/specs/2026-09-25-rebrand-design.md, section 8). */

/* ---------------------------------------------------------------- fonts */
@font-face{font-family:Besley;src:url('/fonts/besley.woff2') format('woff2');font-weight:700 800;font-style:normal;font-display:swap}
@font-face{font-family:Besley;src:url('/fonts/besley-italic.woff2') format('woff2');font-weight:600;font-style:italic;font-display:swap}
@font-face{font-family:"Libre Franklin";src:url('/fonts/libre-franklin.woff2') format('woff2');font-weight:400 700;font-style:normal;font-display:swap}

/* ---------------------------------------------------------------- tokens */
:root{
  color-scheme:light;
  --paper:#f3efe6;          /* page background */
  --card:#f8f5ee;           /* lighter card stock */
  --ink:#1c2a6b;            /* text, lines, structure */
  --accent:#f0a30a;         /* marigold: fills, the print echo, button shadows. Never text on paper */
  --accent-text:#8c5100;    /* marigold text on paper: emphasis, labels, "and". The spec's #9a5a00 is 4.8:1 on flat
                               paper but falls to about 4.2:1 on the grained paper and 4:1 on the tinted pricing band,
                               under WCAG AA for the small labels; this is at least 4.6:1 on both. The logo files keep
                               #9a5a00 (flat colour, large text). */
  --water:#93a2dc;          /* water in illustrations */
  --water-deep:#6372af;     /* water 60% with ink */
  --soft:#475184;           /* ink 80% on paper: body text */
  --rule:#c8c8cd;           /* ink 20% on paper: dividers */
  --earth:#d9d7d7;          /* ink 12% on paper: illustration ground */
  --wall:#e6e3df;           /* ink 6% on paper: illustration walls */
  --serif:Besley,Georgia,"Times New Roman",serif;
  --sans:"Libre Franklin","Segoe UI",system-ui,-apple-system,sans-serif;
  /* Aliases, so code ported from the motion catalogue works unchanged. */
  --accent-ink:var(--accent-text);--display:var(--serif);--body:var(--sans);
  /* Paper grain: SVG fractal noise (the same value as GRAIN in scripts/growth_art.py). */
  --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .25 0 0 0 0 .2 0 0 0 0 .14 0 0 0 .9 -.25'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  /* Paper with the grain showing at 30%. Use as background-image on anything opaque. */
  --paper-grain:linear-gradient(rgb(243 239 230 / .7),rgb(243 239 230 / .7)),var(--grain);
  --tint:rgb(28 42 107 / .04);   /* a faint ink wash that lets the grain through */
  --sheet:rgb(255 255 255 / .42);/* card stock over the grain */
  --gutter:clamp(16px,4vw,56px);
  --gap:clamp(24px,4vw,64px);
  --header-h:76px;
}

/* ---------------------------------------------------------------- base */
*,*::before,*::after{box-sizing:border-box}
html{background-color:var(--paper);background-image:var(--paper-grain);-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:calc(var(--bar-space,0px) + var(--header-h) + 16px)}
body{margin:0;color:var(--ink);font:400 17px/1.65 var(--sans);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
h1,h2,h3,p,figure,blockquote{margin:0}
h1,h2,h3{font-family:var(--serif);font-weight:700;line-height:1.1;letter-spacing:-.012em;color:var(--ink);text-wrap:balance}
h1{font-size:clamp(36px,5vw,64px);line-height:1.06}
h2{font-size:clamp(30px,3.6vw,46px)}
h3{font-size:clamp(21px,2vw,25px);line-height:1.2}
h1 em,h2 em{font-style:normal;color:var(--accent-text)}
p{color:var(--soft)}
strong{color:var(--ink);font-weight:700}
a{color:inherit;text-decoration:none;-webkit-tap-highlight-color:transparent}
img,video{display:block;max-width:100%;height:auto}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;-webkit-tap-highlight-color:transparent}
button,a{touch-action:manipulation}
:focus-visible{outline:3px solid var(--ink);outline-offset:3px}
::selection{background:var(--accent);color:var(--ink)}
.container{width:min(1200px,calc(100% - 2 * var(--gutter)));margin-inline:auto}
.container .container{width:auto}
.section{padding-block:clamp(56px,8vw,96px)}
.section-intro{max-width:62ch;margin-top:20px;font-size:18px}
.small-note{max-width:70ch;margin-top:24px;font-size:14px}
.label{margin:0 0 16px;font:700 12.5px/1.4 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text)}
.skip-link{position:absolute;left:16px;top:-100px;z-index:60;padding:12px 18px;background:var(--ink);color:var(--paper);font-weight:600}
.skip-link:focus{top:12px}
.sprite{position:absolute;width:0;height:0;overflow:hidden}

/* ---------------------------------------------------------------- buttons and links */
/* Primary button: solid indigo, paper text, a 4px marigold offset shadow (the print echo), 2px corners.
   --press is the shadow offset and --ring an inset ink outline; 02-letterpress.css animates them. */
.button{--press:4px;--ring:0px;display:inline-flex;align-items:center;justify-content:space-between;gap:16px;min-height:48px;padding:12px 20px;border:0;border-radius:2px;background:var(--ink);color:var(--paper);box-shadow:inset 0 0 0 var(--ring) var(--ink),var(--press) var(--press) 0 var(--accent);font:600 15px/1.25 var(--sans);text-align:left;text-decoration:none;white-space:nowrap}
.button span{font-size:18px;line-height:1}
.text-link{display:inline-flex;align-items:center;gap:10px;min-height:44px;font-weight:600;color:var(--ink);white-space:nowrap}
p .text-link{display:inline;min-height:0;white-space:normal}

/* ---------------------------------------------------------------- header */
.site-header{position:sticky;top:var(--bar-space,0px);z-index:20;background-color:var(--paper);background-image:var(--paper-grain);border-bottom:1px solid var(--rule)}
.site-header-inner{position:relative;display:flex;align-items:center;justify-content:space-between;gap:24px;min-height:var(--header-h)}
.brand{display:inline-flex;align-items:center;gap:12px;min-width:0;color:var(--ink)}
.brand-mark{flex:none;width:64px;height:auto;overflow:visible}
.brand-name{font:800 22px/1.1 var(--serif);letter-spacing:-.012em;white-space:nowrap}
.brand-name em{font-style:italic;font-weight:600;color:var(--accent-text)}
.main-nav{display:flex;align-items:center;gap:26px}
.main-nav>a{position:relative;padding-block:12px;font:600 14px/1.2 var(--sans);color:var(--soft);white-space:nowrap}
.main-nav>a:hover,.main-nav>a[aria-current=page]{color:var(--ink)}
.main-nav>a[aria-current=page]::after{content:"";position:absolute;left:0;right:0;bottom:4px;height:3px;background:var(--accent)}
.main-nav .button{--ring:2px;--press:3px;min-height:42px;padding:9px 15px;gap:12px;background:transparent;color:var(--ink);font-size:14px}
.menu-toggle{display:none;min-height:44px;padding:8px 14px;border:2px solid var(--ink);border-radius:2px;background:transparent;color:var(--ink);font:600 14px/1 var(--sans)}

/* ---------------------------------------------------------------- heroes */
.business-hero>.container{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:var(--gap);align-items:center;padding-block:64px 56px}
.business-hero h1{font-size:clamp(38px,4.8vw,64px)}
.hero-description{max-width:46ch;margin-top:24px;font-size:19px;line-height:1.6}
.hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:14px 24px;margin-top:30px}
.hero-copy>.button{margin-top:28px}
.business-hero .small-note{margin-top:22px}
.service-hero{padding-block:56px 48px}
.service-hero>.hero-description{max-width:62ch}
.service-hero>.button{margin-top:28px}
.hero-lower{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--gap);align-items:center;margin-top:28px}
.hero-copy{max-width:520px}
.hero-copy .hero-description{margin-top:0}
.website-hero-art{max-width:560px;justify-self:end;padding:12px;background:var(--sheet);border:2px solid var(--ink);border-radius:3px;box-shadow:8px 8px 0 var(--accent)}
.website-hero-art img{width:100%;aspect-ratio:1.75;object-fit:cover;object-position:top;border-radius:1px}
.concept-banner{margin:0 0 22px;padding:12px 16px;border-left:4px solid var(--accent);background:var(--sheet)}
.concept-banner p{color:var(--ink);font-size:15px;font-weight:600}
.case-hero .hero-description{max-width:62ch}
/* The homepage hero bridge (drawn artwork) is styled in motion/20-hero-bridge.css. */

/* ---------------------------------------------------------------- AI automation task picker */
.automation-picker{width:100%;max-width:500px;justify-self:end;padding-top:22px;border-top:2px solid var(--ink)}
.picker-heading{margin-bottom:18px;font:700 26px/1.2 var(--serif);color:var(--ink)}
.picker-choices{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:20px}
.picker-choices button{min-height:44px;padding:10px 14px;border:2px solid var(--ink);border-radius:2px;background:transparent;color:var(--ink);font:600 14px/1.25 var(--sans)}
.picker-choices button:hover{background:var(--tint)}
.picker-choices button[aria-pressed=true]{background:var(--ink);color:var(--paper);box-shadow:3px 3px 0 var(--accent)}
.picker-result{min-height:220px;padding:26px 28px;background:var(--sheet);border:1px solid var(--rule);border-left:4px solid var(--accent)}
.picker-result [hidden]{display:none}
.picker-result h2{margin-bottom:12px;font-size:clamp(26px,2.6vw,32px)}
.picker-result p:last-child{max-width:40ch;font-size:16px}

/* ---------------------------------------------------------------- homepage services, founder, portfolio */
.services-section{padding-top:clamp(40px,6vw,72px)}
.services-section>h2{max-width:22ch}
.service-links{margin-top:36px}
.service-links>a{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr) auto;gap:16px 40px;align-items:center;padding:28px 12px;border-top:1px solid var(--rule);transition:background-color .25s}
.service-links>a:last-child{border-bottom:1px solid var(--rule)}
.service-links>a:hover{background:var(--tint)}
.service-links h3{font-size:clamp(26px,2.8vw,34px)}
.service-links p{font-size:16px;line-height:1.6}
.service-link-label{font:700 13px/1.3 var(--sans);letter-spacing:.04em;color:var(--accent-text);white-space:nowrap}
.founder-section{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:clamp(40px,7vw,110px);align-items:center;border-top:1px solid var(--rule)}
.founder-photo{max-width:420px;padding-right:8px}
.founder-photo img{width:100%;aspect-ratio:4/5;object-fit:cover;border:2px solid var(--ink);border-radius:3px;box-shadow:8px 8px 0 var(--accent)}
.founder-section h2{margin-bottom:24px}
.founder-section p{max-width:52ch}
.founder-section p+p{margin-top:16px}
.founder-section .button{margin-top:28px}
.portfolio-section{border-top:1px solid var(--rule)}
.portfolio-section>h2{margin-bottom:36px}
.portfolio-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:40px;align-items:start}
.portfolio-image{display:block;overflow:hidden;background:var(--wall);border:2px solid var(--ink);border-radius:3px}
.portfolio-image img{width:100%;aspect-ratio:2.05;object-fit:cover;object-position:top}
.portfolio-feature .portfolio-image{aspect-ratio:.93;padding:22px 22px 0;background:var(--ink)}
.portfolio-feature .portfolio-image img{height:100%;aspect-ratio:auto;object-fit:cover;object-position:top left;border-radius:2px 2px 0 0}
.portfolio-caption{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;margin-top:16px}
.portfolio-caption p{margin-bottom:4px;font:700 12px/1.4 var(--sans);letter-spacing:.12em;text-transform:uppercase;color:var(--accent-text)}
.portfolio-caption h3{font-size:24px}
.portfolio-caption .text-link{flex-shrink:0;font-size:14px}
.portfolio-section>.small-note,.portfolio-feature .small-note{font-size:14px}

/* ---------------------------------------------------------------- capabilities, process, builds */
.capabilities{border-top:1px solid var(--rule)}
.capability-list{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:40px;margin-top:44px}
.capability-list article{padding-top:20px;border-top:3px solid var(--ink)}
.capability-list h3{margin-bottom:12px}
.capability-list p{font-size:16px}
.approach-section{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--gap);border-top:1px solid var(--rule)}
.approach-section+.section{border-top:1px solid var(--rule)}  /* e.g. the AI workflow automation section, which has no class of its own */
.approach-section>div>p+p{margin-top:18px}
.approach-section>div>.button{margin-top:26px}
/* Step numbers sit in small lock chambers, shown full at rest. */
.process-list{display:grid;gap:30px;margin:0;padding:0;list-style:none;counter-reset:step}
.process-list li{position:relative;min-height:40px;padding-left:62px;counter-increment:step}
.process-list li::before{content:counter(step);position:absolute;left:0;top:-4px;display:grid;place-items:center;width:40px;height:40px;border:2.5px solid var(--ink);border-top:0;border-radius:0 0 3px 3px;background:linear-gradient(var(--water),var(--water)) 0 100%/100% 72% no-repeat;font:800 18px/1 var(--serif);color:var(--ink)}
.process-list h3{margin-bottom:8px;font-size:22px}
.process-list p{max-width:46ch;font-size:16px}
.automation-example{padding:clamp(26px,4.5vw,56px);margin-top:clamp(40px,6vw,72px);background:var(--sheet);border:2px solid var(--ink);border-radius:3px}
.builds{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:28px;margin-top:36px}
.builds article{padding-top:18px;border-top:3px solid var(--accent)}
.builds article>p{margin-top:10px;font-size:16px}

/* ---------------------------------------------------------------- pricing */
.pricing-section{background:var(--tint);border-block:1px solid var(--rule)}
.plans{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px;margin-top:40px}
.plan{position:relative;display:flex;flex-direction:column;padding:28px;background:var(--sheet);border:2px solid var(--ink);border-radius:3px}
.plan h3{font-size:30px}
.plan-description{min-height:3.2em;margin-top:10px;font-size:15px;line-height:1.55}
.price{margin-top:24px;font:700 clamp(40px,4vw,52px)/1 var(--serif);letter-spacing:-.02em;color:var(--ink)}
.price span{margin-left:4px;font:500 14px/1 var(--sans);letter-spacing:0;color:var(--soft)}
.plan-terms{margin-top:12px;font-size:13.5px;line-height:1.7}
.plan ul{display:grid;gap:10px;margin:24px 0 28px;padding:22px 0 0;border-top:1px solid var(--rule);list-style:none;font-size:15px;line-height:1.5}
.plan li{position:relative;padding-left:24px;color:var(--soft)}
.plan li::before{content:"";position:absolute;left:2px;top:.42em;width:10px;height:5px;border-left:2px solid var(--ink);border-bottom:2px solid var(--ink);transform:rotate(-45deg)}
.plan .button{align-self:stretch;margin-top:auto;padding-inline:16px;white-space:normal}
.pricing-note{max-width:80ch;margin-top:24px;font-size:13.5px}

/* ---------------------------------------------------------------- FAQ */
.faq{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:var(--gap);border-top:1px solid var(--rule)}
.faq h2{max-width:12ch;font-size:clamp(30px,3vw,40px)}
.faq details{padding-block:18px;border-bottom:1px solid var(--rule)}
.faq details:first-child{padding-top:0}
.faq summary{display:flex;justify-content:space-between;align-items:baseline;gap:24px;font:600 17px/1.45 var(--sans);color:var(--ink);cursor:pointer;list-style:none}
.faq summary::-webkit-details-marker{display:none}
.faq summary span{flex:none;font:400 26px/1 var(--sans);color:var(--accent-text);transition:transform .2s}
.faq details[open] summary span{transform:rotate(45deg)}
.faq details p{max-width:62ch;margin-top:12px;font-size:16px}

/* ---------------------------------------------------------------- case studies */
.case-screenshot{margin-top:clamp(28px,4vw,48px);padding-bottom:clamp(40px,4vw,48px)}  /* ends the hero, like .service-hero's bottom padding */
.case-screenshot a{display:block}
.case-screenshot img{width:100%;border:2px solid var(--ink);border-radius:3px;box-shadow:8px 8px 0 var(--accent)}
.case-screenshot figcaption{margin-top:16px;font-size:13px;color:var(--soft)}
/* Case stories share the left edge of every other section and keep an 820px reading measure. */
.case-story{border-top:1px solid var(--rule)}
:where(.case-story)>*{max-width:820px}
.case-story>p{margin-top:20px;font-size:18px;line-height:1.75}
.case-story>h2{margin:52px 0 20px;font-size:clamp(28px,3vw,38px)}
.case-story>h2:first-child,.case-story>.label+h2{margin-top:0}
.case-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:28px;margin:32px 0}
.case-stats>div{padding-top:16px;border-top:3px solid var(--ink)}
.case-stats strong{display:block;font:800 clamp(36px,4vw,48px)/1.05 var(--serif);color:var(--ink)}
.case-stats span{display:block;max-width:30ch;margin-top:10px;font-size:15px;line-height:1.5;color:var(--soft)}
.case-story>.small-note{font-size:13.5px;line-height:1.6}
.case-results{display:grid;gap:14px;margin:24px 0 0;padding-left:22px;font-size:17px;line-height:1.65;color:var(--soft)}
.case-results li::marker{color:var(--accent-text)}
.case-quote{margin-top:44px;padding:clamp(22px,3.5vw,34px);background:var(--sheet);border:2px solid var(--ink);border-radius:3px;box-shadow:8px 8px 0 var(--accent)}
.case-quote p{font:italic 600 clamp(19px,2vw,23px)/1.55 var(--serif);color:var(--ink)}
.case-quote cite{display:block;margin-top:20px;font:700 12.5px/1.4 var(--sans);font-style:normal;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text)}
/* Privacy notice content from content/privacy.html. */
.lane-grid{display:grid;gap:40px}
.definition h2{margin-bottom:12px;font-size:clamp(24px,2.6vw,30px)}
.definition p+p{margin-top:12px}

/* ---------------------------------------------------------------- contact */
.contact-section{padding-block:clamp(64px,9vw,104px);border-top:1px solid var(--rule)}
.contact-section h2{max-width:20ch;font-size:clamp(32px,4vw,52px)}
.contact-section p{max-width:54ch;margin-top:20px;font-size:18px}
.contact-section .button{margin-top:30px}
.contact-page{padding-top:8px}
.contact-panel{max-width:680px;margin-inline:auto;padding:clamp(20px,4vw,44px);background:var(--sheet);border:2px solid var(--ink);border-radius:3px;box-shadow:8px 8px 0 var(--accent)}
.contact-panel h2{margin-bottom:12px;font-size:clamp(28px,3.4vw,36px)}
.contact-panel .form-result:empty{display:none}
.contact-preview{width:min(600px,calc(100% - 32px));max-height:calc(100dvh - 32px);overflow-y:auto;padding:clamp(22px,4vw,34px);background-color:var(--paper);background-image:var(--paper-grain);color:var(--ink);border:2px solid var(--ink);border-radius:3px;box-shadow:8px 8px 0 var(--accent)}
.contact-preview::backdrop{background:rgb(28 42 107 / .55)}
.contact-preview h2{margin-bottom:12px;font-size:clamp(27px,4vw,34px)}
.contact-preview>p{font-size:15px}
.dialog-close{display:block;min-height:40px;margin:0 0 18px auto;padding:6px 14px;border:2px solid var(--ink);border-radius:2px;background:transparent;color:var(--ink);font:600 14px/1 var(--sans)}
.enquiry-form{display:grid;gap:18px;margin-top:24px}
.enquiry-form [hidden]{display:none}
.enquiry-form label{display:grid;gap:7px;font:600 14px/1.4 var(--sans);color:var(--ink)}
.enquiry-form input,.enquiry-form select,.enquiry-form textarea{width:100%;min-height:46px;padding:10px 12px;background:rgb(255 255 255 / .6);color:var(--ink);border:1.5px solid var(--soft);border-radius:2px;font:400 16px/1.4 var(--sans)}
.enquiry-form input:focus,.enquiry-form select:focus,.enquiry-form textarea:focus{border-color:var(--ink)}
.enquiry-form textarea{min-height:110px;resize:vertical}
.enquiry-form textarea::placeholder{color:var(--soft);opacity:.85}
.enquiry-form .button{justify-self:start}
.contact-details{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
.service-form-note{font-size:14px;line-height:1.5}
.form-privacy{max-width:56ch;font-size:13px;line-height:1.55}
.form-result{margin-top:16px;color:var(--ink)}
.honeypot{position:absolute;left:-10000px;width:1px;height:1px;opacity:0;pointer-events:none}

/* ---------------------------------------------------------------- footer */
footer{display:grid;grid-template-columns:auto minmax(0,1fr);gap:24px 48px;align-items:center;padding-block:36px 44px;border-top:2px solid var(--ink)}
footer>div{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px 24px;font-size:13.5px;color:var(--soft)}
footer>div a{padding-block:6px;color:var(--soft)}
footer>div a:hover{color:var(--ink)}
footer details summary{cursor:pointer;padding-block:6px}
footer details a{display:block}
footer .brand-name{font-size:20px}

/* ---------------------------------------------------------------- responsive */
@media (max-width:1100px){
  .menu-toggle{display:inline-flex;align-items:center}
  .main-nav{position:absolute;top:100%;left:0;right:0;z-index:5;display:none;flex-direction:column;align-items:stretch;gap:0;padding:12px 20px 22px;background-color:var(--paper);background-image:var(--paper-grain);border:2px solid var(--ink);border-top:0;box-shadow:6px 6px 0 var(--accent)}
  .main-nav.open{display:flex}
  .main-nav>a{padding-block:13px;font-size:17px;border-bottom:1px solid var(--rule)}
  .main-nav>a[aria-current=page]::after{bottom:9px;right:auto;width:28px}
  .main-nav .button{margin-top:18px;justify-content:space-between;font-size:15px;min-height:48px}
  .service-links>a{grid-template-columns:minmax(0,1fr) minmax(0,1.3fr);gap:14px 32px}
  .service-link-label{grid-column:2}
  .portfolio-caption{display:block}
  .portfolio-caption .text-link{margin-top:6px}
}
@media (max-width:900px){
  .capability-list{gap:28px}
  .builds{gap:22px}
  .faq{grid-template-columns:minmax(0,1fr)}
  .faq h2{max-width:none}
  .plan{padding:22px}
  .plans{gap:14px}
}
@media (max-width:760px){
  :root{--header-h:66px}
  body{font-size:16px}
  .brand{gap:9px}
  .brand-mark{width:50px}
  .brand-name{font-size:19px}
  .business-hero>.container{grid-template-columns:minmax(0,1fr);gap:8px;padding-block:24px 44px}
  h1 br,h2 br{display:none}  /* let headings wrap naturally on phones instead of at desktop line breaks */
  .hero-lower,.approach-section,.founder-section{grid-template-columns:minmax(0,1fr)}
  .hero-lower{gap:32px}
  .service-hero{padding-block:36px 40px}
  .hero-description{font-size:17px}
  .website-hero-art{justify-self:start;box-shadow:6px 6px 0 var(--accent)}
  .automation-picker{justify-self:stretch;max-width:none}
  .service-links>a{grid-template-columns:minmax(0,1fr);gap:10px;padding:24px 4px}
  .service-link-label{grid-column:auto}
  .founder-section{gap:32px}
  .founder-photo{max-width:260px}
  .portfolio-grid,.capability-list,.builds,.plans{grid-template-columns:minmax(0,1fr)}
  .portfolio-grid{gap:36px}
  .portfolio-feature .portfolio-image{aspect-ratio:1.5;padding:14px 14px 0}
  .portfolio-image img{aspect-ratio:1.65}
  .plan-description{min-height:0}
  .contact-details{grid-template-columns:minmax(0,1fr)}
  .case-story>p{font-size:17px}
  footer{grid-template-columns:minmax(0,1fr)}
  footer>div{justify-content:flex-start;gap:4px 20px}
}
@media (max-width:420px){
  .brand-mark{width:44px}
  .brand-name{font-size:17px}
  .site-header-inner{gap:12px}
  .button{gap:12px;padding-inline:16px}
}
/* The marigold echo is dropped wherever the mark is 32px tall or smaller. */
@media (max-width:760px){.brand-mark .mark-echo{display:none}}

/* ---------------------------------------------------------------- reduced motion safety net
   Every motion partial handles reduced motion itself; this makes anything left over finish at once. */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
}
@media print{.site-header{position:static}}

/* ---- motion/01-print.css ---- */
/* 1. Headlines print in: the marigold plate lands first and slides into register under the indigo.
   The text never moves or fades; only its marigold text-shadow travels. H1s play on load,
   section H2s when 01-print.js adds .is-printing as they enter the screen. */
@keyframes wg-print{
  0%{text-shadow:14px 10px 0 var(--accent)}
  40%{text-shadow:5px 4px 0 var(--accent)}
  75%{text-shadow:1.5px 1px 0 var(--accent)}
  100%{text-shadow:0 0 0 transparent}
}
@media (prefers-reduced-motion:no-preference){
  main h1{animation:wg-print 1.1s .1s cubic-bezier(.2,.7,.2,1) both}
  main h2.is-printing{animation:wg-print 1.1s cubic-bezier(.2,.7,.2,1) both}
}

/* ---- motion/02-letterpress.css ---- */
/* 2. Letterpress buttons: on hover or keyboard focus the button lifts off the paper as its
   marigold shadow slips; pressing stamps it flat. --press (the shadow offset) is set in style.css. */
.button{transition:transform .16s ease,box-shadow .16s ease}
.button:hover,.button:focus-visible{transform:translate(-1px,-2px);--press:7px}
.button:active{transform:translate(3px,3px);--press:0px;transition-duration:.07s}
@media (prefers-reduced-motion:reduce){.button:hover,.button:focus-visible,.button:active{transform:none}}

/* ---- motion/03-header-lift.css ---- */
/* 3. The bridge in the header and footer logo: the span lifts between the towers on hover,
   keyboard focus, or tap, and settles back. The .lift groups come from growth_art.mark_svg(). */
.brand-mark .lift{transition:transform .7s cubic-bezier(.45,0,.2,1)}
.brand:hover .brand-mark .lift,.brand:focus-visible .brand-mark .lift,.brand:active .brand-mark .lift{transform:translateY(-44px)}
@media (prefers-reduced-motion:reduce){.brand-mark .lift{transition:none}}

/* ---- motion/04-ink-links.css ---- */
/* 4. Ink links: a pen stroke draws under text links and links in paragraphs on hover or focus.
   At rest a thin rule underlines them, so links never rely on colour alone. Not buttons, not navigation. */
.text-link,main p a:not(.button),.form-privacy a{
  color:var(--ink);font-weight:600;text-decoration:none;padding-bottom:2px;
  background:linear-gradient(var(--rule),var(--rule)) 0 100%/100% 1.5px no-repeat,linear-gradient(var(--ink),var(--ink)) 0 100%/0% 2px no-repeat;
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
  transition:background-size .45s cubic-bezier(.5,0,.2,1)
}
/* Standalone text links are 44px tall tap targets; keep their line just under the words. */
.text-link{background-position:0 calc(50% + .8em),0 calc(50% + .8em)}
p .text-link{background-position:0 100%,0 100%}
.text-link:hover,.text-link:focus-visible,main p a:not(.button):hover,main p a:not(.button):focus-visible,.form-privacy a:hover,.form-privacy a:focus-visible{background-size:100% 1.5px,100% 2px}
@media (prefers-reduced-motion:reduce){.text-link,main p a:not(.button),.form-privacy a{transition:none}}

/* ---- motion/05-canal-bar.css ---- */
/* 5. Canal reading bar: a thin water line along the top edge, with the freighter riding it as you read.
   The page reserves the bar's height (--bar-space) and the sticky header sits below it, so the bar
   never covers the header's links. Markup is in page() in scripts/build_growth.py. Hidden under
   reduced motion and in print, where the reserved space goes too. */
:root{--bar-h:24px;--bar-space:calc(var(--bar-h) + env(safe-area-inset-top,0px))}
body{padding-top:var(--bar-space)}
.canal-bar{position:fixed;top:0;left:0;right:0;z-index:30;height:var(--bar-space);background-color:var(--paper);background-image:var(--paper-grain);pointer-events:none}
.canal-track,.canal-fill{position:absolute;left:0;bottom:5px;height:3px}
.canal-track{right:0;background:var(--rule)}
.canal-fill{width:100%;background:var(--water);transform:scaleX(0);transform-origin:0 50%}
.canal-ship{position:absolute;left:8px;bottom:4px;width:40px;height:19px;overflow:visible}
@media (prefers-reduced-motion:reduce){:root{--bar-space:0px}.canal-bar{display:none}}
@media print{:root{--bar-space:0px}.canal-bar{display:none}}

/* ---- motion/06-form.css ---- */
/* 6. Enquiry form: each field draws its line on focus, the marigold plate first and then the indigo
   over it, a little out of register like the logo. When a valid enquiry is sent, a freighter casts off
   from beside Send enquiry and leaves a wake. Markup: the enquiry <dialog> in page() in
   scripts/build_growth.py, which /contact/ also shows inline. */

/* Every visible field sits last in its label, so the label's bottom edge is the field's bottom edge. */
.enquiry-form label{position:relative}
.enquiry-form label::before,.enquiry-form label::after{content:"";position:absolute;left:0;right:0;height:2.5px;pointer-events:none;transform:scaleX(0);transform-origin:0 50%;transition:transform .3s cubic-bezier(.5,0,.2,1)}
.enquiry-form label::before{bottom:-4px;background:var(--accent);transition-delay:.1s}
.enquiry-form label::after{bottom:0;background:var(--ink)}
.enquiry-form label:focus-within::before{transform:scaleX(1);transition:transform .4s cubic-bezier(.5,0,.2,1)}
.enquiry-form label:focus-within::after{transform:scaleX(1);transition:transform .5s .14s cubic-bezier(.5,0,.2,1)}
/* The focused field also darkens and thickens its border at once, so focus never depends on the drawing. */
.enquiry-form :is(input,select,textarea):focus-visible{outline:1px solid var(--ink);outline-offset:0;border-color:var(--ink)}

/* The castoff. Hidden at rest; 06-form.js sets --travel to the room beside the button. The ship sits
   behind the button (z-index -1 inside the isolated row), so its trailing wake starts out tucked under it. */
.enquiry-form .send-row{position:relative;isolation:isolate;display:inline-flex;align-items:center;justify-self:start;max-width:100%}
.send-row .castoff{position:absolute;z-index:-1;left:100%;top:50%;width:52px;height:25px;margin:-14px 0 0 8px;overflow:visible;opacity:0;pointer-events:none}
.castoff .wake path{fill:none;stroke:var(--water-deep);stroke-width:2.2;stroke-linecap:round}
.castoff .wake path:nth-child(2){opacity:.6}
.castoff .wake path:nth-child(3){opacity:.32}
.castoff .wake path:nth-child(4){opacity:.14}
.castoff .wake{opacity:0}
.send-row .castoff.is-going{animation:wg-castoff-move 1.7s cubic-bezier(.5,0,.35,1) both,wg-castoff-fade 1.7s linear both,wg-castoff-bob .55s ease-in-out 3 alternate}
.send-row .castoff.is-going .wake{animation:wg-wake-in .45s .2s ease-out both}
@keyframes wg-castoff-move{from{transform:translateX(0)}to{transform:translateX(var(--travel,120px))}}
@keyframes wg-castoff-fade{0%{opacity:0}12%,72%{opacity:1}100%{opacity:0}}
@keyframes wg-castoff-bob{from{translate:0 0}to{translate:0 -1.5px}}
@keyframes wg-wake-in{from{opacity:0;transform:translateX(6px)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion:reduce){
  .enquiry-form label::before,.enquiry-form label::after{transition:none}
  .send-row .castoff{display:none}
}

/* ---- motion/07-faq.css ---- */
/* 7. FAQ gates: each question's icon is a small lift gate. Opening the question raises the gate about
   9 units so the water runs through, and the answer eases in. The <details> element is untouched, so
   keyboard and screen readers behave as normal; the icon is decorative. Markup: faq() in
   scripts/build_growth.py. No script needed. */
.faq summary{align-items:flex-start}
.faq .gate-ic{flex:none;width:26px;height:26px;margin-top:-1px;overflow:visible}
.gate-ic .gi-post{fill:none;stroke:var(--ink);stroke-width:2;stroke-linecap:round}
.gate-ic .gi-water{fill:var(--water)}
.gate-ic .gi-gate{fill:var(--accent);stroke:var(--ink);stroke-width:1;transition:transform .45s cubic-bezier(.3,1.4,.5,1)}
/* A small lift on hover or keyboard focus hints that the gate opens. */
.faq summary:hover .gi-gate,.faq summary:focus-visible .gi-gate{transform:translateY(-2px)}
.faq details[open] .gi-gate{transform:translateY(-9px)}
.faq details[open]>p{animation:wg-answer-in .42s cubic-bezier(.2,.7,.2,1) both}
@keyframes wg-answer-in{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
/* Where the browser can, the answer's space opens and closes smoothly too. */
@supports selector(::details-content){
  @media (prefers-reduced-motion:no-preference){
    .faq details{interpolate-size:allow-keywords}
    .faq details::details-content{block-size:0;overflow:hidden;transition:block-size .38s cubic-bezier(.3,.7,.2,1),content-visibility .38s allow-discrete}
    .faq details[open]::details-content{block-size:auto}
  }
}
@media (prefers-reduced-motion:reduce){
  .gate-ic .gi-gate{transition:none}
  .faq details[open]>p{animation:none}
}

/* ---- motion/08-process.css ---- */
/* 8. Process steps fill like lock chambers: when a .process-list comes on screen, the water in each
   numbered chamber rises in turn, surges a little, and settles. At rest (no script, reduced motion, or
   a list already on screen at load) the chambers are full, as style.css draws them. The number sits
   over the water in ink and stays readable throughout. 08-process.js adds the classes and --step. */
.process-list li::before{background:linear-gradient(rgb(243 239 230 / .85) 0 1.5px,var(--water) 1.5px) 0 100%/100% 72% no-repeat}
.process-list.is-waiting li::before{background-size:100% 0%}
.process-list.is-filling li::before{animation:wg-lock-fill 1.05s calc(var(--step,0) * .45s + .1s) cubic-bezier(.3,.75,.35,1.18) both}
@keyframes wg-lock-fill{from{background-size:100% 0%}to{background-size:100% 72%}}
@media (prefers-reduced-motion:reduce){.process-list li::before{animation:none!important;background-size:100% 72%!important}}

/* ---- motion/09-plans.css ---- */
/* 9. Plans as water levels: Launch, Grow, and Dominate hold water to about 30%, 55%, and 80% of the card,
   so more support reads as a higher level. It rises when the cards come on screen, and its surface drifts
   gently while they stay on screen. The water is pale and sits behind the text (the card is its own
   stacking context, so z-index:-1 stays above the card's background). Hover or focus inside a card
   lifts it like a span. At rest the water simply stands at its level. 09-plans.js adds the classes. */
.plan{isolation:isolate;--lvl:30%;transition:transform .25s ease,box-shadow .25s ease}
.plan:nth-child(2){--lvl:55%}
.plan:nth-child(3){--lvl:80%}
.plan::before{
  content:"";position:absolute;left:0;right:0;bottom:0;z-index:-1;height:var(--lvl);border-radius:0 0 1px 1px;opacity:.3;pointer-events:none;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='8'%3E%3Cpath d='M0 5 Q12 1.5 24 5 T48 5 V8 H0Z' fill='%2393a2dc'/%3E%3Cpath d='M0 5 Q12 1.5 24 5 T48 5' fill='none' stroke='%231c2a6b' stroke-width='1.3'/%3E%3C/svg%3E") 0 0/48px 8px repeat-x,
    linear-gradient(var(--water),var(--water)) 0 7px/100% 100% no-repeat;
  animation:wg-plan-drift 7s calc(var(--i,0) * -2.4s) linear infinite paused
}
.plans.is-drifting .plan::before{animation-play-state:running}
.plan.is-waiting::before{height:0}
.plan.is-rising::before{animation:wg-plan-rise 1.6s calc(var(--i,0) * .2s + .1s) cubic-bezier(.2,.7,.3,1) both,wg-plan-drift 7s calc(var(--i,0) * -2.4s) linear infinite paused}
.plans.is-drifting .plan.is-rising::before{animation-play-state:running,running}
@keyframes wg-plan-rise{from{height:0}}
@keyframes wg-plan-drift{from{background-position:0 0,0 7px}to{background-position:48px 0,0 7px}}
@media (hover:hover){.plan:hover{transform:translateY(-6px);box-shadow:6px 8px 0 var(--accent)}}
.plan:focus-within{transform:translateY(-6px);box-shadow:6px 8px 0 var(--accent)}
@media (prefers-reduced-motion:reduce){
  .plan::before,.plan.is-rising::before{animation:none;height:var(--lvl)}
  .plan,.plan:hover,.plan:focus-within{transform:none;transition:none}
}

/* ---- motion/10-results.css ---- */
/* 10. Real results rise: before and after water columns that restate results already written on the page
   (markup from scripts/art_local.py). Levels are drawn to scale within each chart. At rest every column is
   full to its level and every number is printed; 10-results.js fills them and counts up when a chart first
   comes on screen. The charts are aria-hidden because the sentences beside them already give each figure. */
/* Columns line up by row (number, tank, label), so a label that wraps never lifts its tank. */
.rise-cols{display:grid;grid-template-columns:repeat(2,minmax(0,104px));gap:16px;align-items:start}
.rise-col{display:grid;justify-items:center;gap:6px;min-width:0}
.rise-val{font:800 19px/1.1 var(--serif);color:var(--ink);white-space:nowrap}
.rise-tank{position:relative;display:block;width:100%;height:118px;border:2.5px solid var(--ink);border-top:0;border-radius:0 0 3px 3px;background:var(--wall);overflow:hidden}
.rise-level{position:absolute;left:0;right:0;bottom:0;height:var(--h);background:var(--water);box-shadow:inset 0 2px 0 rgb(255 255 255 / .45);transform-origin:50% 100%}
.rise-col.is-after .rise-level{background:var(--water-deep)}
/* One line, so tanks in neighbouring charts share a baseline; a long period may run into the gap. */
.rise-when{font-size:12.5px;line-height:1.3;text-align:center;white-space:nowrap;color:var(--soft)}

/* Growth marketing: two charts under the Jetta Grove results. */
.results-rise{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px clamp(20px,4vw,48px);margin-top:32px}
.rise{display:flex;flex-direction:column;gap:16px;padding-top:16px;border-top:3px solid var(--ink)}
.rise-title{margin:0;font-size:14px;line-height:1.45;color:var(--soft)}
.rise-title strong{display:block;font:700 18px/1.25 var(--serif);color:var(--ink)}
.rise .rise-cols{margin-top:auto}

/* Frank's case study: a before and after pair under "Nearly 3x". style.css styles every span in
   .case-stats as a caption, so the chart's own spans are reset here. */
.stat-rise .rise-frank{margin-top:20px}
.case-stats .rise-group span{margin-top:0;max-width:none}
.case-stats .rise-when{font-size:12.5px;line-height:1.3}
.rise-frank .rise-cols{grid-template-columns:repeat(2,minmax(0,64px))}
.rise-frank .rise-tank{height:92px}

@media (max-width:420px){
  .results-rise{gap:20px 16px}
  .rise-cols{gap:12px}
  .rise-when{font-size:11.5px}
  .rise-val{font-size:17px}
  .rise-tank{height:104px}
}

@keyframes wg-rise{from{transform:scaleY(0)}to{transform:none}}
@media (prefers-reduced-motion:no-preference){
  .rise-group.is-armed .rise-level{transform:scaleY(0)}
  .rise-group.is-rising .rise-level{animation:wg-rise 1.4s var(--d,0ms) cubic-bezier(.2,.7,.3,1) both}
}

/* ---- motion/11-portfolio.css ---- */
/* 11. Portfolio screenshots glide and tilt. On hover or keyboard focus the screenshot pans slowly through
   its frame to show the part the frame crops (the lower half of the tall Welland Votes page, for one), and
   eases back when you move away. With a mouse, the frame also tilts slightly toward the pointer while its
   marigold shadow shifts. Phones play the glide once as each screenshot scrolls in. No tilt on touch
   screens or under reduced motion. 11-portfolio.js adds .is-tilting and .is-gliding. */
.portfolio-grid .portfolio-image img{transition:object-position 1.4s cubic-bezier(.45,0,.25,1)}
.portfolio-grid .portfolio-image:hover img,.portfolio-grid .portfolio-image:focus-visible img,.portfolio-grid .portfolio-image.is-gliding img{object-position:50% 100%;transition-duration:3.2s}
.portfolio-grid .portfolio-feature .portfolio-image:hover img,.portfolio-grid .portfolio-feature .portfolio-image:focus-visible img,.portfolio-grid .portfolio-feature .portfolio-image.is-gliding img{object-position:100% 100%}
.portfolio-grid .portfolio-image:focus-visible{box-shadow:6px 6px 0 var(--accent)}
@media (hover:hover) and (pointer:fine) and (prefers-reduced-motion:no-preference){
  .portfolio-grid .portfolio-image{transition:transform .45s cubic-bezier(.3,.7,.3,1),box-shadow .45s cubic-bezier(.3,.7,.3,1)}
  .portfolio-grid .portfolio-image.is-tilting{transform:perspective(1000px) rotateX(var(--tilt-x,0deg)) rotateY(var(--tilt-y,0deg));box-shadow:var(--shade-x,0px) var(--shade-y,8px) 0 var(--accent);transition-duration:.15s}
}
@media (prefers-reduced-motion:reduce){.portfolio-grid .portfolio-image img{transition:none}}

/* ---- motion/12-founder.css ---- */
/* 12. Founder photo frame. At rest the colour photo sits in an indigo border with the marigold print echo.
   On mouseover the echo swings once around the frame, like a second printing plate finding register,
   the photo lifts a touch, and an indigo rule draws itself around the frame, clockwise from the top left.
   Touch screens play it once when the photo comes on screen (12-founder.js adds .is-lit).
   Under reduced motion the rule simply appears and nothing moves. Markup: founder() in scripts/build_growth.py. */
.founder-print{position:relative;border:2px solid var(--ink);border-radius:3px;box-shadow:8px 8px 0 var(--accent);background:var(--wall);
  transition:transform .45s cubic-bezier(.2,.8,.2,1),box-shadow .45s cubic-bezier(.2,.8,.2,1)}
.founder-photo .founder-print img{display:block;border:0;border-radius:1px;box-shadow:none}
.founder-trace{position:absolute;inset:-15px;pointer-events:none;opacity:0;transition:opacity .4s ease;
  background:linear-gradient(var(--ink),var(--ink)) left top/100% 2px no-repeat,linear-gradient(var(--ink),var(--ink)) right top/2px 100% no-repeat,
    linear-gradient(var(--ink),var(--ink)) right bottom/100% 2px no-repeat,linear-gradient(var(--ink),var(--ink)) left bottom/2px 100% no-repeat}
@keyframes founder-trace{
  0%{background-size:0 2px,2px 0,0 2px,2px 0}
  25%{background-size:100% 2px,2px 0,0 2px,2px 0}
  50%{background-size:100% 2px,2px 100%,0 2px,2px 0}
  75%{background-size:100% 2px,2px 100%,100% 2px,2px 0}
  100%{background-size:100% 2px,2px 100%,100% 2px,2px 100%}}
@keyframes founder-orbit{
  0%{box-shadow:8px 8px 0 var(--accent)}
  24%{box-shadow:-8px 8px 0 var(--accent)}
  48%{box-shadow:-8px -8px 0 var(--accent)}
  72%{box-shadow:8px -8px 0 var(--accent)}
  100%{box-shadow:11px 11px 0 var(--accent)}}
.founder-print.is-lit{animation:founder-orbit 1.15s cubic-bezier(.45,0,.3,1) both;transform:translate(-3px,-3px)}
.founder-print.is-lit .founder-trace{opacity:1;transition-duration:0s;animation:founder-trace 1s linear .2s both}
@media (hover:hover){
  .founder-print:hover{animation:founder-orbit 1.15s cubic-bezier(.45,0,.3,1) both;transform:translate(-3px,-3px)}
  .founder-print:hover .founder-trace{opacity:1;transition-duration:0s;animation:founder-trace 1s linear .2s both}
}
@media (prefers-reduced-motion:reduce){
  .founder-print,.founder-print:hover,.founder-print.is-lit{animation:none;transform:none;transition:none}
  .founder-trace,.founder-print:hover .founder-trace,.founder-print.is-lit .founder-trace{animation:none;transition:none}
}

/* ---- motion/13-services.css ---- */
/* 13. Service drawings: each homepage service card carries a small line drawing from the motion catalogue.
   A lock lifts a boat (AI automation), a page lays itself out (Web development), a search finds a pin
   (Growth marketing). Each plays the first time its card is on screen and again on hover or keyboard
   focus (13-services.js adds .is-on). The static drawing is the finished state; .is-armed holds a
   drawing at its first frame, and is only ever set while that drawing is off screen.
   Markup: SERVICE_GLYPHS in scripts/art_showpieces.py. */
.service-name{display:grid;gap:14px;justify-items:start;align-content:start;min-width:0}
.service-glyph{display:block;width:88px;height:58px;overflow:visible}
.sg-line{fill:none;stroke:var(--ink);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.sg-line.sg-route{stroke:var(--rule);stroke-width:5}
.sg-line.sg-lens{fill:var(--paper)}
.sg-fill{fill:var(--ink)}
.sg-acc{fill:var(--accent)}
.sg-pin-shape{stroke:var(--ink);stroke-width:1.6}
.sg-water{fill:var(--water)}
.sg-rise{transform-box:fill-box;transform-origin:50% 100%;transform:scaleY(.8)}
.sg-frame{stroke-dasharray:1 2}
.sg-gate{transform:translateY(-14px)}
.sg-boat{transform:translate(34px,-10px)}
.sg-mag{transform:translate(46px,22px)}
@keyframes sg-draw{from{stroke-dashoffset:1.02}to{stroke-dashoffset:0}}
@keyframes sg-pop{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}
@keyframes sg-water{from{transform:scaleY(.35)}to{transform:scaleY(.8)}}
@keyframes sg-gate{from{transform:none}to{transform:translateY(-14px)}}
@keyframes sg-boat{0%{transform:none}45%,58%{transform:translate(0,-10px)}100%{transform:translate(34px,-10px)}}
@keyframes sg-mag{from{transform:translate(12px,30px)}to{transform:translate(46px,22px)}}
@keyframes sg-pin{from{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:no-preference){
  .service-glyph:is(.is-on,.is-armed) .sg-frame{animation:sg-draw .7s both}
  .service-glyph:is(.is-on,.is-armed) .sg-pop{animation:sg-pop .45s var(--d,0s) cubic-bezier(.3,1.5,.5,1) both}
  .service-glyph:is(.is-on,.is-armed) .sg-rise{animation:sg-water 1s .2s cubic-bezier(.2,.7,.3,1) both}
  .service-glyph:is(.is-on,.is-armed) .sg-gate{animation:sg-gate .5s 1.25s cubic-bezier(.3,1.4,.5,1) both}
  .service-glyph:is(.is-on,.is-armed) .sg-boat{animation:sg-boat 2.3s .2s cubic-bezier(.45,0,.25,1) both}
  .service-glyph:is(.is-on,.is-armed) .sg-mag{animation:sg-mag 1.3s cubic-bezier(.45,0,.2,1) both}
  .service-glyph:is(.is-on,.is-armed) .sg-pin{animation:sg-pin .6s 1.2s cubic-bezier(.3,1.6,.5,1) both}
  .service-glyph.is-armed :is(.sg-frame,.sg-pop,.sg-rise,.sg-gate,.sg-boat,.sg-mag,.sg-pin){animation-play-state:paused}
}
/* Phones: the drawing sits to the right of the service name. */
@media (max-width:760px){
  .service-name{grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:16px}
  .service-glyph{order:2;width:76px;height:50px}
}

/* ---- motion/14-journey.css ---- */
/* 14. The customer's journey: a freighter sails a canal route past three stops in the Growth marketing and
   Niagara SEO heroes (markup from scripts/art_local.py, JOURNEY). At rest the whole route is travelled and
   every stop is lit; 14-journey.js moves the boat and lights the stops as the page scrolls. The labels are
   a real HTML list under the drawing, one column per stop. */
.journey{width:100%;max-width:600px;min-width:0;justify-self:end}
.journey-art{display:block;width:100%;height:auto;overflow:visible}
.journey-bank{fill:none;stroke:var(--ink);stroke-width:9;stroke-linecap:round}
.journey-route{fill:none;stroke:var(--water);stroke-width:5;stroke-linecap:round}
/* The stretch already sailed, in deeper water. pathLength is 1, so the dash offset is the share still ahead. */
.journey-done{fill:none;stroke:var(--water-deep);stroke-width:5;stroke-linecap:round;stroke-dasharray:1 2;stroke-dashoffset:0}
.journey-post{fill:none;stroke:var(--ink);stroke-width:2;stroke-linecap:round;stroke-dasharray:.1 5}
.journey-stop circle{fill:var(--paper);stroke:var(--ink);stroke-width:2.5;transition:fill .35s ease}
.journey-stop.is-reached circle{fill:var(--accent)}
.journey-icon{fill:none;stroke:var(--ink);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.journey-stops{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));margin:12px 0 0;padding:0;list-style:none;text-align:center}
.journey-stops li{font:700 clamp(17px,1.85vw,24px)/1.2 var(--serif);letter-spacing:-.012em;color:var(--soft);transition:color .35s ease}
.journey-stops li.is-reached{color:var(--ink)}
.journey-stops li:last-child.is-reached{color:var(--accent-text)}
@media (max-width:760px){
  .journey{justify-self:stretch;max-width:520px}
  .journey-stops{margin-top:8px}
}
@media (max-width:420px){.journey-stops li{font-size:16px}}
@media (prefers-reduced-motion:reduce){.journey-stop circle,.journey-stops li{transition:none}}
/* Until 14-journey.js takes over (it adds .is-live), a page that will run it shows the script's first frame:
   the boat at the start of the route and no stop lit yet. So a script that arrives after the first paint never
   makes the boat jump back from the end of the route. .js is set by an inline script in the page head; without
   scripts, and under reduced motion, the whole route stays travelled. */
@media (prefers-reduced-motion:no-preference){
  .js .journey:not(.is-live) .journey-ship{transform:translate(30px,107px) rotate(-22.2deg) scale(.8)}
  .js .journey:not(.is-live) .journey-done{stroke-dashoffset:1.02}
  .js .journey:not(.is-live) .journey-stop circle{fill:var(--paper)}
  .js .journey:not(.is-live) .journey-stops li{color:var(--soft)}
}

/* ---- motion/15-map.css ---- */
/* 15. Your town on the canal: a stylized Niagara map beside the capabilities list on the three location
   pages (markup from scripts/art_local.py, canal_map()). The town names are buttons over the drawing:
   choosing one moves the marigold pin there. 15-map.js draws the canal and drops the pins the first time
   the map comes on screen, and sails a freighter along the canal while it is visible. */

/* Layout: on wider screens the capabilities list stacks beside the map, under the full-width heading. */
@media (min-width:761px){
  .capabilities.has-map{display:grid;grid-template-columns:minmax(0,1fr) minmax(280px,400px);column-gap:clamp(36px,6vw,96px);align-items:start}
  .capabilities.has-map>*{grid-column:1}
  .capabilities.has-map>h2{grid-column:1/-1}
  .capabilities.has-map>.canal-map{grid-column:2;grid-row:2/span 2;margin-top:44px}
  .capabilities.has-map .capability-list{grid-template-columns:minmax(0,1fr);gap:30px}
  .capabilities.has-map .capability-list p{max-width:60ch}
}
@media (max-width:760px){
  .capabilities.has-map>.canal-map{margin-top:40px;max-width:400px}
}

.canal-map{min-width:0}
.map-stage{position:relative;container-type:inline-size;padding:0;background:var(--sheet);border:2px solid var(--ink);border-radius:3px;box-shadow:8px 8px 0 var(--accent);overflow:hidden}
.map-art{display:block;width:100%;height:auto}
.canal-map figcaption{margin-top:16px;font-size:13px;font-style:italic;color:var(--soft)}

.map-lake{fill:var(--water);opacity:.5}
.map-lake-name{font:italic 12px var(--sans);fill:var(--ink)}
.map-water-name{font:italic 9.5px var(--sans);fill:var(--soft)}
.map-river{fill:none;stroke:var(--water);stroke-width:4;stroke-linecap:round}
.map-canal-bank,.map-canal{fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:1 2;stroke-dashoffset:0}
.map-canal-bank{stroke:var(--ink);stroke-width:6.5}
.map-canal{stroke:var(--water);stroke-width:3}
.map-dot{fill:var(--paper);stroke:var(--ink);stroke-width:1.8;transition:fill .25s ease}
.map-dot.is-pinned{fill:var(--ink)}

/* Pins: the marigold one moves; small ink ones mark the towns a page names and stay put. */
.map-pin-body path{stroke:var(--ink);stroke-width:1.6;stroke-linejoin:round}
.map-pin.is-primary .map-pin-body path{fill:var(--accent)}
.map-pin.is-also .map-pin-body path{fill:var(--ink);stroke:var(--paper);stroke-width:1.4}
.map-pin-eye{fill:var(--paper)}
.map-pin.is-also .map-pin-eye{fill:var(--accent)}
.map-pin.is-under{display:none}
.map-pulse{fill:none;stroke:var(--accent-text);stroke-width:1.5;opacity:0;transform-box:fill-box;transform-origin:center}

/* Town names: buttons placed on their dots. Each button also covers its dot, so the dot is tappable too. */
.map-towns{position:absolute;inset:0}
.map-town{position:absolute;left:var(--x);top:var(--y);display:inline-flex;align-items:center;min-height:30px;padding:2px 6px;border:0;border-radius:2px;background:transparent;color:var(--ink);font:600 clamp(12px,3.8cqw,15px)/1.1 var(--sans);white-space:nowrap;cursor:pointer;
  text-shadow:0 0 2px var(--paper),0 0 2px var(--paper),0 0 4px var(--paper)}
.map-town.is-start{padding-left:18px;transform:translate(-10px,-50%)}
.map-town.is-end{padding-right:18px;transform:translate(calc(-100% + 10px),-50%)}
.map-town[aria-pressed=true]{font-weight:800}
.map-town:hover,.map-town:focus-visible{text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px}
.map-town:focus-visible{outline:3px solid var(--ink);outline-offset:1px}

/* Motion. .is-armed is set only on maps that start below the screen, so they are complete at rest. */
@keyframes wg-map-draw{from{stroke-dashoffset:1.02}to{stroke-dashoffset:0}}
@keyframes wg-pin-drop{from{opacity:0;transform:translateY(-26px)}to{opacity:1;transform:none}}
@keyframes wg-map-fade{from{opacity:0}to{opacity:1}}
@keyframes wg-map-pulse{from{opacity:.85;transform:scale(1)}to{opacity:0;transform:scale(4)}}
@media (prefers-reduced-motion:no-preference){
  .canal-map.is-armed .map-canal-bank,.canal-map.is-armed .map-canal{stroke-dashoffset:1.02}
  .canal-map.is-armed .map-pin-body,.canal-map.is-armed .map-ship{opacity:0}
  .canal-map.is-drawing .map-canal-bank,.canal-map.is-drawing .map-canal{animation:wg-map-draw 1.8s cubic-bezier(.5,0,.3,1) both}
  .canal-map.is-drawing .map-pin-body{animation:wg-pin-drop .7s calc(1.45s + var(--pd,0s)) cubic-bezier(.3,1.6,.5,1) both}
  .canal-map.is-drawing .map-ship{animation:wg-map-fade .6s 1.5s both}
  .canal-map .map-pin.is-dropping .map-pin-body{animation:wg-pin-drop .6s cubic-bezier(.3,1.6,.5,1) both}
  .canal-map.is-live .map-pin.is-primary .map-pulse{animation:wg-map-pulse 2.2s 1s ease-out infinite}
}

/* ---- motion/16-bridge-up.css ---- */
/* 16. Bridge up on the 404 page: the span is raised, the BRIDGE UP sign's lamps flash, and the road
   barrier is down. Reaching for Back to home (hover, keyboard focus, or a tap) brings the span down,
   stops the lamps, and lifts the barrier (16-bridge-up.js sets .is-lowered). The lamps flash only while
   the sign is on screen (.is-live), and not at all under reduced motion.
   Markup: BRIDGE_UP in scripts/art_showpieces.py. */
.bridge-up{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:var(--gap);align-items:center}
.bu-copy .hero-description{max-width:46ch}
.bu-copy .button{margin-top:28px}
.bu-stage{min-width:0}
.bu-art{display:block;width:100%;max-width:640px;height:auto;margin-inline:auto;overflow:visible}
.bu-road{fill:none;stroke:var(--ink);stroke-width:5;stroke-linecap:round}
.bu-line{fill:none;stroke-width:6;stroke-linecap:round;stroke-linejoin:round}
.bu-line.bu-water{stroke:var(--water)}
.bu-echo{stroke:var(--accent);mix-blend-mode:multiply;opacity:.9}
.bu-ink{stroke:var(--ink)}
.bu-span{transform:translateY(-70px);transition:transform 1.2s cubic-bezier(.45,0,.2,1)}
.bu-post{fill:none;stroke:var(--ink);stroke-width:4;stroke-linecap:round}
.bu-plate{fill:var(--paper);stroke:var(--ink);stroke-width:3}
.bu-sign text{font:700 11.5px var(--sans);letter-spacing:.05em;fill:var(--ink);transition:opacity .4s}
.bu-lamp{fill:var(--accent);stroke:var(--ink);stroke-width:2}
.bu-barrier{transform-box:view-box;transform-origin:374px 574.5px;transition:transform .9s .25s cubic-bezier(.45,0,.2,1)}
.bu-arm{fill:var(--paper);stroke:var(--ink);stroke-width:2}
.bu-stripes{fill:none;stroke:var(--accent);stroke-width:5}
.bu-pivot{fill:var(--ink)}
@keyframes bu-blink{50%{fill:var(--paper)}}
@media (prefers-reduced-motion:no-preference){
  .bridge-up.is-live .bu-lamp{animation:bu-blink 1s steps(1) infinite}
  .bridge-up.is-live .bu-lamp-2{animation-delay:.5s}
}
/* The way is clear. */
.bridge-up.is-lowered .bu-span{transform:none}
.bridge-up.is-lowered .bu-lamp{animation:none;fill:var(--paper)}
.bridge-up.is-lowered .bu-sign text{opacity:.35}
.bridge-up.is-lowered .bu-barrier{transform:rotate(80deg)}
/* Phones: the drawing sits above the heading. */
@media (max-width:760px){
  .bridge-up{grid-template-columns:minmax(0,1fr);gap:20px}
  .bu-stage{grid-row:1}
  .bu-art{max-width:420px;margin-inline:0}
}

/* ---- motion/17-thank-you.css ---- */
/* 17. Through the last lock, on the thank-you page: once on load the chamber fills, the freighter rises,
   the marigold gate lifts, the freighter sails out, and the tick lands on the badge (17-thank-you.js).
   The markup is the finished state, which is also what reduced motion shows.
   Markup: THANK_YOU_LOCK in scripts/art_showpieces.py. */
.ty-hero{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:var(--gap);align-items:center}
.ty-copy .hero-description{max-width:46ch}
.ty-copy .button{margin-top:28px}
.ty-lock{min-width:0}
.ty-art{display:block;width:100%;max-width:520px;height:auto;margin-inline:auto;overflow:visible}
.ty-wall{fill:var(--wall)}
.ty-water{fill:var(--water);opacity:.9}
.ty-surf{fill:none;stroke:var(--paper);stroke-width:1.2;opacity:.75}
.ty-earth{fill:var(--earth)}
.ty-bed{fill:none;stroke:var(--ink);stroke-width:4;stroke-linejoin:round;stroke-linecap:round}
.ty-gate rect{fill:var(--ink)}
.ty-gate-up rect{fill:var(--accent)}
.ty-badge circle{fill:var(--accent);stroke:var(--ink);stroke-width:1.8}
.ty-tick{fill:none;stroke:var(--ink);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:1 2}
/* Until 17-thank-you.js takes over (it adds .is-live), a page that will run it shows the script's first frame:
   the chamber low, the freighter waiting in it, and the tick not yet drawn. So a script that arrives after the
   first paint never makes the freighter jump back into the chamber. .js is set by an inline script in the page
   head; without scripts, and under reduced motion, the finished drawing stays. */
@media (prefers-reduced-motion:no-preference){
  .js .ty-art:not(.is-live) .ty-chamber{transform-box:view-box;transform-origin:0 140px;transform:scaleY(.5714)}
  .js .ty-art:not(.is-live) .ty-surf{transform:translateY(30px)}
  .js .ty-art:not(.is-live) .ty-ship{transform:translate(140px,95.3px) scale(.8)}
  .js .ty-art:not(.is-live) .ty-tick{stroke-dashoffset:1.02}
}
/* Phones: the drawing sits above the heading. */
@media (max-width:760px){
  .ty-hero{grid-template-columns:minmax(0,1fr);gap:20px}
  .ty-lock{grid-row:1}
  .ty-art{max-width:400px;margin-inline:0}
}

/* ---- motion/20-hero-bridge.css ---- */
/* Homepage hero: the Welland lift bridge in two inks (spec section 5), replacing the old video ident.
   The marigold plate sits offset under the indigo and is multiplied, like a two-colour print slightly out
   of register. On load each line draws itself, the water follows, then the span lifts and settles back,
   once. 20-hero-bridge.js holds the drawing back only when the page opens scrolled past the hero.
   At rest and under reduced motion the drawing is complete with the span down.
   Markup: HERO_BRIDGE in scripts/art_showpieces.py. */
.hero-bridge{width:100%;max-width:540px;justify-self:center}
.hero-bridge-art{display:block;width:100%;height:auto;overflow:visible}
.hb-line{fill:none;stroke-width:6.5;stroke-linecap:round;stroke-linejoin:round}
.hb-ink{stroke:var(--ink)}
.hb-accent{stroke:var(--accent)}
.hb-echo{mix-blend-mode:multiply;opacity:.9}
.hb-line.hb-water{stroke:var(--water)}
/* pathLength="1": a dash of 1 and a gap of 2, starting just past 1, keeps round caps from showing as dots. */
.hb-draw{stroke-dasharray:1 2}
@keyframes hb-draw{from{stroke-dashoffset:1.02}to{stroke-dashoffset:0}}
@keyframes hb-lift{0%{transform:translateY(0)}30%,64%{transform:translateY(-38px)}100%{transform:translateY(0)}}
@media (prefers-reduced-motion:no-preference){
  .hero-bridge .hb-draw{animation:hb-draw var(--t,1.2s) var(--d,0s) cubic-bezier(.55,0,.25,1) both}
  .hero-bridge .hb-span{animation:hb-lift 2.8s 2.4s cubic-bezier(.45,0,.2,1) both}
}
/* Phones: the drawing sits above the headline, small enough that the headline stays on the first screen. */
@media (max-width:760px){
  .hero-bridge{grid-row:1;max-width:min(300px,78vw);justify-self:start;margin-bottom:6px}
}

/* ---- motion/21-lock.css ---- */
/* The canal lock on the AI automation page (spec section 6), ported from the approved preview
   (design/rebrand-preview/preview_template.html, round four). Five locks rise left to right; a freighter
   is lifted one step per lock, and the fourth gate (the review) is marigold. The step list is HTML under
   the drawing: one label under each lock on wide screens, stacked on phones. The markup is the finished
   state; 21-lock.js runs the simulation. Markup: LOCK_SECTION in scripts/art_showpieces.py. */
.lock-section{border-top:1px solid var(--rule)}
/* The heading uses the FAQ heading size, so its two lines stay clear of the third gate on wide screens. */
.lock-section h2{font-size:clamp(30px,3vw,38px)}
.lock-figure{max-width:1060px;margin:8px 0 0}
.cl-art{display:block;width:100%;height:auto;overflow:visible}
/* The viewBox starts at y -60, above the highest wall (18), so the raised gates fit, and the drawing moves
   up into that headroom so the staircase rises toward the heading. A raised gate lifts 72 units: gate 1
   (20% across) tops out at y 54, gate 2 (40%) at 20, gate 3 (60%) at -14, gate 4 (80%) at -48. A margin-top
   in % is a share of the figure's width, and the width is 600 units, so -1% moves the drawing up 6 units.
   Each rule puts the highest raised gate that can pass under the heading's text 8 to 20px below the
   heading, and no raised gate or the badge ever overlaps its text (measured from 360 to 1920 wide). */
/* Phones: the heading can run past gate 4, so gate 4's raised top (-48) sits 8px below the heading. */
.cl-art{margin-top:-2%}
/* Mid widths: the heading runs past gate 3, so gate 3's raised top (-14) sits 16px below the heading. */
@media (min-width:761px){
  .lock-figure{margin-top:16px}
  .cl-art{margin-top:-7.667%}
}
/* Wide screens: the heading ends before gate 3 (59% across), so gates 3 and 4 and the review badge rise
   beside it, and gate 2's raised top (20) sits 20px below the heading. */
@media (min-width:900px){
  .lock-figure{margin-top:20px}
  .cl-art{margin-top:-13.333%}
}

/* The drawing */
.cl-wallface{fill:var(--wall)}
.cl-masonry{fill:url(#cl-masonry)}
.cl-wet{fill:var(--ink);opacity:0}
.cl-coping{fill:none;stroke:var(--ink);stroke-width:2.2;stroke-linecap:round}
.cl-water{fill:url(#cl-water-fill);opacity:.92}
.cl-surf{fill:none;stroke:var(--paper);stroke-width:1.3;opacity:.75;stroke-linecap:round;stroke-linejoin:round}
.cl-rip{fill:none;stroke:var(--ink);stroke-width:1.1;opacity:.14;stroke-dasharray:9 9;stroke-linecap:round}
.cl-p-b{fill:var(--paper);opacity:.8}
.cl-p-d{fill:var(--water-deep)}
.cl-p-f{fill:var(--paper)}
.cl-splash{fill:none;stroke:var(--paper);stroke-width:1}
.cl-earth{fill:var(--earth)}
.cl-hatch-fill{fill:url(#cl-hatching)}
.cl-bed{fill:none;stroke:var(--ink);stroke-width:4.5;stroke-linejoin:round;stroke-linecap:round}
.cl-gate rect,.cl-gate-end rect{fill:var(--ink)}
.cl-gate .cl-rib,.cl-gate-end .cl-rib{fill:none;stroke:var(--paper);stroke-width:.9;opacity:.55}
.cl-gate.cl-yours rect{fill:var(--accent)}
.cl-gate.cl-yours .cl-rib{stroke:var(--ink);opacity:.45}
.cl-hull{fill:var(--ink)}
.cl-stripe{fill:none;stroke:var(--accent);stroke-width:1.6}
.cl-house{fill:var(--paper);stroke:var(--ink);stroke-width:1.6}
.cl-stack{fill:var(--accent);stroke:var(--ink);stroke-width:1}
.cl-win{fill:var(--ink)}
.cl-mast,.cl-hatch{fill:none;stroke:var(--ink);stroke-width:1.2;stroke-linecap:round}
/* The review badge: the ring fills while the job waits, then the tick lands and the disc turns marigold. */
.cl-ring{fill:none;stroke:var(--accent-text);stroke-width:2;stroke-dasharray:1 2;stroke-linecap:round}
.cl-disc{fill:var(--paper);stroke:var(--accent-text);stroke-width:1.6;transition:fill .3s}
.cl-tick{fill:none;stroke:var(--accent-text);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:1 2;transition:stroke .3s}
.lock-figure.is-approved .cl-disc{fill:var(--accent)}
.lock-figure.is-approved .cl-tick{stroke:var(--ink)}
@keyframes cl-pulse{from{opacity:1}to{opacity:.35}}
@media (prefers-reduced-motion:no-preference){
  .lock-figure.is-waiting .cl-gate.cl-yours rect{animation:cl-pulse .8s ease-in-out infinite alternate}
}

/* The steps, one under each lock */
.cl-steps{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));margin:14px 0 0;padding:0;list-style:none}
.cl-steps li{display:grid;gap:4px;align-content:start;padding:12px 12px 0 0;border-top:3px solid var(--rule);transition:border-color .3s}
.cl-steps li.is-done{border-top-color:var(--ink)}
.cl-steps li.is-active{border-top-color:var(--accent)}
.cl-n{font:700 13px/1.3 var(--sans);letter-spacing:.06em;color:var(--accent-text)}
.cl-t{font:500 15px/1.35 var(--sans);color:var(--ink)}
.cl-steps li.cl-yours .cl-t{font-weight:600;color:var(--accent-text)}

/* Caption, then the replay button under the figure (shown by 21-lock.js only when motion is welcome) */
.lock-figure figcaption{max-width:62ch;margin-top:22px;font-size:14px;line-height:1.55;color:var(--soft)}
.lock-figure figcaption span{font-weight:600;color:var(--ink)}
.cl-replay{display:inline-flex;align-items:center;min-height:44px;margin-top:18px;padding:8px 16px;border:2px solid var(--ink);border-radius:2px;background:transparent;color:var(--ink);font:600 14px/1 var(--sans);white-space:nowrap;transition:background-color .2s}
.cl-replay:hover,.cl-replay:focus-visible{background:var(--tint)}
.cl-replay[hidden]{display:none}

@media (max-width:640px){
  .cl-steps{grid-template-columns:minmax(0,1fr);gap:8px}
  .cl-steps li{grid-template-columns:24px minmax(0,1fr);padding:4px 0 4px 12px;border-top:0;border-left:3px solid var(--rule)}
  .cl-steps li.is-done{border-left-color:var(--ink)}
  .cl-steps li.is-active{border-left-color:var(--accent)}
}
