/* =========================================================================
   The Kinetic shell: every page of v2 shares this file.

   It was inline in kinetic/index.html, which was fine for one page and wrong
   for fifteen: 48KB of shell per page, copied, and fifteen copies to keep in
   step. The live site works that way and it is exactly why its Spanish mirror
   drifts from the English one. One file, linked, no build step.
   ========================================================================= */
/* =========================================================================
   CONCEPT: "Kinetic"  -  a site that moves sideways.

   Third pass. The note was that it read like a PowerPoint deck, which it did,
   and for structural reasons rather than cosmetic ones: eight sealed boxes of
   identical size, hard-snapped so you could never rest between them, each
   opening with the same kicker-then-headline beat.

   What changed, in order of how much it matters:

   1. ONE SCREEN PER SECTION, EXACTLY. Every section is 100vw and all of its
      content fits in one screen - nothing is scrolled through twice, and at
      rest you never see part of the next section alongside the one you are
      reading. Uneven widths were tried (74vw to 138vw) to stop the viewport
      edge reading as a frame; the cost was that the track almost never lined
      up, so every resting position showed two half-sections.
   2. THE TRAVEL IS REAL, EVEN THOUGH IT LANDS SQUARE. A gesture scrolls the
      track continuously and it decelerates - you watch the sections move past
      rather than cutting between them - and it finishes by settling onto a
      section. The settle uses the same easing as the gesture, so it reads as
      the movement completing, not as the page correcting you. What a deck
      does, and this does not, is teleport between fixed states with the travel
      removed.
   3. ONE CONTINUOUS GROUND. A single background across the whole track and a
      khipu cord running its entire length, knotting at each section. The cord
      is the thing that makes it one canvas instead of eight cards, and it is
      on the nose for a company named after knotted Andean record-keeping.
   4. CONTENT SITS AT DIFFERENT HEIGHTS. Top, middle, bottom, offset. A deck
      centres everything; a page does not.
   5. LAYERS MOVE AT DIFFERENT RATES, so the composition rearranges as you go
      rather than cutting between fixed states.
   ========================================================================= */
:root{
  /* --dim was #6D8294, which cleared 4.76:1 on the old flat background but
     only 4.29:1 once the ground became a gradient with lighter passages. It
     carries the legal line and the results caveat, so it has to clear on the
     LIGHTEST tone, not the average. */
  --bg:#0A1119; --ink:#F4EFE7; --muted:#93A7B4; --dim:#7A94A6;
  --line:#22323E; --copper:#E39767; --hot:#FF7A3D; --green:#4FBF95;
}
*{box-sizing:border-box;}
html,body{height:100%;margin:0;overflow:hidden;}
body{background:var(--bg);color:var(--ink);
  font-family:'DM Sans',-apple-system,"Segoe UI",sans-serif;font-size:16px;line-height:1.45;
  -webkit-font-smoothing:antialiased;}
h1,h2,h3{margin:0;font-family:'Manrope','DM Sans',sans-serif;line-height:.94;
  letter-spacing:-.045em;font-weight:800;text-transform:uppercase;}
em{font-family:'Instrument Serif',Georgia,serif;font-style:italic;text-transform:none;
  letter-spacing:-.01em;font-weight:400;}
a{color:inherit;text-decoration:none;}
:focus-visible{outline:2px solid var(--hot);outline-offset:3px;}

