/* ============================================================
   Agentic Lens — agenticlens.co
   Warm monochrome from the brand board, one signal colour,
   engineered type. No shadows, no radius, no imagery.
   ============================================================ */

:root{
  --ink:#101010;
  --bone:#F6F2EA;
  --bone-raise:#FBF8F2;
  --sand:#D8D0C2;
  --muted:#4B453B;   /* darkened twice from #7B756C (Ivan, 14 Aug: darker, then darker still) */
  --signal:#2071B7;        /* cobalt (Ivan, 18 Aug; was terracotta #C4551F) */
  --signal-deep:#1A5C96;
  --signal-plate:#12426E;  /* the paper plate under the CTA, and its pressed shade */
  /* MERGE COMPLETED 18 Aug (Ivan: "it should be merged"): the ramp is
     re-derived in the cobalt hue (~208deg) so site and collateral carry
     ONE blue family, anchored on --signal. The old slate values came from
     the diorama's river; that river and the logo's slate are ART and are
     unchanged. Token names keep their roles: mist = light fill with ink
     text (11.6:1), river = line-work only (3.75:1 on bone, never body
     text), harbour = deep fill with bone text (6.2:1, same value as
     --signal-deep by design). */
  --mist:#B5CDE3;
  --mist-lift:#C2D8EB;   /* hover fill: the sheet lifting into light */
  --mist-pale:#D3E2EE;   /* selected cards, one step off the buttons */
  --river:#4C80AC;
  --harbour:#1A5C96;
  --forest:#2B4434;   /* dark bands: black stays in type only (Ivan, 14 Aug) */
  --ink-rule:rgba(246,242,234,.18);
  --ink-muted:rgba(246,242,234,.62);

  --font-sans:"Geist","Instrument Sans",-apple-system,"Helvetica Neue",Arial,sans-serif;
  --font-display:"Bricolage Grotesque",var(--font-sans);   /* headings only (14 Aug) */
  --font-mono:"JetBrains Mono",ui-monospace,"SF Mono",Menlo,monospace;

  --s1:8px;--s2:16px;--s3:24px;--s4:32px;--s5:48px;--s6:64px;--s7:96px;--s8:160px;
  --wrap:1240px;
  --measure:680px;
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

body{
  background:var(--bone);
  color:var(--ink);
  font:400 17px/28px var(--font-sans);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

::selection{background:var(--signal);color:var(--bone)}

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

h1,h2,h3{font-family:var(--font-display);letter-spacing:-.01em;text-wrap:balance}
h1{font-size:clamp(40px,6.2vw,76px);line-height:1.03;font-weight:700}
/* the hero's colour-wave word: mostly ink, a band of the brand's six
   colours sweeps through every few seconds */
.shimmer{
  /* wide ink margins: at rest (position 0% or 100%) the visible window
     sits entirely in ink, so no colour ever parks on the letter tails */
  background:linear-gradient(100deg,
    var(--ink) 0%, var(--ink) 36%,
    #2E4A38 42%, #7A93A8 46%, #C4551F 50%, #E7CB7F 54%, #9FB27E 58%,
    var(--ink) 64%, var(--ink) 100%);
  background-size:320% 100%;
  background-position:100% 0;
  -webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
  animation:shimmer 6.5s ease-in-out infinite;
}
@keyframes shimmer{
  0%{background-position:100% 0}
  55%{background-position:0% 0}
  100%{background-position:0% 0}
}
@media (prefers-reduced-motion: reduce){
  .shimmer{animation:none;background-position:50% 0}
}
h2{font-size:clamp(30px,3.6vw,44px);line-height:1.09;font-weight:700}
h3{font-size:clamp(21px,2vw,26px);line-height:1.23;font-weight:600;letter-spacing:-.01em}
.lede{font-size:20px;line-height:32px}
p+p{margin-top:var(--s3)}

a{color:inherit}
/* Content links warm to Harbour on hover (Path A). Scoped to prose so the
   wordmark and nav, which carry their own colours, are untouched. */
p a:hover,li a:hover,dd a:hover{color:var(--harbour)}
:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
section[data-tone="dark"] :focus-visible{outline-color:var(--bone)}

/* ---- labels: the mono voice ---------------------------------- */
.label{
  display:block;
  font:500 12px/16px var(--font-mono);
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
}
.label::before{content:"[ "}
.label::after{content:" ]"}
.label.bare::before,.label.bare::after{content:none}

/* ---- buttons -------------------------------------------------- */
.btn,.btn-2{
  display:inline-block;
  font:500 12px/16px var(--font-mono);
  letter-spacing:.14em;text-transform:uppercase;
  text-decoration:none;
  padding:18px 34px;
  border:1px solid transparent;
  /* The die-cut sticker (Ivan, 14 Aug): buttons ALONE carry an 8px
     corner — cut paper comes rounded when it's a sticker, and the plate
     underneath makes it a sticker stack. The zero-radius law still
     holds for everything else on the site. Plate and sheen follow the
     corner on their own (box-shadow + overflow both respect radius). */
  border-radius:8px;
  cursor:pointer;
  transition:background-color .18s ease,color .18s ease,border-color .18s ease;
}
/* The primary is a papercraft object (14 Aug): a hard offset plate behind
   it, zero blur, reads as a second sheet of cut paper, which is the one
   3D this system can honestly do; the zero-shadow law bans soft elevation,
   and this is a drawn edge, not a glow. The spring curve gives the bounce:
   hover lifts off the plate with a slight overshoot, press lands flush.

   Colour scheme "Mist except hero" (Ivan, 14 Aug): the default button is
   Mist over a Harbour plate with ink text; pressing commits to solid
   Harbour. The hero CTA alone carries the signal (cobalt, 18 Aug), so
   the accent appears exactly once per screen; the rocket keeps its
   terracotta as art.
   The plate colour rides on --plate so each scheme changes one line. */
.btn{
  /* plate one step deeper than the border, mirroring the collateral's
     signal/signalDeep/signalPlate stack */
  --plate:var(--signal-plate);
  position:relative;overflow:hidden;   /* clips the sheen strip; the plate is box-shadow, outside, unclipped */
  background:var(--mist);color:var(--ink);
  border-color:var(--harbour);
  font-size:13px;letter-spacing:.12em;
  /* optical centring: the trailing tracking space counts as a right pad */
  padding:19px 36px 19px calc(36px + .12em);
  box-shadow:4px 4px 0 0 var(--plate);
  transform:translate(0,0);
  transition:transform .2s cubic-bezier(.34,1.56,.64,1),
             box-shadow .2s cubic-bezier(.34,1.56,.64,1),
             background-color .18s ease,color .18s ease;
}
.btn:hover{
  background:var(--mist-lift);
  transform:translate(-1px,-2px);
  box-shadow:6px 7px 0 0 var(--plate);
}
.btn:active{
  background:var(--harbour);color:var(--bone);
  transform:translate(4px,4px);
  box-shadow:0 0 0 0 var(--plate);
  transition-duration:.09s;
}
/* the one signal button: the hero's */
.hero-ctas .btn{
  --plate:var(--signal-plate);
  background:var(--signal-deep);color:var(--bone);
  border-color:transparent;
}
.hero-ctas .btn:hover{background:#164C7C}
.hero-ctas .btn:active{background:#164C7C;color:var(--bone)}

/* Idle sheen (Ivan, 14 Aug): a light band crosses the button every ~7s,
   the attractor from his reference. Transform-only (no layout work),
   skewed to read as a glint, and NOT on the nav: a sticky header that
   glints on a timer is an eye-magnet in the wrong place. */
.btn:not(.btn-nav)::after{
  content:"";position:absolute;top:-2px;bottom:-2px;left:0;width:38%;
  background:linear-gradient(105deg,transparent 0%,rgba(255,255,255,.5) 50%,transparent 100%);
  transform:translateX(-140%) skewX(-18deg);
  animation:btn-sheen 7s ease-in-out infinite;
  pointer-events:none;
}
@keyframes btn-sheen{
  0%,80%{transform:translateX(-140%) skewX(-18deg)}
  94%,100%{transform:translateX(420%) skewX(-18deg)}
}
/* Unused in any page since the hero's second CTA went (13 Aug); kept as
   the ghost pattern, now in the river family per Path A. */
.btn-2{border-color:var(--river);color:var(--ink);background:transparent}
.btn-2:hover{box-shadow:inset 0 0 0 1px var(--river)}
@media (prefers-reduced-motion:reduce){
  .btn,.btn:hover,.btn:active{
    transform:none;
    box-shadow:4px 4px 0 0 var(--plate);
    transition:background-color .18s ease,color .18s ease;
  }
  .btn::after{animation:none;display:none}
}

/* ---- nav ------------------------------------------------------ */
.nav{
  position:sticky;top:0;z-index:40;
  background:rgba(246,242,234,.9);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  border-bottom:1px solid var(--sand);
}
.nav-inner{
  max-width:var(--wrap);margin:0 auto;
  display:flex;align-items:center;gap:var(--s4);
  padding:14px var(--s5);
}
.logo-mark{width:27px;height:27px}
/* Wordmark moved to Bricolage 14 Aug (Ivan), reversing the earlier
   "wordmark stays Geist" call in DESIGN.md. Needs weight 500 loaded for
   the "Lens" half, so the font link carries 500;600;700 on every page. */
.logo{
  font:700 20px/1 var(--font-display);
  letter-spacing:-.015em;
  text-decoration:none;color:#2E4A38;
  white-space:nowrap;
  display:inline-flex;align-items:center;gap:9px;
}
.logo em{font-style:normal;color:#B7C69B;font-weight:500}
.logo:hover em{color:var(--signal)}
.nav-links{margin-left:auto;display:flex;gap:var(--s4)}
.nav-links a{
  font:500 12px/16px var(--font-mono);
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);text-decoration:none;
  padding:6px 0;
}
.nav-links a:hover{color:var(--ink)}
.nav-links a[aria-current="page"]{color:var(--ink)}
.nav-links a[aria-current="page"]::before{content:"[ ";color:var(--signal)}
.nav-links a[aria-current="page"]::after{content:" ]";color:var(--signal)}
/* Nav stays at the label size with a shallower plate, so the header
   doesn't out-weigh the hero's CTA. */
.btn-nav{padding:12px 22px;margin-left:var(--s2);font-size:12px;letter-spacing:.14em;box-shadow:3px 3px 0 0 var(--plate)}
.btn-nav:hover{box-shadow:5px 6px 0 0 var(--plate)}
.btn-nav:active{box-shadow:0 0 0 0 var(--plate)}

.nav-toggle{
  display:none;
  margin-left:auto;
  background:none;border:1px solid var(--ink);
  font:500 12px/16px var(--font-mono);letter-spacing:.14em;text-transform:uppercase;
  padding:10px 16px;color:var(--ink);cursor:pointer;
}

/* mobile menu */
.menu{
  display:none;
  position:fixed;inset:0;z-index:50;
  background:var(--forest);color:var(--bone);
  padding:var(--s5);
  flex-direction:column;
}
.menu.open{display:flex}
.menu a{color:var(--bone);text-decoration:none}
.menu .menu-close{
  align-self:flex-end;
  background:none;border:1px solid var(--ink-rule);color:var(--bone);
  font:500 12px/16px var(--font-mono);letter-spacing:.14em;text-transform:uppercase;
  padding:10px 16px;cursor:pointer;
}
.menu nav{display:flex;flex-direction:column;gap:var(--s4);margin-top:var(--s7)}
.menu nav a{font-size:clamp(28px,8vw,44px);font-weight:700;letter-spacing:-.02em}
.menu .btn{margin-top:var(--s6);align-self:flex-start}

/* ---- sections ------------------------------------------------- */
section{padding:var(--s8) 0;border-bottom:1px solid var(--sand)}
section[data-tone="dark"]{
  background:var(--forest);color:var(--bone);
  border-bottom:none;
}
section[data-tone="dark"] .label{color:var(--ink-muted)}
section h2{margin-bottom:var(--s5)}
.section-label{margin-bottom:var(--s3)}

/* ---- hero ------------------------------------------------------ */
.hero{
  border-bottom:1px solid var(--sand);
  padding:calc(var(--s7) + 8px) 0 var(--s7);
  min-height:calc(100svh - 73px);
  display:flex;align-items:center;
}
.hero .wrap{width:100%} /* flex child would otherwise shrink to content and centre */

/* ---- the lens reveal ---------------------------------------------
   Layout by reservation: copy owns the left column, the scene stage owns
   the right. The plates are contain-fitted inside the stage, so the whole
   drawing is visible at every window size and can never collide with the
   copy. The blueprint's paper matches the page background, so the drawing
   reads as sitting on the same sheet. */
.reveal-hero{
  position:relative;overflow:hidden;
  /* leave room for the agents-deployed ribbon inside the first viewport,
     Corgi-style: nav (73) + hero + ribbon (~140) ≈ one screen */
  min-height:calc(100svh - 226px);
}
/* Layered world, Corgi-style. The FIELD is a stretchable backdrop with no
   content, so crops never matter. The CLUSTER (stations, stream, gate,
   rocket) is one positioned element with a size cap and a copy-safe left
   edge: it scales with the window but never crops, never inflates past
   its designed size, and can never collide with the copy. The torch
   canvas draws paper procedurally and places the blueprint cluster at
   the built cluster's measured DOM rect, so registration is correct by
   construction at every window size. */
.scene-stage{position:absolute;inset:0}
.reveal-hero{
  background-color:#9fb27e;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Crect width='100' height='100' fill='%239fb27e'/%3E%3Cpath d='M0 0 H100 V32 Q70 40 45 33 T0 36 Z' fill='%23a9bc89'/%3E%3Cpath d='M0 72 Q30 64 55 72 T100 69 V100 H0 Z' fill='%2393a672'/%3E%3C/svg%3E");
  background-size:100% 100%;
}
canvas.scene-torch{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.cluster-box{
  position:absolute;pointer-events:none;
  /* copy column right edge = max(50% + 148px, 768px); this keeps a
     constant 24px gap from it at every viewport width. The right edge
     aligns to the 1240px content column (the Get Started button's edge),
     and the box centres vertically against the copy — the art lives
     inside the same vertical rails as the nav, not in the viewport
     corner. */
  left:max(calc(50% + 172px), 792px);
  right:max(calc(50% - 572px), 24px);  /* = the Get Started button's right edge */
  top:12px;bottom:12px;
  max-height:800px;                    /* caps the cluster below its designed size */
  margin-top:auto;margin-bottom:auto;  /* vertical centring within the stage */
}
.scene-under{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;object-position:right center;
  pointer-events:none;
}
.hero-copy{position:relative;z-index:2}
.hero-copy-inner{max-width:720px}
.hero-copy-inner .lede{max-width:520px}
/* short viewports (MacBook): compress the copy stack so the ribbon
   stays inside the first screen instead of being pushed below it */
/* Mobile hero (Ivan, 13 Aug): the built world sits ABOVE the copy,
   already revealed — the torch is a cursor mechanic, so phones get the
   destination, not the drawing. The stamp stays below the copy as the
   works-drawing flavour. */
@media (max-width: 860px){
  .reveal-hero{display:flex;flex-direction:column;min-height:0}
  .scene-stage{position:relative;inset:auto;order:-1;height:auto;padding:20px 0 0}
  canvas.scene-torch{display:none}
  .cluster-box{
    position:relative;inset:auto;max-height:none;margin:0 auto;
    width:min(88vw, 480px);
  }
  .scene-under{
    display:block;   /* inline img leaves a baseline gap; the fx layer then oversizes */
    position:relative;inset:auto;width:100%;height:auto;
    aspect-ratio:770/850;object-position:center;
  }
}

@media (max-height: 1000px){
  .reveal-hero{padding-top:var(--s5);padding-bottom:var(--s5)}
  .reveal-hero h1{font-size:clamp(40px, min(6.2vw, 8.2svh), 76px)}
  .dwg-stamp{margin-top:var(--s4)}
}
@media (max-height: 820px){
  .reveal-hero{padding-top:var(--s4);padding-bottom:var(--s4)}
  .reveal-hero h1{font-size:clamp(36px, min(6.2vw, 7svh), 76px);margin-bottom:var(--s3)}
  .reveal-hero .lede{font-size:18px;line-height:28px}
  .reveal-hero .hero-ctas{margin-top:var(--s3)}
  .dwg-stamp{margin-top:var(--s3)}
  .dwg-row{padding:6px 12px}
  section.deployed{padding:var(--s3) 0 var(--s4)}
}
@media (max-width: 900px){
  .cluster-box{
    position:relative;left:auto;right:auto;top:auto;bottom:auto;
    width:min(92%, 520px);aspect-ratio:770/850;
    margin:var(--s5) auto 0;
  }
  .scene-under{object-position:center bottom}
}

/* the works-drawing stamp, in-flow below the CTAs */
.dwg-stamp{
  margin-top:var(--s6);max-width:420px;
  transition:opacity .35s linear;
  border:1.5px solid var(--muted);background:var(--bone);
  font:500 11px/16px var(--font-mono);
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
}
.dwg-row{display:flex;justify-content:space-between;gap:var(--s3);padding:9px 14px;border-top:1px solid var(--muted)}
.dwg-row:first-child{border-top:0}
.dwg-head{color:var(--ink);font-size:12px;letter-spacing:.16em}
.hero-grid{
  display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);
  gap:var(--s7);align-items:center;
}
.hero h1{margin-bottom:var(--s4)}
.hero .lede{color:var(--muted);max-width:520px}
.hero-ctas{margin-top:var(--s6);display:flex;flex-wrap:wrap;gap:var(--s2)}

/* ---- the signature: living system diagram --------------------- */
.diagram{width:100%;height:auto;display:block}
.diagram text{
  font:500 11px var(--font-mono);
  letter-spacing:.12em;
  fill:var(--muted);
}
.diagram .node{fill:var(--bone-raise);stroke:var(--sand);stroke-width:1}
.diagram .node-you{stroke:var(--signal);stroke-width:1.5}
.diagram .node-you-label{fill:var(--signal)}
.diagram .pipe{fill:none;stroke:var(--sand);stroke-width:1}
.diagram .pipe-flow{
  fill:none;stroke:var(--signal);stroke-width:1.5;
  stroke-dasharray:3 9;
  animation:flow 1.6s linear infinite;
}
.diagram .pipe-learn{fill:none;stroke:var(--sand);stroke-width:1;stroke-dasharray:2 5}
.diagram .pulse{fill:var(--signal)}
.diagram .caption{fill:var(--ink);font-weight:500;letter-spacing:.14em}
@keyframes flow{to{stroke-dashoffset:-12}}
@media (prefers-reduced-motion:reduce){
  .diagram .pipe-flow{animation:none;stroke-dasharray:none;opacity:.5}
  .diagram .dot{display:none}
}

/* ---- recent projects boxes ------------------------------------ */
.boxes{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s5)}
.box{border-top:2px solid var(--signal);padding-top:var(--s3)}
.box .label{margin-bottom:var(--s3)}
.box h3{margin-bottom:var(--s2)}
.box p{color:var(--ink-muted)}
section:not([data-tone="dark"]) .box p{color:var(--muted)}

/* ---- hero sub, second beat ------------------------------------- */
.lede-2{display:block;margin-top:var(--s2)}

/* ---- agents deployed marquee ------------------------------------ */
.deployed{padding:var(--s4) 0 var(--s5);border-bottom:1px solid var(--sand)}
.deployed-label{text-align:center;margin-bottom:var(--s3)}
.marquee{
  overflow:hidden;
  position:relative;
}
/* Edge fades as bone-coloured overlays, NOT mask-image. A mask applied
   across an animated transform is repaint-fragile: browsers intermittently
   stop painting the newly revealed right edge until the loop resets (the
   "right side goes blank, then snaps back" bug, Ivan 14 Aug). Overlays
   paint on top and never interact with the animation. Identical look,
   because the section background is flat bone. */
.marquee::before,.marquee::after{
  content:"";position:absolute;top:0;bottom:0;width:10%;
  pointer-events:none;z-index:1;
}
.marquee::before{left:0;background:linear-gradient(90deg,#F6F2EA,#F6F2EA00)}  /* --bone */
.marquee::after{right:0;background:linear-gradient(270deg,#F6F2EA,#F6F2EA00)}
/* will-change promotes the track to its own layer, so the whole strip is
   rasterised once and scrolled as a texture instead of painted on demand,
   the other half of the same repaint bug. */
.marquee-track{display:flex;width:max-content;animation:marquee 36s linear infinite;will-change:transform}
.marquee:hover .marquee-track{animation-play-state:paused}
.marquee-group{display:flex;gap:var(--s7);padding-right:var(--s7)}
.dep{
  display:flex;align-items:center;gap:12px;white-space:nowrap;
  font:500 12px/16px var(--font-mono);
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);
}
.dep-mark{
  width:60px;height:60px;flex:none;
  object-fit:cover;
}
@keyframes marquee{to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){
  .marquee-track{animation:none;will-change:auto}
  .marquee{overflow-x:auto}
  /* Manual scroll: the edge fades would sit over the strip's real ends
     and make the first and last items look cut off, so drop them. */
  .marquee::before,.marquee::after{display:none}
}

/* ---- the four phases (one week each) --------------------------- */
.brand-inline{font-weight:700;color:#2E4A38}
.brand-inline em{font-style:normal;color:#B7C69B}
.phases-intro{margin-top:var(--s5);color:var(--muted)}
.phases .label{white-space:nowrap}
.phases{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s5);margin-top:var(--s6)}
@media (max-width:1100px){.phases{grid-template-columns:1fr 1fr}}
@media (max-width:640px){.phases{grid-template-columns:1fr}}

/* ---- the two doors --------------------------------------------- */
.doors{display:grid;grid-template-columns:1fr 1fr;gap:var(--s6);margin-top:var(--s6)}
.doors .box h3{margin-bottom:var(--s2)}
@media (max-width:900px){.doors{grid-template-columns:1fr}}

/* ---- phases ---------------------------------------------------- */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s5)}
.step{border-top:1px solid var(--sand);padding-top:var(--s3)}
.step .label{margin-bottom:var(--s2)}
.step h3{margin-bottom:var(--s2)}
.step p{color:var(--muted)}
.give{
  display:block;
  font:500 12px/16px var(--font-mono);
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--signal);
  margin:var(--s3) 0 var(--s1);
}
.step .get{color:var(--ink)}

/* ---- faq ------------------------------------------------------- */
.faq{list-style:none}
.faq li{padding:var(--s4) 0;border-top:1px solid var(--sand)}
section[data-tone="dark"] .faq li{border-top-color:var(--ink-rule)}
.faq h3{margin-bottom:var(--s1)}
.faq p{color:var(--muted)}
section[data-tone="dark"] .faq p{color:var(--ink-muted)}

/* ---- close band ------------------------------------------------ */
.close-band h2{margin-bottom:var(--s5)}
.close-note{margin-top:var(--s3);color:var(--ink-muted)}
.close-note a{color:inherit}

/* ---- about ------------------------------------------------------ */
/* Default is the no-portrait state, so the page is correct today and in
   any browser that does not support :has(). Drop a .portrait back into
   .bio and the two-column layout returns with no other edit. Capping the
   width matters here: with one column the bio would otherwise run the
   full 1240px wrap, far past a readable measure. */
.bio{display:grid;grid-template-columns:1fr;gap:var(--s7);align-items:start;max-width:680px}
.bio:has(.portrait){grid-template-columns:2fr 3fr;max-width:none}
.portrait{
  aspect-ratio:4/5;
  background:var(--sand);
  display:flex;align-items:center;justify-content:center;
}
.portrait span{font:500 12px/16px var(--font-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
.bio h2{margin-bottom:var(--s4)}
.bio .sig{margin-top:var(--s4);color:var(--muted)}

.cert{display:flex;align-items:center;justify-content:center;gap:var(--s6);padding:var(--s2) 0}
/* Without the badge the block is a lone text column, so centre the text
   too or it reads as accidentally off-centre. Reverts on its own once a
   .badge is present again. */
.cert:not(:has(.badge)){text-align:center}
.badge{
  width:128px;height:128px;flex:none;
  border:1px solid var(--sand);
  display:flex;align-items:center;justify-content:center;text-align:center;
  font:500 11px/16px var(--font-mono);letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);padding:var(--s1);
}
.cert h3{margin-bottom:4px}
.cert p{color:var(--muted)}

.tools{display:grid;grid-template-columns:repeat(6,1fr);gap:var(--s6) var(--s4)}
.tool{text-align:center}
.tool .mark{
  height:48px;margin:0 auto var(--s2);
  display:flex;align-items:center;justify-content:center;
}
.tool .mark img{max-height:34px;max-width:110px;width:auto;height:auto}
.tool span{font:500 12px/16px var(--font-mono);letter-spacing:.08em;color:var(--muted)}

/* ---- forms ------------------------------------------------------ */
.field{margin-bottom:var(--s4)}
.field>label{
  display:block;
  font:500 12px/16px var(--font-mono);
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);margin-bottom:var(--s1);
}
.field input,.field textarea,.field select{
  width:100%;
  padding:16px;
  border:1px solid var(--sand);
  background:var(--bone-raise);
  font:400 17px/26px var(--font-sans);
  color:var(--ink);
  border-radius:0;
  appearance:none;-webkit-appearance:none;
}
.field select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%237B756C' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 16px center;
  padding-right:44px;
}
.field input:focus,.field textarea:focus,.field select:focus{
  outline:2px solid var(--ink);outline-offset:0;border-color:var(--ink);
}
.field textarea{min-height:140px;resize:vertical}
.field ::placeholder{color:var(--muted);opacity:.75}
.two{display:grid;grid-template-columns:1fr 1fr;gap:0 var(--s4)}
/* Keep the two controls on a row bottom-aligned when one label wraps to
   two lines and its neighbour does not. Grid already makes the cells equal
   height; this pushes the input to the foot of the cell instead of letting
   it float up under a short label. Robust to any label length, so copy can
   change without reopening this. */
.two>.field{display:flex;flex-direction:column}
.two>.field>label{flex:1 0 auto}
.form-group{margin:var(--s6) 0 var(--s3)}
.checks{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
.checks label{
  display:flex;gap:var(--s2);align-items:center;
  border:1px solid var(--sand);
  background:var(--bone-raise);
  padding:16px;cursor:pointer;
  font:400 16px/24px var(--font-sans);
}
.checks label:hover{border-color:var(--muted)}
/* .field input (above) strips native rendering with appearance:none, which
   on a checkbox removes the tick ENTIRELY: state changes invisibly and the
   control reads as broken (caught by Ivan, 14 Aug). Restore the native
   checkbox here, and mark the whole card when selected so the state is
   unmissable. */
.checks input{
  appearance:auto;-webkit-appearance:checkbox;
  width:16px;height:16px;flex:none;padding:0;
  accent-color:var(--harbour);
}
/* Selected state in the river family (Path A): the signal is reserved for
   the CTA, and Mist under ink text (11.7:1) reads chosen, not alarmed. */
.checks label:has(input:checked){
  border-color:var(--harbour);
  box-shadow:inset 0 0 0 1px var(--harbour);
  /* one step paler than the buttons, so "chosen" and "act" never share
     a fill now that the buttons themselves are Mist */
  background:var(--mist-pale);
}
.form-error{display:none;color:var(--signal-deep);font:500 14px/22px var(--font-sans);margin-bottom:var(--s3)}
.form-error.show{display:block}

/* Honeypot: present in the DOM for bots, gone for people and for
   screen readers (the wrapper carries aria-hidden). */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.calendar-slot{
  margin-top:var(--s5);
  /* was the dark-band bone-alpha pair, near-invisible on bone; the river
     line (Path A) is the fix as well as the palette move */
  border:1px solid var(--river);
  padding:var(--s7) var(--s4);
  text-align:center;
  font:500 12px/16px var(--font-mono);letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);
}

/* Live booking embed. Zero radius per the site convention; the rule
   stays so the calendar reads as a drawn panel, not a floating widget. */
.booking-mounted{
  margin-top:var(--s5);
  border:1px solid var(--river);
  max-width:900px;
}
/* Tall enough that Google's own content rarely needs its own scrollbar.
   A nested scroll region inside a scrolling page is the thing to avoid,
   and it bites hardest on mobile where the month grid stacks. */
.booking-frame{
  display:block;
  width:100%;
  height:860px;
  border:0;
}
@media (max-width:860px){
  .booking-frame{height:1050px}
}

/* ---- FA page ---------------------------------------------------- */
.moments{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s5)}
.moments .box ul{list-style:none;margin-top:var(--s2)}
.moments .box li{padding:6px 0 6px 18px;position:relative;color:var(--ink-muted)}
.moments .box li::before{content:"—";position:absolute;left:0;color:var(--muted)}
.plain-list{list-style:none;margin-top:var(--s5)}
.plain-list li{padding:var(--s4) 0;border-top:1px solid var(--sand)}
section[data-tone="dark"] .plain-list li{border-top-color:var(--ink-rule)}
.plain-list h3{margin-bottom:var(--s1)}
.plain-list p{color:var(--muted)}
section[data-tone="dark"] .plain-list p{color:var(--ink-muted)}
.todo{color:var(--signal-deep)}
.boundary{margin-top:var(--s6)}

/* ---- resources holding ------------------------------------------ */
.holding{min-height:62vh;display:flex;align-items:center;border-bottom:1px solid var(--sand)}

/* ---- footer ------------------------------------------------------ */
footer{
  padding:var(--s5) 0;
  font:500 12px/16px var(--font-mono);
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);
}

/* ---- reveals ------------------------------------------------------
   Hidden state only applies once main.js has stamped .js on <html>,
   so content is never invisible without JavaScript. */
html.js .reveal{opacity:0;transform:translateY(8px);transition:opacity .45s ease-out,transform .45s ease-out}
html.js .reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  html.js .reveal{opacity:1;transform:none;transition:none}
}