/* The ground sits on the body so the scrolling track can stay transparent. */
body{background:
  radial-gradient(120% 90% at 20% 0%, #0E1A24 0%, transparent 60%),
  radial-gradient(120% 90% at 85% 100%, #101D28 0%, transparent 55%),
  #0A1119;}

/* ---- the track is one long canvas, not a stack of cards ---- */
/* 100dvh after 100vh throughout: on a tablet browser 100vh is the height with
   the toolbars hidden, so a screen sized to it ran its bottom edge - the proof
   strip, the ticker - under the toolbar. dvh is the height actually visible.
   On a desktop the two are the same number; browsers without dvh keep vh. */
.track{position:relative;z-index:1;display:flex;height:100vh;height:100dvh;overflow-x:auto;overflow-y:hidden;
  /* CSS snapping and smooth scroll-behavior are both off on purpose. The settle
     is done in JS so it can be directional - a deliberate gesture advances
     rather than being pulled back to where it started - and CSS snap would
     fight that by re-pulling the position the moment the easing slows.
     scroll-behavior:smooth would animate every scrollLeft write, turning the JS
     easing into a rubber band and a drag into a lag. */
  cursor:grab;background:transparent;}
.track.dragging{cursor:grabbing;}
.track::-webkit-scrollbar{display:none;}
.track{scrollbar-width:none;}

/* The cord: one continuous line through the entire site, drifting slower than
   the content so the two never feel locked together.
   It lives in a FIXED layer, deliberately outside the scroll container. Inside
   it, the parallax transform extended the track's scrollable area, so the
   scrollWidth grew as you scrolled (12,028px to 12,894px) and the end of the
   site kept receding as you approached it. */
.cordwrap{position:fixed;inset:0;overflow:hidden;z-index:0;pointer-events:none;}
.cordwrap::before{content:"";position:absolute;inset:0;
  background:
    linear-gradient(180deg,rgba(5,12,18,.68) 0%,rgba(5,12,18,.42) 48%,rgba(5,12,18,.7) 100%),
    linear-gradient(90deg,rgba(5,12,18,.48),transparent 42%,rgba(5,12,18,.28)),
    url('./assets/mountain-range-backdrop-v1.webp') center bottom/cover no-repeat;
  opacity:.86;filter:saturate(.9) contrast(1.02);}
.cord{position:absolute;left:0;top:0;height:100%;will-change:transform;z-index:1;}

.panel{position:relative;z-index:1;height:100vh;height:100dvh;width:100vw;
  padding:128px 5vw 104px;display:flex;flex-direction:column;flex:0 0 auto;}
.panel:not(.p-start) .say,.panel:not(.p-start) .kick,
.panel:not(.p-start) .sub{position:relative;text-shadow:0 2px 18px rgba(0,0,0,.55);}
/* Content sits at a different height in each section. A deck centres
   everything; this is what stops the eye settling into a rhythm. */
.panel.at-top{justify-content:flex-start;padding-top:158px;}
.panel.at-mid{justify-content:center;}
.panel.at-low{justify-content:flex-end;padding-bottom:150px;}

/* ---- reveal: content arrives as its section comes into view ---- */
[data-rv]{opacity:0;transform:translateY(20px);
  transition:opacity .66s cubic-bezier(.16,.8,.28,1),transform .66s cubic-bezier(.16,.8,.28,1);}
.live [data-rv]{opacity:1;transform:none;}
.live [data-rv]:nth-child(1){transition-delay:.02s;}
.live [data-rv]:nth-child(2){transition-delay:.08s;}
.live [data-rv]:nth-child(3){transition-delay:.14s;}
.live [data-rv]:nth-child(4){transition-delay:.20s;}
.live [data-rv]:nth-child(5){transition-delay:.26s;}
.live [data-rv]:nth-child(6){transition-delay:.32s;}

/* ---- fixed chrome ---- */
.skip{position:fixed;left:16px;top:-80px;z-index:100;background:var(--ink);color:var(--bg);
  padding:10px 14px;border-radius:4px;font-family:'Manrope',sans-serif;font-weight:800;}
.skip:focus{top:12px;}
.hd{position:fixed;inset:0 0 auto 0;z-index:60;display:flex;align-items:center;gap:28px;
  min-height:82px;padding:20px 4.8vw;color:var(--ink);
  background:linear-gradient(180deg,rgba(5,13,20,.82),rgba(5,13,20,0));}
.hd .bd{display:flex;align-items:center;gap:10px;font-family:'Manrope',sans-serif;
  font-weight:800;letter-spacing:.18em;font-size:.98rem;}
.hd .bd img{width:30px;height:30px;border-radius:6px;}
.hd nav{margin-left:7vw;display:flex;gap:28px;font-size:.74rem;letter-spacing:.01em;
  font-weight:700;}
.hd nav button{background:none;border:0;color:inherit;font:inherit;cursor:pointer;opacity:.45;
  min-height:44px;padding:2px 0;transition:opacity .2s,color .2s;position:relative;}
.hd nav button:hover,.hd nav button[aria-current="true"]{opacity:1;}
.hd nav button[aria-current="true"]:after{content:"";position:absolute;left:0;right:0;bottom:-5px;
  height:1.5px;background:var(--hot);}
.hd-cta{display:inline-flex;align-items:center;justify-content:center;gap:10px;min-height:44px;
  padding:0 22px;border:1px solid rgba(255,122,61,.72);border-radius:10px;color:var(--copper);
  font-family:'Manrope',sans-serif;font-size:.72rem;font-weight:800;letter-spacing:.11em;
  text-transform:uppercase;transition:background .2s,color .2s,border-color .2s;}
.hd-cta:hover{background:var(--hot);border-color:var(--hot);color:var(--bg);}
.nav-toggle{display:none;background:none;border:0;color:inherit;font:inherit;font-size:.75rem;
  letter-spacing:.15em;text-transform:uppercase;font-weight:800;cursor:pointer;}

/* Wayfinding without deck furniture.
   A numbered corner ("05 / 08") and a row of segments along the bottom are
   exactly how a slide deck tells you where you are, so both are gone. What
   replaces them is a single unbroken hairline that fills as you move: the
   reading-progress convention from long-form web pages, which says "you are
   partway through a page" rather than "you are on slide five". The header nav
   keeps its underline, and that is the real wayfinding. */
.foot{position:fixed;left:0;right:0;bottom:0;z-index:60;
  display:flex;align-items:flex-end;justify-content:flex-end;padding:0 5vw 20px;
  pointer-events:none;}
.rail{position:fixed;left:0;right:0;bottom:0;height:2px;z-index:61;
  background:rgba(255,255,255,.07);}
/* Driven by transform, not width. The fill is updated on every animation frame
   now, and animating `width` relayouts the element each time, which is exactly
   the kind of per-frame layout work that shows up as stutter. scaleX is handled
   on the compositor. The old .18s transition is gone with it - with a value
   arriving every frame, a transition only adds lag. */
.rail i{display:block;height:100%;width:100%;background:var(--hot);
  transform:scaleX(0);transform-origin:0 50%;will-change:transform;}
.hint{flex:0 0 auto;font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);
  display:flex;align-items:center;gap:9px;transition:opacity .5s;}
.hint.gone{opacity:0;}
.hint .ar{animation:nudge 1.7s ease-in-out infinite;}
@keyframes nudge{0%,100%{transform:translateX(0);}50%{transform:translateX(7px);}}

/* ---- opening ---- */
.panel.p-start{justify-content:flex-start;padding:140px 4.8vw 104px;overflow:hidden;}
.p-start h1{font-size:clamp(3.6rem,4.8vw,4.9rem);line-height:.88;max-width:13ch;}
.p-start h1 em{color:var(--copper);display:block;}
.lede{max-width:49ch;color:#A9BBC7;font-size:clamp(1rem,1.18vw,1.08rem);margin:24px 0 24px;}
/* The hero now reads as an information system: a primary cord with organized
   pendants and distinct knots. The source reserves its left side for copy, so
   it can stay uncropped and no longer pushes the headline off screen. */
.knot{position:absolute;inset:0;width:100%;height:100%;aspect-ratio:auto;
  overflow:hidden;isolation:isolate;
  will-change:transform;z-index:0;
  /* The right-hand feather that stops the opening photograph ending in a hard
     vertical line as you travel to the second section. Width is written by the
     scroll handler as --hero-feather and is 0px at rest, so this is no mask at
     all while you are on the opening and the section looks exactly as
     designed. See heroFade in kinetic.js for why the edge needs removing. */
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - var(--hero-feather,0px)),transparent 100%);
  mask-image:linear-gradient(90deg,#000 calc(100% - var(--hero-feather,0px)),transparent 100%);}
.knot img{position:relative;z-index:0;display:block;width:100%;height:100%;
  object-fit:cover;object-position:center;opacity:.94;}
/* A restrained text-side veil keeps the headline dominant without hiding the
   khipu's structure. It also makes the generated navy merge into the page. */
.knot::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(90deg,rgba(6,14,21,.38) 0%,rgba(6,14,21,.22) 36%,
    rgba(6,14,21,.03) 57%,transparent 72%),
    linear-gradient(180deg,rgba(4,11,17,.18),transparent 22%,transparent 72%,rgba(4,11,17,.32));}
.khipu-network{position:absolute;inset:0;z-index:2;display:block;width:100%;height:100%;
  pointer-events:none;mix-blend-mode:screen;}

.p-start .inner{position:relative;z-index:4;max-width:48vw;}

.hero-node-labels{position:absolute;inset:0;z-index:3;pointer-events:none;
  font-family:'Manrope',sans-serif;font-size:.61rem;font-weight:800;letter-spacing:.18em;
  text-transform:uppercase;color:rgba(244,239,231,.84);}
.hero-node-labels span{position:absolute;display:flex;align-items:center;gap:9px;white-space:nowrap;}
.hero-node-labels span::after{content:"";display:block;width:34px;height:1px;
  background:linear-gradient(90deg,var(--copper),rgba(227,151,103,.08));
  box-shadow:35px 0 8px 1px rgba(255,122,61,.8);}
.hero-node-labels .node-1{left:47.5%;top:20%;}
.hero-node-labels .node-2{left:47%;top:39%;}
.hero-node-labels .node-3{left:47%;top:58%;}
.hero-node-labels .node-4,.hero-node-labels .node-5,.hero-node-labels .node-6{right:4.8%;flex-direction:row-reverse;}
.hero-node-labels .node-4{top:23%;}
.hero-node-labels .node-5{top:41%;}
.hero-node-labels .node-6{top:59%;}
.hero-node-labels .node-4::after,.hero-node-labels .node-5::after,.hero-node-labels .node-6::after{
  transform:scaleX(-1);}

/* Three statements, one per line. The fixed 150px was narrower than the middle
   line needs once uppercase and .18em of letter-spacing are counted, so
   "Modern intelligence." broke across two lines and read as four statements
   rather than three. Sized to its content instead, growing leftward from the
   right edge, with each line held on one line. Spanish is the longer set
   ("Inteligencia moderna.") and sets the width. */
.hero-aside{position:absolute;right:4.8vw;bottom:113px;z-index:4;margin:0;
  width:max-content;max-width:38vw;white-space:nowrap;
  font-family:'Manrope',sans-serif;font-size:.64rem;font-weight:800;letter-spacing:.18em;
  line-height:1.85;text-transform:uppercase;color:rgba(244,239,231,.78);}
.hero-aside span{display:block;}
.hero-aside::after{content:"";display:block;width:34px;height:1px;margin-top:14px;background:var(--hot);}

.hero-proof{position:absolute;left:4.8vw;bottom:44px;z-index:4;display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));width:min(47vw,650px);}
.hero-proof > div{display:flex;align-items:center;gap:13px;min-width:0;padding:2px 22px;
  border-right:1px solid rgba(147,167,180,.27);}