/* ---- responsive --------------------------------------------------- */
@media (max-width:1024px){
  .boxes{grid-template-columns:1fr 1fr}
  .steps{grid-template-columns:1fr 1fr;row-gap:var(--s6)}
  .tools{grid-template-columns:repeat(4,1fr)}
  .moments{grid-template-columns:1fr 1fr}
}
@media (max-width:900px){
  .nav-links,.btn-nav{display:none}
  .nav-toggle{display:block}
  .hero{min-height:0}
  .hero-grid{grid-template-columns:1fr;gap:var(--s6)}
  .hero-visual{max-width:480px}
  .bio{grid-template-columns:1fr;gap:var(--s5)}
  .portrait{max-width:380px}
  .cert{flex-direction:column;text-align:center;gap:var(--s4)}
}
@media (max-width:640px){
  .wrap{padding:0 var(--s3)}
  .nav-inner{padding:14px var(--s3)}
  section{padding:var(--s6) 0}
  .hero{padding:var(--s6) 0}
  .boxes,.steps,.two,.checks,.moments{grid-template-columns:1fr}
  .tools{grid-template-columns:repeat(2,1fr)}
  .hero-ctas .btn,.hero-ctas .btn-2{width:100%;text-align:center}
}

/* ---- scene fx: the world breathes (Ivan, 14 Aug) ----------------
   Additive layers over the built plate, inside the same box, below the
   torch canvas. The container mirrors the img's contain fit (right/
   bottom anchored, 770:850), so every % position is art-space. */