.hero-proof > div:first-child{padding-left:0;}
.hero-proof > div:last-child{border-right:0;}
.hero-proof svg{width:29px;height:29px;flex:0 0 auto;fill:none;stroke:var(--hot);
  stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;}
.hero-proof p{margin:0;min-width:0;font-family:'Manrope',sans-serif;text-transform:uppercase;}
/* Allowed to wrap, not cut off. These were held to one line with an ellipsis,
   and every Spanish desktop width lost words to it - "APROBADO POR PERSONAS"
   and "ACCIONES, NO CAJAS NEGRAS" were cut short even at 1440px, and English
   lost "ACTIONS, NOT BLACK BOXES" at 1280px. A promise with its last word
   missing is worse than a strip one line taller. Where a line fits, as English
   does at 1440, it looks exactly as before. */
.hero-proof strong,.hero-proof span{display:block;overflow-wrap:break-word;}
.hero-proof strong{font-size:.66rem;letter-spacing:.1em;color:var(--ink);}
.hero-proof span{margin-top:4px;font-size:.53rem;letter-spacing:.08em;color:var(--muted);}

.mq,.rail{transition:opacity .25s ease;}
body.at-start .mq,body.at-start .rail{opacity:0;}
body.at-start .hint{opacity:0;}

.btn{display:inline-flex;align-items:center;gap:10px;background:var(--hot);color:#0A1119;
  font-weight:800;letter-spacing:.04em;padding:15px 26px;border-radius:2px;text-transform:uppercase;
  font-size:.82rem;border:0;cursor:pointer;font-family:inherit;
  transition:transform .16s,background .16s,box-shadow .16s;}
.btn:hover{background:var(--copper);transform:translate(-2px,-2px);box-shadow:5px 5px 0 rgba(227,151,103,.34);}
.btn.line{background:transparent;color:var(--ink);border:1.5px solid var(--line);}
.btn.line:hover{border-color:var(--hot);box-shadow:none;transform:none;background:transparent;}
.row{display:flex;gap:14px;flex-wrap:wrap;align-items:center;}

/* The hero's buttons are sized by their labels, which have nothing to do with
   how wide the headline should be allowed to run. Leaving them inside the text
   column meant the two languages broke differently for a reason no visitor
   could see: Spanish labels run about a quarter longer AND Spanish gets a
   narrower column (46vw, below), so the same three buttons sat one-then-two
   there and two-then-one in English. The row now measures itself and wraps
   only when the screen genuinely runs out, so both languages break the same
   way at the same width. Capped short of the viewport so it never reaches the
   edge of the panel's padding. */
.p-start .row{width:max-content;max-width:min(84vw,1060px);}

/* The ticker used to live inside the opening section at width:150%, so it ran
   out 806px into the SECOND section and stopped dead - a hard vertical edge
   with the text sliced mid-word, which is what made the page look unfinished.
   It is now a track-level band: one horizon line running the entire length of
   the site, the same move the cord makes, so it never terminates on screen.
   Its width is set in JS from track.scrollWidth (see fillTicker).
   It sits at bottom:44px, clear of the 104px floor the panels pad to, so it
   cannot collide with the lowest content in any section. */
.mq{position:absolute;left:0;bottom:44px;overflow:hidden;white-space:nowrap;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:11px 0;z-index:0;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 2%,#000 98%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 2%,#000 98%,transparent);}
.mq div{display:inline-block;animation:slide 44s linear infinite;font-size:.75rem;
  letter-spacing:.24em;text-transform:uppercase;color:var(--dim);font-weight:700;}
.mq b{color:var(--ink);}
@keyframes slide{from{transform:translateX(0);}to{transform:translateX(-50%);}}

/* ---- shared type ---- */
.kick{font-size:.71rem;letter-spacing:.26em;text-transform:uppercase;color:var(--hot);
  font-weight:800;margin-bottom:20px;}
.say{font-size:min(5.2vw,8vh,4.3rem);max-width:15ch;}
.say em{color:var(--copper);}
.sub{color:var(--muted);max-width:56ch;font-size:1.01rem;margin-top:20px;}
.fine{color:var(--dim);font-size:.75rem;margin-top:20px;max-width:74ch;}


/* ---- one screen per section, exactly ----
   These ran from 74vw to 138vw so the viewport edge would stop reading as a
   frame. That is a real effect, but it has a cost that outweighs it here: with
   sections of uneven width the track almost never lines up with the screen, so
   at rest you are nearly always looking at the tail of one section and the head
   of the next. Every section is now exactly one screen, which is the only way
   a section can fill the screen on its own with nothing of its neighbours
   showing. */
/* Width lives on .panel above, not here. These were one rule per section id
   from when this was a single page, which meant a new page's sections had no
   width rule at all and fell through to auto - growing as wide as their
   content instead of filling one screen. */

/* ---- columns: hairlines, not cards ----------------------------------------
   These were filled tiles on a 1px grid - a dark panel, a border, a hover
   state - which read as a UI component dropped onto the page rather than as
   part of it. Three sections used them at once (Deliverables, Process, Work)
   and the effect was a wall of boxes.

   The page already had the better pattern: the Problem section's run-list is
   hairline rules with no fill, so the ground and the khipu cord show straight
   through it. These now use the same language. The first column is flush left
   so the row starts on the same line as the headline above it, which is most
   of what stops it reading as a separate object. */
.cols{display:grid;gap:0;background:none;border:0;margin-top:34px;}
.c3{grid-template-columns:repeat(3,minmax(0,1fr));}
/* Three across, two rows - not six. Six columns on one screen is 216px each,
   narrow enough to keep the label and explanation readable together. */
.c6{grid-template-columns:repeat(3,minmax(0,1fr));}
.cols > div{background:none;padding:0 34px;}
.cols > div:first-child,
.cols.c6:not(.work-cols) > div:nth-child(3n+1),
.cols.c3 > div:nth-child(3n+1){padding-left:0;}
.cols.c3 > div:not(:nth-child(3n+1)),
.cols.c6 > div:not(:nth-child(3n+1)){border-left:1px solid var(--line);}
/* Second row of a six-up gets a rule above it and room to breathe. */
.cols.c6:not(.work-cols) > div:nth-child(n+4){border-top:1px solid var(--line);padding-top:30px;margin-top:30px;}
/* Work is one row of four, so its fourth card is not a second row: the two
   rules above skip it, and it takes the same padding as cards two and three
   at every height tier. Overriding them here lost on specificity instead. */
.work-cols{grid-template-columns:repeat(4,minmax(0,1fr));}
.work-cols > div:nth-child(4){border-left:1px solid var(--line);}

/* The figure carries the section now that no box does. */
.cols b{display:block;font-family:'Manrope',sans-serif;font-size:min(3.4vw,5vh,3rem);
  letter-spacing:-.045em;color:var(--copper);line-height:.95;}
.cols span.cap{display:block;margin-top:10px;font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dim);font-weight:700;}
.cols p{color:var(--muted);font-size:.88rem;margin:8px 0 0;max-width:38ch;}
.cols h3{font-size:1rem;text-transform:none;letter-spacing:-.01em;margin-bottom:6px;}

/* The supplied visual proposal uses a consistent family of copper line icons
   to make dense operational concepts scannable. These are code-native so they
   inherit the design tokens, remain sharp, and stay decorative beside text. */
.feature-icon{width:35px;height:35px;display:flex;align-items:center;justify-content:center;
  color:var(--hot);filter:drop-shadow(0 0 9px rgba(255,122,61,.22));}
.feature-icon svg{width:27px;height:27px;display:block;fill:none;stroke:currentColor;
  stroke-width:1.65;stroke-linecap:round;stroke-linejoin:round;}
.visual-cols .feature-icon{margin-bottom:13px;}
.visual-cols h3{margin-top:0;}
.work-cols .feature-icon{display:inline-flex;margin:0 10px 0 0;vertical-align:middle;}
.work-cols b{display:inline-block;vertical-align:middle;font-size:1.45rem;}

/* Process nodes borrow the proposal's illuminated-knot rhythm while remaining
   an abstract interface marker rather than pretending to be another khipu. */
.process-cols{position:relative;}
.process-cols::before{content:"";position:absolute;left:20px;right:20px;top:24px;height:1px;
  background:linear-gradient(90deg,transparent,var(--copper) 12%,var(--copper) 88%,transparent);
  opacity:.44;box-shadow:0 0 9px rgba(255,122,61,.34);}
.process-mark{position:relative;z-index:1;display:flex;align-items:center;gap:10px;margin-bottom:15px;}
.process-mark .feature-icon{width:47px;height:47px;border:1px solid rgba(227,151,103,.7);
  border-radius:50%;background:#0A1119;box-shadow:0 0 18px rgba(255,122,61,.2);}
.process-mark .feature-icon svg{width:24px;height:24px;}
.process-cols .process-mark b{display:block;font-size:.72rem;letter-spacing:.14em;
  color:var(--ink);background:#0A1119;padding:4px 6px;}
.process-cols h3{margin-top:0;}

/* The problem list runs as a wide single row: a different shape again. */
.runlist{list-style:none;padding:0;margin:28px 0 0;display:flex;gap:0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);}
.runlist li{flex:1;padding:18px 20px 18px 0;border-right:1px solid var(--line);
  font-size:.96rem;display:flex;gap:12px;align-items:flex-start;}
.runlist li:last-child{border-right:0;}
.runlist i{font-style:normal;color:var(--hot);font-family:'Manrope',sans-serif;
  font-weight:800;font-size:.76rem;padding-left:20px;}
.runlist .feature-icon{flex:0 0 31px;width:31px;height:31px;margin-left:14px;}
.runlist .feature-icon svg{width:24px;height:24px;}

.tiers{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;background:var(--line);
  border:1px solid var(--line);max-width:720px;margin-top:30px;}
.tiers > div{background:#0B1520;padding:26px;}
.tiers .f{background:rgba(255,122,61,.1);}
.tiers .amt{font-family:'Manrope',sans-serif;font-size:2.8rem;letter-spacing:-.045em;}
.tiers .amt small{font-size:.72rem;color:var(--muted);letter-spacing:.08em;text-transform:uppercase;}
.tiers .nm{font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;color:var(--hot);font-weight:800;}
.tiers p{color:var(--muted);font-size:.89rem;margin:10px 0 18px;}

.qa{margin-top:22px;max-width:76ch;}
.qa details{border-top:1px solid var(--line);padding:12px 0;}
.qa details:last-of-type{border-bottom:1px solid var(--line);}
.qa summary{cursor:pointer;list-style:none;display:flex;justify-content:space-between;gap:18px;
  font-weight:700;font-size:1rem;}
.qa summary::-webkit-details-marker{display:none;}
.qa summary:after{content:"+";color:var(--hot);font-weight:800;}
.qa details[open] summary:after{content:"\2013";}
.qa p{color:var(--muted);margin:8px 0 0;font-size:.93rem;}

.face{display:grid;grid-template-columns:auto 1fr;gap:36px;align-items:end;}
/* Full colour. These were desaturated to keep the palette tight, but the page
   is copper on near-black and the photographs are the only human thing on it -
   draining them costs more than the restraint is worth. */
/* Circular, not a portrait rectangle. founder.jpg has a white circular
   border baked into the image, so in a rectangle it shows white corners and a
   visible ring. Round frames match what that file already is, and Alex's
   square photograph crops to a circle cleanly. */
.face img{width:224px;height:224px;border-radius:50%;object-fit:cover;object-position:center top;}

/* ---- the team pair ----
   Two people side by side on one screen. Each is a photo beside a name, role
   and one line, so both fit without either becoming a footnote. */
/* The pull quote. This was an inline font-size using vw, which meant it
   collapsed to about 11px on a phone AND could not be overridden by the phone
   breakpoint, because an inline style beats a stylesheet rule. */
.quote{font-size:min(2.8vw,4.4vh,2.2rem);max-width:30ch;}

.team{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:34px;
  margin-top:26px;max-width:1180px;}
.member{display:grid;grid-template-columns:auto 1fr;gap:22px;align-items:center;
  background:#0B1520;border:1px solid var(--line);padding:22px;}
.member img{width:132px;height:132px;border-radius:50%;object-fit:cover;object-position:center top;}
.member h3{font-size:1.15rem;text-transform:none;letter-spacing:-.01em;margin:0 0 4px;}
.member .cap{display:block;font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--hot);font-weight:800;margin-bottom:9px;}
.member p{color:var(--muted);font-size:.9rem;margin:0;}

.swipe-note{display:none;color:var(--dim);font-size:.72rem;letter-spacing:.14em;
  text-transform:uppercase;margin-top:10px;}

/* ---- short viewports ----------------------------------------------------
   Now that every section has to fit one screen, height is as much of a
   constraint as width, and a 1366x768 laptop is the common case that fails.
   At 768 the standard frame leaves ~490px of room and Work's two rows of cards
   need ~590px. Because the low sections use justify-content:flex-end, that
   overflow goes UPWARDS - the "Selected work" kicker was printing on top of the
   KHIPUAI logo in the fixed header.

   So the frame tightens instead of the content colliding with the chrome. The
   bottom padding stays at 100px on purpose: the ticker band occupies 44px to
   91px up from the bottom, so anything less would push content into it. */
@media (min-width:901px) and (max-height:860px) and (min-height:501px){
  .panel{padding:96px 5vw 100px;}
  .panel.at-top{padding-top:112px;}
  .panel.at-low{padding-bottom:100px;}
  .cols,.tiers,.runlist{margin-top:20px;}
  .cols > div{padding:15px 16px;}
  .tiers > div{padding:20px;}
  .sub,.fine{margin-top:13px;}
  .qa{margin-top:14px;}
  .lede{margin:16px 0 20px;}
  .hero-proof{bottom:28px;}
  .hero-aside{bottom:94px;}
  /* The founder portrait is the tallest fixed element on the page; at 258px it
     pushed the Founder section 11px into the ticker band. */
  .face img{width:190px;height:190px;}
}

/* A second, tighter tier. At 1280x720 the frame above still leaves only 524px
   and Work's two card rows need 554, so its kicker clipped under the header
   again. The card padding and the gaps give up the difference; the bottom stays
   at 100px for the ticker band, as above. */
@media (min-width:901px) and (max-height:740px) and (min-height:501px){
  .panel{padding:76px 5vw 100px;}
  .panel.at-top{padding-top:88px;}
  .panel.at-low{padding-bottom:100px;}
  .cols,.tiers,.runlist{margin-top:16px;}
  .cols > div{padding:12px 14px;}
  .cols h3{margin-bottom:3px;}
  .cols p{font-size:.82rem;}
  .cols span.cap{margin-top:5px;}
  .visual-cols .feature-icon{width:27px;height:27px;margin-bottom:7px;}
  .visual-cols .feature-icon svg{width:22px;height:22px;}
  .work-cols .feature-icon{margin:0 7px 0 0;}
  .process-mark{margin-bottom:9px;}
  .process-mark .feature-icon{width:35px;height:35px;}
  .process-cols::before{top:18px;}
  .face img{width:168px;height:168px;}
  .p-start h1{font-size:clamp(3rem,4.5vw,3.9rem);}
  .hero-proof{bottom:22px;}
  .hero-aside{bottom:84px;}
}

@media (max-width:1180px) and (min-width:901px){
  .hd{gap:18px;}
  .hd nav{margin-left:2vw;gap:17px;}
  .hd-cta{display:none;}
  .hero-node-labels,.hero-aside{display:none;}
  .hero-proof{width:65vw;}
}

/* ---- the stacked layout: phones, and tablets held upright ----------------
   Every rule block that switches to the stacked layout uses this same query.
   It used to be width alone (900px), which sent a 1024x1366 iPad Pro held
   upright to the sideways layout: the opening was one 1366px-tall screen with
   the headline in the top third, 700px of empty sky, and the proof strip at the
   very bottom. A portrait tablet is read like a phone, so up to 1100px wide it
   now gets the stacked layout too. Held sideways it keeps the desktop layout,
   which it has the room for.
   The third condition is a phone held sideways. A 932x430 phone is wider than
   900px, so it got the sideways layout with 430px of height - less than the
   header and the bottom padding need between them before any content. Nothing
   under 500px tall can hold a one-screen section, so it stacks. The two
   short-laptop tiers above stop at 501px for the same reason.
   A normal desktop window is landscape and taller than 500px, so none of this
   reaches it. */
@media (max-width:900px), (max-width:1100px) and (orientation:portrait), (max-height:500px){
  html,body{overflow:auto;height:auto;}
  .track{display:block;height:auto;overflow:visible;scroll-snap-type:none;cursor:auto;
    background:rgba(10,17,25,.38);}
  .cord{display:none;}
  .panel,.p-start,.p-problem,.p-get,.p-process,.p-work,.p-fee,.p-questions,.p-operator{
    width:100%;height:auto;min-height:0;padding:88px 22px 38px;justify-content:flex-start;}
  .panel.p-start{padding:88px 22px 38px;}
  .panel:last-child{padding-bottom:74px;}
  .p-start h1{font-size:clamp(2.15rem,9vw,3.4rem);}
  .p-start .inner{max-width:none;}
  /* On the phone the buttons already stack full-width; letting the row measure
     itself here would shrink them back to their labels. */
  .p-start .row{width:auto;max-width:none;}
  .say{font-size:clamp(1.9rem,8vw,2.6rem);}
  /* The desktop rule now positions with left/top/aspect-ratio, so the stacked
     layout has to unset all three - left:50vw on a position:relative element
     would shove the image half a screen to the right. */
  .knot{position:relative;inset:auto;margin-top:20px;
    width:100%;aspect-ratio:16/9;height:auto;
    -webkit-mask-image:none;mask-image:none;}
  .knot::after{background:linear-gradient(90deg,rgba(10,17,25,.18),transparent 62%);}
  .hero-node-labels,.hero-aside{display:none;}
  .hero-proof{position:static;display:flex;width:100%;margin-top:34px;overflow-x:auto;
    padding:4px 0 10px;scroll-snap-type:x proximity;}
  /* The desktop rule truncates these with an ellipsis instead of wrapping,
     which is right in a fixed-height strip across the bottom of the hero and
     wrong here, where they are a swipeable row with room below. At the larger
     type it was turning "improving operations" into "improving operatio...".
     Let them wrap; a second short line costs nothing and says the whole word. */
  .hero-proof > div{flex:0 0 212px;padding:4px 18px;scroll-snap-align:start;}
  .hero-proof > div:first-child{padding-left:0;}
  .hero-proof strong,.hero-proof span{white-space:normal;overflow:visible;
    text-overflow:clip;line-height:1.3;}
  /* 11.2px and 9.3px. The second one is below anything that should be asked of
     a reader on a phone, and both sit under the hero where they are the first
     supporting detail anyone meets. */
  .hero-proof strong{font-size:.78rem;}
  .hero-proof span{font-size:.7rem;}
  .mq,.hint,.rail{display:none;}
  .foot{position:static;padding:0;}

  /* ---- the header has to be opaque here ----------------------------------
     On the desktop layout the header floats over a section that is not moving
     underneath it, so a gradient that fades to nothing is fine. On a phone the
     whole page scrolls under it, and the gradient's transparent lower half let
     body copy run straight through the wordmark and the menu. On the Team
     screen the pull quote and the word KHIPUAI were printed on top of each
     other and neither could be read.
     Solid, with a hairline under it so it reads as a deliberate bar rather
     than a panel that happens to be dark. */
  .hd{background:rgba(8,15,22,.96);border-bottom:1px solid var(--line);
    -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
    min-height:64px;padding:10px 22px;gap:14px;}

  /* ---- touch targets ------------------------------------------------------
     AGENTS.md asks for 44x44 where practical. These were the three that were
     not close: the menu button at 54x19, the language switch at 18x21, and the
     FAQ rows at 23px tall. The type size is unchanged - the box around it grew.
     min-height on a flex child needs the box to be a flex container too, or
     the padding lands but the height does not. */
  .nav-toggle{display:flex;align-items:center;min-height:44px;padding:0 4px;}
  .hd .bd{min-height:44px;}
  .lang{gap:6px;}
  .lang a,.lang span{display:flex;align-items:center;justify-content:center;
    min-width:34px;min-height:44px;padding:0;}
  .lang .sep{min-width:0;}
  .qa summary{min-height:44px;align-items:center;padding:8px 0;}
  .hd-cta{display:none;}
  .hd nav{display:none;}
  .hd nav.open{display:flex;position:absolute;left:5vw;right:5vw;top:66px;max-height:70vh;
    overflow:auto;flex-direction:column;gap:0;padding:10px 18px;background:var(--bg);
    color:var(--ink);border:1px solid var(--line);mix-blend-mode:normal;box-shadow:0 18px 50px rgba(0,0,0,.16);}
  .hd nav.open button{width:100%;text-align:left;padding:12px 0;border-bottom:1px solid var(--line);opacity:.75;}
  .hd nav.open button:last-child{border-bottom:0;}
  .runlist{flex-direction:column;}
  .runlist li{border-right:0;border-bottom:1px solid var(--line);padding:14px 0;}
  .runlist li:last-child{border-bottom:0;}
  .runlist i{padding-left:0;}
  .runlist .feature-icon{margin-left:0;}
  /* Stacked, the six-up grids ran to 1,579px on their own. Swiping them keeps
     the concept's horizontal idea alive on a phone and roughly halves it. */
  /* Mandatory rather than proximity, and a narrower peek. At 76% the next card
     showed a quarter of itself, which is enough width to start rendering full
     sentences and read as a card that has been cut in half rather than as a
     card waiting behind. 86% shows a sliver: clearly more to come, nothing
     half-said. Mandatory snapping also means a swipe always lands on a card
     instead of stopping between two. */
  .cols.c3,.cols.c6{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch;}
  .cols.c3 > div,.cols.c6 > div{flex:0 0 86%;scroll-snap-align:start;}
  .process-cols::before{display:none;}
  /* The desktop grid puts items 4-6 on a second row, with a rule above them and
     margin to clear it. On a phone these become ONE swipeable row, so those
     rules dropped items 4-6 thirty pixels below their neighbours with a stray
     hairline floating over them. Reset for the row layout. */
  .cols.c6 > div:nth-child(n+4){border-top:0;padding-top:0;margin-top:0;}
  .cols > div{padding:0 18px;}
  .cols > div:first-child{padding-left:0;}
  .cols.c3 > div:not(:first-child),
  .cols.c6 > div:not(:first-child){border-left:1px solid var(--line);}
  .cols.c3 > div:nth-child(3n+1):not(:first-child),
  .cols.c6 > div:nth-child(3n+1):not(:first-child){padding-left:18px;}
  .cols.c3::-webkit-scrollbar,.cols.c6::-webkit-scrollbar{height:5px;}
  .cols.c3::-webkit-scrollbar-thumb,.cols.c6::-webkit-scrollbar-thumb{background:var(--line);border-radius:99px;}
  .swipe-note{display:block;}
  .tiers{grid-template-columns:minmax(0,1fr);}
  .face{grid-template-columns:1fr;gap:18px;align-items:start;}
  /* Two cards side by side leaves 148px each on a phone, most of it taken by
     the photograph. One per row instead. */
  .quote{font-size:clamp(1.15rem,5.2vw,1.5rem);max-width:none;}
  .team{grid-template-columns:minmax(0,1fr);gap:16px;margin-top:18px;}
  /* The photo beside the text leaves about 165px for the paragraph at 390px
     wide, which breaks the bio into three and four word lines. Stacked, the
     text gets the full card and reads as prose again. */
  .member{grid-template-columns:minmax(0,1fr);padding:18px;gap:14px;}
  .member img{width:84px;height:84px;}
  .face img{width:150px;height:150px;}
  [data-rv]{opacity:1;transform:none;}
}
@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important;}
  .track{scroll-behavior:auto;}
  [data-rv]{opacity:1;transform:none;}
}