.scene-fx{
  position:absolute;right:0;bottom:0;height:100%;
  aspect-ratio:770/850;
  pointer-events:none;
}
@keyframes glide{to{stroke-dashoffset:-462}}
@keyframes pondspin{to{stroke-dashoffset:-320}}
@keyframes pondglow{0%,100%{opacity:.12}50%{opacity:.5}}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-1.7%)}}
@keyframes bob{0%,100%{transform:translateY(1.2%)}50%{transform:translateY(-3%)}}
.fx-flies .bfly{position:absolute;width:3.2%;aspect-ratio:10/7;overflow:visible}
.fx-flies .b1{left:31%;top:37%;animation:fly1 17s ease-in-out infinite}
.fx-flies .b2{left:39%;top:42%;animation:fly2 13s ease-in-out infinite}
.fx-flies .b3{left:26%;top:45%;animation:fly3 21s ease-in-out infinite}
.bfly .wing{fill:#E7CB7F;stroke:#C9A85C;stroke-width:.6}
.bfly .wl{transform-origin:10px 7px;animation:flapL .5s ease-in-out infinite alternate}
.bfly .wr{transform-origin:10px 7px;animation:flapR .5s ease-in-out infinite alternate}
@keyframes flapL{from{transform:scaleX(1)}to{transform:scaleX(.35)}}
@keyframes flapR{from{transform:scaleX(.35)}to{transform:scaleX(1)}}
@keyframes fly1{0%,100%{transform:translate(0,0)}25%{transform:translate(320%,-170%)}50%{transform:translate(140%,-430%)}75%{transform:translate(-190%,-150%)}}
@keyframes fly2{0%,100%{transform:translate(0,0)}30%{transform:translate(-260%,-240%)}60%{transform:translate(200%,-330%)}}
@keyframes fly3{0%,100%{transform:translate(0,0)}20%{transform:translate(240%,120%)}55%{transform:translate(420%,-260%)}80%{transform:translate(90%,-380%)}}
@media (prefers-reduced-motion:reduce){
    }
@media (max-width:860px){
  .dwg-stamp{display:none}   /* no works-drawing box on mobile (Ivan, 14 Aug) */
}

/* ---- FA page: the agents (Yui-shaped, our spine) ---------------- */
.agent-index{
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);
  margin-top:var(--s5);padding-bottom:var(--s3);
  border-bottom:1px solid var(--sand);
}
.agent-index a{
  font:500 12px/16px var(--font-mono);letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);text-decoration:none;padding:6px 0;
}
.agent-index a:hover{color:var(--ink)}
.agent-index a::before{content:"[ "}
.agent-index a::after{content:" ]"}
article.agent{
  display:grid;grid-template-columns:1fr 1fr;gap:var(--s6);
  align-items:start;
  padding-top:var(--s6);margin-top:var(--s6);
  border-top:2px solid var(--signal);
  scroll-margin-top:96px;
}
article.agent.flip .agent-copy{order:2}
article.agent.flip .chat{order:1}
.agent-head{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s3)}
.agent-head img{flex:none}
.agent-head .label{margin:0}
article.agent h3{margin-bottom:var(--s2)}
.agent-gets{list-style:none;margin-top:var(--s3)}
.agent-gets li{
  padding-left:22px;position:relative;
  color:var(--muted);margin-top:8px;
}
.agent-gets li::before{
  content:"";position:absolute;left:0;top:9px;
  width:10px;height:10px;border:1px solid var(--signal);
}
.chat{
  background:var(--bone-raise);border:1px solid var(--sand);
  padding:var(--s3);
  font-size:15px;line-height:24px;
}
.chat-head{
  font:500 11px/16px var(--font-mono);letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);margin-bottom:var(--s2);
  padding-bottom:var(--s2);border-bottom:1px solid var(--sand);
}
.chat .msg{max-width:88%;padding:10px 14px;margin-top:10px}
.chat .msg.agent{background:var(--bone);border:1px solid var(--sand);margin-right:auto}
.chat .msg.you{background:#E9E4D8;margin-left:auto;text-align:left}
.chat-cap{
  margin-top:var(--s2);
  font:500 10px/16px var(--font-mono);letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);text-align:right;
}
.flow{
  grid-column:1 / -1;
  display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;
  margin-top:var(--s3);padding-top:var(--s3);
  border-top:1px solid var(--sand);
}
.flow .chip{
  font:500 11px/16px var(--font-mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);
  border:1px solid var(--sand);padding:7px 10px;background:var(--bone-raise);
  white-space:nowrap;
}
.flow .chip.gate{color:var(--bone);background:var(--signal-deep);border-color:var(--signal-deep)}
.flow .arr{color:var(--sand)}
@media (max-width:900px){
  article.agent{grid-template-columns:1fr;gap:var(--s4)}
  article.agent.flip .agent-copy{order:1}
  article.agent.flip .chat{order:2}
  .flow{align-items:stretch}
  .flow .chip{white-space:normal}
}