/* ---- hover: spotlight, not a box ----------------------------------------
   The old cards had a hover that filled the tile, which is the boxiness this
   design just removed. This does the opposite: the row you are pointing at
   holds its brightness and everything beside it recedes, so attention is
   directed by contrast rather than by drawing a container.

   The hovered item also warms up - its figure goes to the hot copper, its
   body text to full ink, its dividing rule lights - and lifts a few pixels.

   Gated behind (hover:hover) and (pointer:fine). On a touch screen :hover
   latches after a tap, so without this the last thing tapped would stay lit
   and everything else would stay dimmed. */
@media (hover:hover) and (pointer:fine){
  .cols > div, .runlist li, .tiers > div, .member, .qa details{
    transition:opacity .26s ease, color .26s ease, border-color .26s ease,
               transform .26s cubic-bezier(.16,.8,.28,1);}

  .cols:hover > div:not(:hover),
  .runlist:hover li:not(:hover),
  .tiers:hover > div:not(:hover),
  .team:hover .member:not(:hover),
  .qa:hover details:not(:hover){opacity:.34;}

  .cols > div:hover, .runlist li:hover, .tiers > div:hover,
  .member:hover, .qa details:hover{opacity:1;}

  .cols > div:hover{transform:translateY(-4px);border-left-color:var(--copper);}
  .cols > div:hover b{color:var(--hot);}
  .cols > div:hover h3,
  .cols > div:hover p{color:var(--ink);}
  .cols > div:hover span.cap{color:var(--muted);}

  .runlist li:hover{transform:translateY(-3px);}
  .runlist li:hover i{color:var(--ink);}

  .member:hover{transform:translateY(-4px);border-color:var(--copper);}
  .tiers > div:hover{transform:translateY(-4px);}
  .qa details:hover summary{color:var(--copper);}
}

/* The lift is motion; the dimming is not, so under reduce the spotlight still
   works and only the movement goes. */
@media (prefers-reduced-motion:reduce){
  .cols > div:hover, .runlist li:hover, .member:hover, .tiers > div:hover{transform:none;}
}

/* ---- language switch ----
   Sits between the wordmark and the section nav. Set apart from the section
   links by a rule and by being a fixed pair rather than a list, so it does not
   read as another section. */
.lang{display:flex;align-items:center;gap:11px;margin-left:auto;padding-left:20px;
  border-left:1px solid rgba(255,255,255,.16);
  font-family:'Manrope',sans-serif;font-size:.72rem;letter-spacing:.14em;font-weight:800;}
.lang a,.lang span{padding:2px 0;}
.lang a{opacity:.45;transition:opacity .2s;}
.lang a:hover{opacity:1;}
.lang .on{opacity:1;position:relative;}
.lang .on:after{content:"";position:absolute;left:0;right:0;bottom:-5px;height:1.5px;background:currentColor;}
.lang .sep{opacity:.3;font-weight:400;}
@media (max-width:900px), (max-width:1100px) and (orientation:portrait), (max-height:500px){
  /* The section nav is hidden on a phone, but the language switch is not a
     section - it is the one piece of navigation on the page, so it stays. */
  .lang{margin-left:auto;padding-left:0;border-left:0;}
}

/* ---- longer languages ----
   Spanish runs roughly 20% longer than English for the same sentence. At the
   English hero size the Spanish headline pushed 91px past the point where the
   knot photograph is fully opaque - white type over lit rope. Targeted off the
   document's own lang attribute, so it applies to any Spanish page without a
   second stylesheet, and any other long language can be added the same way. */
html[lang="es"] .p-start h1{font-size:clamp(3.3rem,4.35vw,4.5rem);}
html[lang="es"] .p-start .inner{max-width:48vw;}
html[lang="es"] .lede{max-width:40ch;}
@media (max-width:900px), (max-width:1100px) and (orientation:portrait), (max-height:500px){
  html[lang="es"] .p-start h1{font-size:clamp(2.1rem,9vw,3.1rem);}
  html[lang="es"] .p-start .inner{max-width:none;}
}

/* ---- the quote panel ----
   Deliberately not a chat bubble stack. The page is hairlines and big type,
   and a messenger UI would look borrowed from somewhere else. One question at
   a time, answers as the same hairline row used elsewhere, the number arriving
   in the page's own display face. */
.quote-wrap{margin-top:30px;max-width:980px;}
.q-step{font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);
  font-weight:800;margin-bottom:12px;}
.q-ask{font-size:min(2.4vw,3.6vh,1.7rem);font-family:'Manrope',sans-serif;font-weight:800;
  letter-spacing:-.03em;line-height:1.1;margin:0 0 20px;max-width:26ch;}
.q-opts{display:flex;flex-wrap:wrap;gap:0;border-top:1px solid var(--line);}
.q-opts button{flex:0 0 auto;background:none;border:0;border-bottom:1px solid var(--line);
  border-right:1px solid var(--line);color:var(--ink);font:inherit;font-size:.95rem;
  padding:15px 26px;cursor:pointer;transition:color .2s,background .2s;text-align:left;}
.q-opts button:hover{color:var(--hot);}
.q-opts button:last-child{border-right:0;}
.q-back{background:none;border:0;color:var(--dim);font:inherit;font-size:.75rem;
  letter-spacing:.14em;text-transform:uppercase;font-weight:700;cursor:pointer;
  padding:14px 0 0;}
.q-back:hover{color:var(--ink);}

.q-out{border-top:1px solid var(--line);padding-top:26px;}
.q-plan{display:flex;align-items:baseline;gap:10px;margin-bottom:20px;}
.q-plan span,.q-match span{font-size:.68rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--dim);font-weight:800;}
.q-plan strong{font-family:'Manrope',sans-serif;font-size:1rem;}
.q-num{font-family:'Manrope',sans-serif;font-size:min(5.4vw,8vh,4.4rem);letter-spacing:-.045em;
  line-height:.95;color:var(--copper);}
.q-num small{font-size:.24em;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);
  display:block;margin-top:12px;font-weight:800;}
.q-num-regional{max-width:18ch;font-size:min(3.8vw,6vh,3.3rem);}
.q-num-regional small{font-size:.32em;}
.q-note{color:var(--muted);font-size:.92rem;margin:16px 0 0;max-width:52ch;}
.q-match{border-top:1px solid var(--line);margin-top:22px;padding-top:18px;max-width:760px;}
.q-match strong{display:block;font-family:'Manrope',sans-serif;font-size:1rem;margin-top:7px;}
.q-match p{color:var(--muted);font-size:.88rem;line-height:1.55;margin:6px 0 0;max-width:68ch;}
.q-flag{color:var(--dim);font-size:.78rem;margin:10px 0 0;max-width:60ch;}
.q-again{margin-top:22px;}
/* The result on a short screen. Stacked in one column it is about 470px tall
   (560px for the regional answer, with its extra note), and with the kicker and
   headline above it that is more than a 1366x768 or 1280x720 laptop has. The
   section is one fixed screen, so what did not fit was simply cut off - in
   Spanish the "Book a call" button ended up to 167px below the bottom of the
   screen, with no way to scroll to it. Side by side, the estimate on the left
   and what to do about it on the right, it is roughly half the height. Tall
   screens (1920x1080 and up) keep the single column, which fits there. */
@media (min-width:901px) and (max-height:900px) and (min-height:501px){
  .q-out{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:44px;
    align-items:start;}
  .q-side .q-match{margin-top:0;border-top:0;padding-top:0;}
  .q-note{margin-bottom:0;}
}
@media (max-width:900px), (max-width:1100px) and (orientation:portrait), (max-height:500px){
  .q-opts{flex-direction:column;}
  .q-opts button{border-right:0;width:100%;padding:14px 0;}
  .q-ask{font-size:1.15rem;}
  /* The result is sized off the viewport width for the desktop, which on a
     390px phone made the price 21px, the regional answer 15px, and the
     currency and region line under them about 5px. Given phone sizes. */
  .q-plan{flex-wrap:wrap;gap:4px 10px;}
  .q-num{font-size:clamp(2rem,9vw,2.6rem);}
  .q-num-regional{font-size:clamp(1.45rem,6.4vw,2rem);}
  .q-num small,.q-num-regional small{font-size:.75rem;}
}

/* ---- fit: for you / not for you ----
   Two columns that have to read as opposed, not as a pair of equal lists. The
   left keeps the page's ink; the right is muted and marked, so the contrast is
   legible before a word is read. Same hairline language as everything else. */
.fit{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0;margin-top:30px;max-width:1120px;}
.fit > div{padding:0 40px;}
.fit > div:first-child{padding-left:0;}
.fit > div:last-child{border-left:1px solid var(--line);}
.fit h3{font-size:.72rem;letter-spacing:.18em;text-transform:uppercase;font-weight:800;
  margin:0 0 18px;}
.fit .yes h3{color:var(--hot);}
.fit .no h3{color:var(--dim);}
.fit ul{list-style:none;padding:0;margin:0;}
.fit li{position:relative;padding-left:24px;margin-bottom:16px;font-size:.95rem;line-height:1.5;}
.fit li:before{position:absolute;left:0;top:0;font-family:'Manrope',sans-serif;font-weight:800;}
.fit .yes li:before{content:"+";color:var(--hot);}
.fit .no li{color:var(--muted);}
.fit .no li:before{content:"\2013";color:var(--dim);}

/* The objection lines, folded into Deliverables rather than given a screen. */
.nolines{display:flex;flex-wrap:wrap;gap:0 34px;margin-top:22px;padding-top:18px;
  border-top:1px solid var(--line);}
.nolines span{font-family:'Manrope',sans-serif;font-weight:800;font-size:.8rem;
  letter-spacing:.02em;color:var(--dim);}
@media (max-width:900px), (max-width:1100px) and (orientation:portrait), (max-height:500px){
  .fit{grid-template-columns:minmax(0,1fr);}
  .fit > div{padding:0;}
  .fit > div:last-child{border-left:0;border-top:1px solid var(--line);margin-top:24px;padding-top:24px;}
  .nolines{flex-direction:column;gap:8px;}
}

/* =========================================================================
   The self-assessment.

   The live version is one long scrolling worksheet: 15 questions with a point
   value beside each, and you add them up yourself at the bottom. That works on
   a vertical page where all 15 are in front of you. It does not work here -
   nothing on this site is read by scrolling past it, and you cannot hold a
   running total in your head across five screens you have to travel between.

   So the questions became tappable and the total counts itself. That is not a
   feature added for its own sake; it is what the sideways format costs, and
   not paying it would have left a worksheet you could not actually fill in.
   The printable PDF still exists for the pen-and-paper version, and the form
   on the last screen is how you get it.
   ========================================================================= */
.ask{list-style:none;padding:0;margin:26px 0 0;max-width:82ch;
  border-top:1px solid var(--line);}
.ask li{border-bottom:1px solid var(--line);}

/* A button, not a checkbox with a label: the whole row is the target, it
   reports pressed state to a screen reader, and it needs no custom control
   drawn over a native one. */
.ask button{width:100%;display:flex;gap:18px;align-items:flex-start;text-align:left;
  background:none;border:0;padding:17px 4px;color:var(--muted);font:inherit;
  font-size:.97rem;line-height:1.5;cursor:pointer;transition:color .18s;}
.ask button:hover{color:var(--ink);}

/* The points value doubles as the tick box. Empty and dim until chosen, then
   it fills - so the row shows both what it is worth and that you took it. */
.ask .pts{flex:0 0 38px;height:30px;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--line);font-family:'Manrope',sans-serif;font-weight:800;
  font-size:.82rem;color:var(--dim);transition:all .18s;}
.ask button[aria-pressed="true"]{color:var(--ink);}
.ask button[aria-pressed="true"] .pts{background:var(--hot);border-color:var(--hot);color:#0A1119;}
.ask .txt{flex:1;}

/* The running total, bottom-left, opposite the scroll hint. It has to be
   visible from every screen - a tally you can only see on the last one is no
   better than adding it up yourself. */
.tally{flex:0 0 auto;margin-right:auto;font-size:.7rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--dim);display:flex;align-items:baseline;gap:9px;}
.tally b{font-family:'Manrope',sans-serif;font-size:1.5rem;letter-spacing:-.04em;
  color:var(--hot);line-height:1;}

/* The result. One big number, then the three bands with the one you landed in
   lit and the other two held back - rather than three equal boxes leaving you
   to work out which is yours. */
.bignum{font-family:'Manrope',sans-serif;font-weight:800;line-height:.86;
  font-size:min(13vw,17vh,9rem);letter-spacing:-.05em;color:var(--hot);}
.bignum small{font-size:.24em;color:var(--dim);letter-spacing:.06em;margin-left:10px;}
.bands{list-style:none;padding:0;margin:26px 0 0;max-width:86ch;}
.bands li{border-top:1px solid var(--line);padding:16px 0 16px 22px;position:relative;
  color:var(--dim);transition:color .25s,border-color .25s;}
.bands li:last-child{border-bottom:1px solid var(--line);}
.bands li:before{content:"";position:absolute;left:0;top:19px;width:8px;height:8px;
  border:1px solid var(--line);transition:all .25s;}
.bands b{font-family:'Manrope',sans-serif;text-transform:uppercase;letter-spacing:.04em;
  color:var(--muted);transition:color .25s;}
.bands li.on{color:var(--ink);border-color:var(--copper);}
.bands li.on b{color:var(--hot);}
.bands li.on:before{background:var(--hot);border-color:var(--hot);}
/* Nothing is lit until at least one question is answered, or the page would
   claim you scored zero before you had started. */
.bands.idle li{color:var(--muted);}

/* ---- the PDF request ----
   Hairline fields on the dark ground, same as everything else here. The live
   version sits this in a light card; a card would be the one boxed thing left
   on a site that just had its boxes taken away. */
.lead{display:grid;gap:16px;max-width:460px;margin-top:26px;}
.lead .field{display:grid;gap:6px;}
.lead label{font-size:.68rem;letter-spacing:.2em;text-transform:uppercase;
  font-weight:800;color:var(--muted);}
.lead input{font:inherit;font-size:.95rem;padding:12px 0;background:none;color:var(--ink);
  border:0;border-bottom:1px solid var(--line);transition:border-color .18s;}
.lead input:focus{outline:none;border-bottom-color:var(--hot);}
.lead input:disabled{color:var(--dim);}
.lead button{justify-self:start;}
.lead .fineprint{font-size:.78rem;color:var(--dim);margin:0;max-width:44ch;}
/* Text links only: .lead a outranks .btn, and painted the download button's
   label copper on the orange fill (1.10:1). */
.lead a:not(.btn){color:var(--copper);}
/* Off-screen rather than display:none, so bots still fill it in. */
.lead .hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0;}

/* Same two tiers the rest of the shell uses. A 1366x768 laptop is the common
   case that fails: the questions fit, but the PDF form ran 40px into the
   ticker before these. */
@media (min-width:901px) and (max-height:860px) and (min-height:501px){
  .ask{margin-top:18px;}
  .ask button{padding:13px 4px;font-size:.93rem;}
  .lead{gap:11px;margin-top:18px;}
  .lead input{padding:9px 0;}
  .bands li{padding:12px 0 12px 22px;}
  .bands li:before{top:15px;}
}
@media (min-width:901px) and (max-height:740px) and (min-height:501px){
  .ask button{padding:10px 4px;font-size:.89rem;}
  .ask .pts{height:26px;}
  .lead{gap:8px;margin-top:14px;}
  .lead input{padding:7px 0;font-size:.9rem;}
  .bands li{padding:10px 0 10px 22px;font-size:.93rem;}
}
@media (max-width:900px), (max-width:1100px) and (orientation:portrait), (max-height:500px){
  .ask{max-width:none;}
  .ask button{gap:14px;padding:15px 0;font-size:.95rem;}
  .tally{display:none;}          /* the score screen carries it on the phone */
  .lead{max-width:none;}
  /* The "/ 24" is sized as a fraction of the score beside it, and the score is
     sized off the viewport, so on a narrow phone it fell to 10.7px. Given a
     floor, because the denominator is what makes the score mean anything. */
  .bignum small{font-size:max(.24em,.82rem);}
}

/* ---- tablets in the stacked layout: grids, not swipe rows ----------------
   On a phone the six-up and three-up rows become swipeable cards, one card at
   a time, because one column of six ran to 1,579px. On a tablet that same
   treatment showed one 660px-wide card with a sliver of the next - a phone
   layout blown up, with room for two or three columns going unused. From
   601px they are grids again: three steps across, the six deliverables and
   the four work areas two across, the team and the fit lists side by side.
   The .track prefix is only there to outrank the phone rules above. */
@media (min-width:601px) and (max-width:900px),
       (min-width:601px) and (max-width:1100px) and (orientation:portrait),
       (min-width:601px) and (max-height:500px){
  .track .cols.c3,.track .cols.c6{display:grid;overflow:visible;scroll-snap-type:none;}
  .track .cols.c3{grid-template-columns:repeat(3,minmax(0,1fr));}
  .track .cols.c6{grid-template-columns:repeat(2,minmax(0,1fr));}
  .track .panel .cols.c3 > div,.track .panel .cols.c6 > div{flex:none;padding:0 0 0 22px;
    margin-top:0;border-top:0;border-left:1px solid var(--line);}
  .track .panel .cols.c3 > div:nth-child(3n+1),
  .track .panel .cols.c6 > div:nth-child(2n+1){padding-left:0;border-left:0;}
  .track .panel .cols.c6 > div:nth-child(2n){padding-right:0;}
  .track .panel .cols.c3 > div:nth-child(n+4),
  .track .panel .cols.c6 > div:nth-child(n+3){border-top:1px solid var(--line);
    margin-top:26px;padding-top:26px;}
  .track .panel .cols.c3 > div:not(:nth-child(3n)){padding-right:22px;}
  .track .panel .cols.c6 > div:nth-child(2n+1){padding-right:22px;}
  .swipe-note{display:none;}
  .team{grid-template-columns:repeat(2,minmax(0,1fr));}
  .fit{grid-template-columns:repeat(2,minmax(0,1fr));}
  .fit > div{padding:0 0 0 28px;}
  .fit > div:first-child{padding:0 28px 0 0;}
  .fit > div:last-child{border-top:0;border-left:1px solid var(--line);margin-top:0;padding-top:0;}
}

/* A phone held sideways: the stacked opening puts the photograph first, and at
   16:9 across an 888px-wide column it is 500px tall - taller than the whole
   430px screen, so the first thing seen was a picture with no headline and no
   button. Here the headline and its buttons come first and the photograph
   follows. Portrait phones keep the photograph on top, where it is 220px. */
@media (max-height:500px){
  .p-start .inner{order:-1;}
}

/* ---- phones and tablets: a 12px floor for the small labels --------------
   The kickers, captions, role labels and quote step counter are set between
   .68rem and .72rem - 10.9px to 11.5px. Uppercase with wide tracking helps, but
   on a phone held at arm's length they were the smallest text on the page and
   the first things to become a smear. A tablet held sideways gets the desktop
   layout, and with it the same labels plus the opening's proof strip, whose
   second line was 8.5px, so touch screens get the floor too. A desktop with a
   mouse keeps its sizes. */
@media (max-width:900px), (max-width:1100px) and (orientation:portrait), (max-height:500px), (pointer:coarse){
  .kick,.cols span.cap,.member .cap,.swipe-note,.q-step,.q-plan span,.q-match span,
  .process-cols .process-mark b,.fit h3,.hero-proof span,.lead label,
  .lang,.hd nav,.hint,.tally{font-size:.75rem;}
  .hero-proof strong{font-size:.78rem;}      /* the phone size, set above */
}

/* ---- touch screens: 44px targets everywhere, including the sideways layout
   The phone layout already had these. A tablet held sideways gets the
   desktop layout, and with it desktop-sized targets: the section links in the
   header were 30px wide, the wordmark 30px tall, and the FAQ rows and the
   quote's Back button about 25px. (pointer:coarse) is a touch screen as the
   main input, so a desktop with a mouse is untouched. */
@media (pointer:coarse){
  .hd nav button{min-width:44px;}
  .hd .bd{min-height:44px;}
  .lang a{display:flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;}
  .qa summary{min-height:44px;align-items:center;}
  .q-back{display:inline-flex;align-items:center;min-height:44px;padding:0;margin-top:6px;}
  .bignum small{font-size:max(.24em,.82rem);}   /* the phone floor, set above */
}

/* Printing a sideways site gives you screen one and nothing else. The PDF is
   the real printable artefact, but if someone hits Ctrl+P anyway they should
   get the whole worksheet rather than a single panel. */
@media print{
  html,body{height:auto;overflow:visible;background:#fff;color:#000;}
  .hd,.foot,.rail,.cordwrap,.mq,.knot,.swipe-note,.lead{display:none !important;}
  .track{display:block !important;height:auto !important;overflow:visible !important;}
  .panel{width:auto !important;height:auto !important;min-height:0 !important;
    page-break-inside:avoid;padding:0 0 26px !important;opacity:1 !important;
    transform:none !important;}
  .ask button{color:#000;}
  .ask .pts{border-color:#999;color:#000;}
  .bignum,.kick,.bands li.on b{color:#000;}
}

/* Plain-text copy of each Kinetic page for readers that never run JavaScript
   (crawlers, AI agents). buildKinetic() replaces it on load; the .js class is
   set in <head> so the copy never flashes for visitors. Generated by
   tools/prerender.py. */
.js .prerender{display:none}
.prerender{max-width:760px;margin:0 auto;padding:48px 24px;}
