/* ==========================================================================
   pages.css: styles for the standalone service and industry pages.

   Loaded only by the sub-pages, never by index.html. Everything here builds
   on the tokens and primitives already defined in styles.css (--primary,
   --text-0, .container, .section, .h2, .glass, .btn ...) so the sub-pages
   read as the same site without touching the homepage's stylesheet.

   Why a separate file: styles.css is 3,000 lines of homepage-specific
   layout, several rules of which are load-bearing for the WebGL hero and
   the pinned card deck. Adding to it risks a visual regression on the page
   that actually gets traffic, for zero benefit. The sub-pages need about
   400 lines and none of them collide.
   ========================================================================== */

/* The homepage paints its background with a JS mesh-gradient canvas
   (.gridlines). Sub-pages don't run that script, and `html{background:#000}`
   alone reads as a dead flat black next to the homepage. Two fixed radial
   washes reproduce the same colour field statically: no canvas, no rAF, no
   layout cost. `fixed` so they don't scroll away on a long page. */
body.subpage{
  background:
    radial-gradient(120% 80% at 78% -8%, rgba(59,16,128,0.28) 0%, rgba(59,16,128,0) 58%),
    radial-gradient(90% 60% at 8% 4%, rgba(219,174,246,0.10) 0%, rgba(219,174,246,0) 55%),
    var(--bg-0);
  background-attachment: fixed;
}

/* ==========================
   Breadcrumbs
========================== */
.crumbs{
  padding-top: clamp(96px, 10vw, 132px);
  font-size: 0.82rem;
  color: var(--text-2);
}
.crumbs ol{
  list-style:none;
  margin:0;
  padding:0;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:8px;
}
.crumbs a{ color: var(--text-2); text-decoration:none; }
.crumbs a:hover{ color: var(--text-0); }
.crumbs li + li::before{
  content:"/";
  margin-right:8px;
  color: rgba(255,255,255,0.22);
}
.crumbs [aria-current="page"]{ color: var(--text-1); }

/* ==========================
   Page hero
========================== */
.page-hero{
  padding-block: clamp(28px, 3.5vw, 44px) clamp(48px, 5vw, 76px);
}
.page-hero-inner{
  display:grid;
  gap: clamp(28px, 3vw, 48px);
  align-items:start;
}
@media (min-width: 1000px){
  .page-hero-inner{ grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
}
.page-hero h1{
  font-size: clamp(2rem, 4.2vw, 3.4rem);
  line-height:1.08;
  letter-spacing:-0.035em;
  font-weight:600;
  margin:0 0 var(--space-3);
  max-width: 20ch;
}
.page-hero h1 .serif-accent{ display:inline; }
.page-hero .lead{ font-size: clamp(1rem, 1.25vw, 1.18rem); }
.page-hero .lead + .lead{ margin-top: var(--space-3); }
.hero-actions{
  display:flex;
  flex-wrap:wrap;
  gap: var(--space-2);
  margin-top: var(--space-5);
}

/* Fact panel beside the hero copy. Deliberately plain: it carries the
   numbers a buyer scans for before reading a word of body copy. */
.factcard{
  padding: clamp(20px, 2.2vw, 28px);
  display:grid;
  gap: var(--space-4);
  align-content:start;
}
.factcard-row{
  display:grid;
  gap:4px;
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--stroke-0);
}
.factcard-row:last-child{ padding-bottom:0; border-bottom:none; }
.factcard-num{
  font-size: clamp(1.5rem, 2.2vw, 2rem);
  font-weight:600;
  letter-spacing:-0.03em;
  color: var(--primary);
  line-height:1.1;
}
.factcard-label{ font-size:0.86rem; color: var(--text-2); }

/* ==========================
   Prose blocks (the long-form copy Google reads)
========================== */
.prose{ max-width: 74ch; }
.prose p{
  color: var(--text-1);
  margin:0 0 var(--space-3);
}
.prose p:last-child{ margin-bottom:0; }
.prose strong{ color: var(--text-0); font-weight:600; }
.prose a{ color: rgba(219,174,246,0.92); }

/* ==========================
   Feature / problem grid
========================== */
/* minmax(min(280px,100%),1fr) rather than a fixed column count: the same
   markup carries 3 items on one page and 4 on another, and auto-fit picks
   the row shape that doesn't orphan the last card. The min() guard stops
   the 280px floor from overflowing a 320px phone. */
.tile-grid{
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: var(--space-4);
}
/* Four-item grids: 2x2 rather than 3 + 1 orphan, until there is room for a
   clean row of four. Same reasoning as .problem-grid on the homepage. */
@media (min-width: 640px) and (max-width: 1339px){
  .tile-grid--4{
    grid-template-columns: repeat(2, 1fr);
    max-width: 940px;
    margin-inline: auto;
  }
}
@media (min-width: 1340px){
  .tile-grid--4{ grid-template-columns: repeat(4, 1fr); }
}

.tile{
  padding: clamp(20px, 2vw, 26px);
  border-radius: var(--radius-md);
  display:grid;
  gap:10px;
  align-content:start;
}
.tile h3{
  font-size: 1.05rem;
  font-weight:600;
  letter-spacing:-0.01em;
  margin:0;
  color: var(--text-0);
}
.tile p{ margin:0; color: var(--text-1); font-size:0.94rem; }
.tile-icon{
  width:34px; height:34px;
  border-radius:10px;
  display:grid;
  place-items:center;
  font-size:0.82rem;
  font-weight:600;
  color: var(--primary);
  background: rgba(219,174,246,0.10);
  border:1px solid rgba(219,174,246,0.20);
}

/* ==========================
   Numbered steps
========================== */
.steps{
  display:grid;
  gap: var(--space-4);
  counter-reset: step;
  max-width: var(--content);
  margin-inline:auto;
}
/* Deliberately NOT .glass. That class owns ::before as an absolutely
   positioned, opacity:0 overlay, and .step needs ::before for its number
   badge. Sharing the pseudo-element meant overriding position, inset,
   background, opacity and border-radius one by one, and missing any single
   one broke the layout or hid the badge with no error anywhere. The surface
   below is the same as .glass, minus the pseudo-element. */
.step{
  display:grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: var(--space-4);
  align-items:start;
  padding: clamp(18px, 2vw, 24px);
  border-radius: var(--radius-md);
  background: var(--surface-0);
  border: var(--border-hairline) solid var(--stroke-0);
  box-shadow: var(--shadow-0);
}
.step::before{
  counter-increment: step;
  content: counter(step, decimal-leading-zero);
  font-size:0.8rem;
  font-weight:600;
  color: var(--primary);
  background: rgba(219,174,246,0.10);
  border:1px solid rgba(219,174,246,0.20);
  border-radius:10px;
  width:44px; height:44px;
  display:grid;
  place-items:center;
}
.step h3{
  font-size:1.05rem;
  font-weight:600;
  letter-spacing:-0.01em;
  margin:0 0 6px;
  color: var(--text-0);
}
.step p{ margin:0; color: var(--text-1); font-size:0.94rem; }

/* ==========================
   Q&A list: "what the agent asks"
========================== */
.asks{
  display:grid;
  gap: var(--space-2);
  max-width: var(--content);
  margin-inline:auto;
  list-style:none;
  padding:0;
}
.asks li{
  display:grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: var(--space-3);
  align-items:start;
  padding: 14px 18px;
  border-radius: var(--radius-sm);
  background: rgba(255,255,255,0.02);
  border: 1px solid var(--stroke-0);
  color: var(--text-1);
  font-size:0.95rem;
}
.asks li::before{
  content:"";
  width:8px; height:8px;
  margin-top:9px;
  border-radius:50%;
  background: rgba(219,174,246,0.55);
  box-shadow: 0 0 0 4px rgba(219,174,246,0.10);
}

/* ==========================
   Transcript
========================== */
.transcript{
  max-width: 720px;
  margin-inline:auto;
  padding: clamp(18px, 2vw, 26px);
  display:grid;
  gap: var(--space-3);
}
.t-turn{ display:grid; gap:5px; max-width: 82%; }
.t-turn .t-who{
  font-size:0.72rem;
  letter-spacing:0.04em;
  text-transform:uppercase;
  color: var(--text-2);
}
.t-turn p{
  margin:0;
  padding: 11px 15px;
  border-radius: 16px;
  font-size:0.94rem;
  line-height:1.55;
}
.t-agent{ justify-self:start; }
.t-agent p{
  background: linear-gradient(180deg, rgba(219,174,246,0.14), rgba(219,174,246,0.07));
  border:1px solid rgba(219,174,246,0.22);
  border-bottom-left-radius:6px;
  color: rgba(255,255,255,0.94);
}
.t-lead{ justify-self:end; text-align:right; }
.t-lead p{
  background: rgba(255,255,255,0.045);
  border:1px solid var(--stroke-0);
  border-bottom-right-radius:6px;
  color: var(--text-1);
  text-align:left;
}
.t-note{
  margin: var(--space-2) 0 0;
  font-size:0.82rem;
  color: var(--text-2);
  text-align:center;
}

/* ==========================
   Objections / FAQ (shared <details> styling)
========================== */
.qa{
  max-width: var(--content);
  margin-inline:auto;
  display:grid;
  gap: var(--space-2);
}
.qa details{
  border:1px solid var(--stroke-0);
  border-radius: var(--radius-sm);
  background: rgba(255,255,255,0.02);
  overflow:hidden;
}
.qa details[open]{ border-color: rgba(219,174,246,0.22); }
.qa summary{
  cursor:pointer;
  list-style:none;
  padding: 16px 52px 16px 18px;
  font-weight:500;
  color: var(--text-0);
  position:relative;
  font-size:0.98rem;
}
.qa summary::-webkit-details-marker{ display:none; }
.qa summary::after{
  content:"+";
  position:absolute;
  right:18px; top:50%;
  transform: translateY(-50%);
  color: var(--primary);
  font-size:1.15rem;
  line-height:1;
}
.qa details[open] summary::after{ content:"\2013"; }
.qa summary:focus-visible{ outline:none; box-shadow: var(--glow-0); }
.qa .qa-body{
  padding: 0 18px 18px;
  color: var(--text-1);
  font-size:0.94rem;
  max-width: 74ch;
}
.qa .qa-body p{ margin:0 0 10px; }
.qa .qa-body p:last-child{ margin-bottom:0; }

/* ==========================
   Stat strip
========================== */
.stat-strip{
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: var(--space-4);
  padding: clamp(22px, 2.4vw, 32px);
  border-radius: var(--radius-lg);
  border:1px solid var(--stroke-0);
  background: rgba(255,255,255,0.02);
}
.stat{ display:grid; gap:4px; text-align:center; }
.stat-num{
  font-size: clamp(1.6rem, 2.6vw, 2.2rem);
  font-weight:600;
  letter-spacing:-0.03em;
  color: var(--primary);
  line-height:1.1;
}
.stat-label{ font-size:0.85rem; color: var(--text-2); }

/* ==========================
   Callout
========================== */
.callout{
  max-width: var(--content);
  margin-inline:auto;
  padding: clamp(18px, 2vw, 24px);
  border-radius: var(--radius-md);
  border:1px solid rgba(219,174,246,0.20);
  background: linear-gradient(180deg, rgba(219,174,246,0.07), rgba(255,255,255,0.015));
  color: var(--text-1);
  font-size:0.94rem;
}
.callout strong{ color: var(--text-0); }
.callout p{ margin:0 0 8px; }
.callout p:last-child{ margin-bottom:0; }

/* ==========================
   Cross-links (internal linking)
========================== */
.xlinks{
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: var(--space-3);
}
.xlink{
  display:grid;
  gap:6px;
  align-content:start;
  padding: 18px 20px;
  border-radius: var(--radius-md);
  border:1px solid var(--stroke-0);
  background: rgba(255,255,255,0.02);
  text-decoration:none;
  transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
.xlink:hover{
  border-color: rgba(219,174,246,0.28);
  background: rgba(219,174,246,0.05);
  transform: translateY(-2px);
}
.xlink-title{
  font-weight:600;
  color: var(--text-0);
  font-size:0.98rem;
  letter-spacing:-0.01em;
}
.xlink-desc{ color: var(--text-2); font-size:0.87rem; line-height:1.5; }
.xlink-go{ color: rgba(219,174,246,0.92); font-size:0.85rem; font-weight:500; }

/* ==========================
   Final CTA
========================== */
.page-cta{
  text-align:center;
  max-width: 760px;
  margin-inline:auto;
  padding: clamp(32px, 4vw, 56px) clamp(20px, 3vw, 40px);
  border-radius: var(--radius-lg);
  border:1px solid rgba(219,174,246,0.18);
  background:
    radial-gradient(80% 120% at 50% 0%, rgba(59,16,128,0.32), rgba(59,16,128,0) 70%),
    rgba(255,255,255,0.02);
}
.page-cta h2{ margin-bottom: var(--space-3); }
.page-cta .lead{ margin-inline:auto; }
.page-cta .hero-actions{ justify-content:center; }

/* ==========================
   Industry hub grid
========================== */
.hub-grid{
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: var(--space-4);
}
.hub-card{
  display:grid;
  gap:10px;
  align-content:start;
  padding: clamp(20px, 2vw, 26px);
  border-radius: var(--radius-md);
  border:1px solid var(--stroke-0);
  background: rgba(255,255,255,0.02);
  text-decoration:none;
  transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
.hub-card:hover{
  border-color: rgba(219,174,246,0.28);
  background: rgba(219,174,246,0.05);
  transform: translateY(-2px);
}
.hub-card h3{
  margin:0;
  font-size:1.05rem;
  font-weight:600;
  letter-spacing:-0.01em;
  color: var(--text-0);
}
.hub-card p{ margin:0; color: var(--text-1); font-size:0.92rem; }
.hub-card .xlink-go{ margin-top:2px; }

/* ==========================
   Reveal: same feel as the homepage, without GSAP
========================== */
.r{
  opacity:0;
  transform: translateY(22px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
}
.r.in{ opacity:1; transform:none; }
@media (prefers-reduced-motion: reduce){
  .r{ opacity:1; transform:none; transition:none; }
}
/* If the observer never runs (JS off, or a crawler that executes nothing),
   the content must still be visible, otherwise the page is blank to it. */
.no-js .r{ opacity:1; transform:none; }

/* Sub-pages sit above the mobile action bar, same as the homepage. */
@media (max-width: 720px){
  body.subpage{ padding-bottom: 72px; }
}

/* ==========================
   Chip row: sibling industry links

   Four of the ten industry pages were reachable from only the hub, which
   leaves them a single internal link deep. Every industry page now links to
   all nine siblings, so no page in the set depends on one route to be found.
========================== */
.chiprow{
  display:flex;
  flex-wrap:wrap;
  gap:10px;
  max-width: var(--content);
  margin-inline:auto;
  justify-content:center;
}
.chiprow a{
  display:inline-flex;
  align-items:center;
  padding:9px 16px;
  border-radius: var(--radius-pill);
  border:1px solid var(--stroke-0);
  background: rgba(255,255,255,0.025);
  color: var(--text-1);
  text-decoration:none;
  font-size:0.9rem;
  transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}
.chiprow a:hover{
  border-color: rgba(219,174,246,0.30);
  background: rgba(219,174,246,0.07);
  color: var(--text-0);
}

/* ==========================================================================
   INTERACTION LAYER

   Ported from shashwatsharma.vercel.app, which runs Lenis + GSAP +
   ScrollTrigger. None of that comes across. These pages ship zero libraries
   and about 50 lines of inline JS, which is most of why they load the way
   they do, and the homepage already demonstrates what a WebGL/GSAP hero
   costs in Lighthouse. So each effect below is the CSS-and-vanilla
   equivalent of the reference behaviour, not the reference implementation.

   Fonts, colours and type scale are untouched: everything here is motion
   and pointer response built on the tokens already defined in styles.css.
   ========================================================================== */

/* ---- masked word reveal -------------------------------------------------
   The reference's signature move: words rise out of a clipping mask with a
   short stagger (gsap yPercent 108 -> 0, expo.out, 0.035s apart). Same
   curve and rhythm, done with a transition and a per-word delay.

   The shell needs vertical breathing room or the mask clips descenders and
   the italic serif accent; padding plus a negative margin buys it without
   changing layout. */
.w{
  display:inline-block;
  overflow:hidden;
  vertical-align:top;
  padding-bottom:0.12em;
  margin-bottom:-0.12em;
}
.wi{
  display:inline-block;
  transform: translateY(115%);
  transition: transform 1.05s cubic-bezier(.16,1,.3,1);
  will-change: transform;
}
.split.in .wi{ transform:none; }
/* JS off, or a crawler: the words must simply be there. */
.no-js .wi{ transform:none; }

/* ---- staggered children -------------------------------------------------
   Previously every .r revealed on its own trigger, so a four-card grid
   flashed in as one block. Children now inherit the parent's trigger and
   follow it in sequence, which is what makes a grid feel authored. */
.r-stagger > *{
  opacity:0;
  transform: translateY(20px);
  transition: opacity .65s var(--ease-out), transform .65s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.r-stagger.in > *{ opacity:1; transform:none; }
.no-js .r-stagger > *{ opacity:1; transform:none; }

/* ---- pointer spotlight on cards ----------------------------------------
   The reference lights one band at a time on hover. Same idea, finer grain:
   a highlight that tracks the pointer inside each card. --mx/--my are set
   by JS in percentages; the fallback centre keeps it sane before first move
   and on touch, where the layer simply never becomes visible. */
.tile, .step, .xlink, .hub-card, .stat-strip, .factcard, .transcript{
  position:relative;
  isolation:isolate;
}
.tile::after, .step::after, .xlink::after, .hub-card::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:-1;
  border-radius:inherit;
  pointer-events:none;
  opacity:0;
  transition:opacity .45s var(--ease);
  background: radial-gradient(
    260px circle at var(--mx, 50%) var(--my, 50%),
    rgba(219,174,246,0.13),
    rgba(219,174,246,0.05) 40%,
    transparent 72%);
}
@media (hover: hover) and (pointer: fine){
  .tile:hover::after, .step:hover::after,
  .xlink:hover::after, .hub-card:hover::after{ opacity:1; }
  .tile, .step{
    transition: border-color var(--dur-3) var(--ease), transform var(--dur-3) var(--ease-out);
  }
  .tile:hover, .step:hover{
    transform: translateY(-3px);
    border-color: rgba(219,174,246,0.22);
  }
  .asks li{
    transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
  }
  .asks li:hover{
    border-color: rgba(219,174,246,0.20);
    background: rgba(219,174,246,0.04);
  }
}

/* ---- magnetic CTA -------------------------------------------------------
   The reference's #hirePill: the button leans toward the pointer. Applied
   only to primary buttons, and only on a real pointer. --mgx/--mgy come
   from JS; composed with the existing :hover lift rather than replacing it,
   which is why the translate is a separate custom property. */
@media (hover: hover) and (pointer: fine){
  .page-hero .btn-primary, .page-cta .btn-primary{
    transform: translate(var(--mgx, 0px), var(--mgy, 0px));
  }
  .page-hero .btn-primary:hover, .page-cta .btn-primary:hover{
    transform: translate(var(--mgx, 0px), calc(var(--mgy, 0px) - 1px));
  }
}

/* ---- scroll progress ----------------------------------------------------
   These pages run long. A hairline at the top is the cheapest possible
   answer to "how much of this is left". */
.progress{
  position:fixed;
  top:0; left:0; right:0;
  height:2px;
  z-index:1200;
  transform-origin:0 50%;
  transform: scaleX(0);
  background: linear-gradient(90deg, rgba(219,174,246,0.35), var(--primary));
  pointer-events:none;
}

/* ---- header hides on the way down --------------------------------------
   Reference behaviour, and it earns its place here: the sticky header eats
   78px of a phone screen on a page this long. Only in pages.css, so the
   homepage keeps its own header behaviour untouched. */
.site-header{
  transition: transform .45s var(--ease-out), background .5s var(--ease-out),
              border-color .5s ease, backdrop-filter .5s ease;
}
.site-header.is-tucked{ transform: translateY(-102%); }

/* ---- FAQ accordion ------------------------------------------------------
   Native <details> snaps. JS animates the height instead; these rules just
   make the body animatable and stop the summary text jumping. */
.qa details .qa-body{ overflow:hidden; }
.qa summary{ user-select:none; }
.qa summary::after{ transition: transform .35s var(--ease), content 0s; }
.qa details[open] summary::after{ transform: translateY(-50%) rotate(180deg); }

/* ---- numbers count up ---------------------------------------------------
   Tabular figures so the width does not shimmer while the digits change. */
.stat-num, .factcard-num{ font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce){
  .wi{ transform:none; transition:none; }
  .r-stagger > *{ opacity:1; transform:none; transition:none; }
  .site-header.is-tucked{ transform:none; }
  .tile:hover, .step:hover{ transform:none; }
  .progress{ display:none; }
}

/* ==========================================================================
   EDITORIAL  (.editorial)   reference: eyeballs.co

   Only the colours and the typefaces are ours. The composition is theirs:
   no header bar at all, chrome pinned to the four corners, nothing in a box,
   one statement per screen at a size that leaves most of the screen empty,
   and headings that arrive out of focus and sharpen.

   That last one is the whole idea of that site. It is an agency about being
   impossible to overlook, so its type resolves into focus as you reach it.
   Two layers do it: the heading itself blurs from 14px to 0, and a second
   copy stays permanently soft behind it.
   ========================================================================== */

/* ---- no header. corners only. -------------------------------------------
   The reference has no header bar. Four fixed anchors, one per corner, and
   the whole screen belongs to the type. Below 1100px the corners would
   collide, so the normal header comes back. */
@media (min-width: 1100px){
  .editorial .site-header{ display:none; }
  .editorial .crumbs{ padding-top: clamp(120px, 13vw, 190px); }
}
.editorial .corner{
  position:fixed;
  z-index:950;
  display:none;
  font-size:0.82rem;
  letter-spacing:0.01em;
  color: var(--text-2);
  text-decoration:none;
  transition: color var(--dur-2) var(--ease), opacity .5s var(--ease);
}
.editorial .corner:hover{ color: var(--text-0); }
.editorial .corner-tl{ top: 30px; left: clamp(24px, 4vw, 64px); }
.editorial .corner-tr{ top: 26px; right: clamp(24px, 4vw, 64px); }
.editorial .corner-bl{ bottom: 30px; left: clamp(24px, 4vw, 64px); }
.editorial .corner-br{ bottom: 30px; right: clamp(24px, 4vw, 64px); }
.editorial .corner-tl{ display:none; gap: 22px; }
@media (min-width: 1100px){
  .editorial .corner{ display:block; }
  .editorial .corner-tl{ display:flex; }
  /* The corners are fixed, so any flowing text would otherwise run underneath
     them. Inset the column past the corner zone and keep the last section
     clear of the bottom row. The wider gutter is also what makes the page
     read as editorial rather than as a full-width app. */
  .editorial .container{ padding-inline: clamp(40px, 9vw, 180px); }
  .editorial main{ padding-bottom: 96px; }
}
/* The reference sets these as bare text, which works because its hero is short
   and vertically centred. Ours runs longer, so flowing copy passes behind the
   bottom pair. A quiet backdrop keeps both legible instead of letting them
   overlap into mush. */
.editorial .corner-bl,
.editorial .corner-br{
  padding: 8px 15px;
  border-radius: var(--radius-pill);
  background: rgba(5,5,7,0.72);
  border: 1px solid var(--stroke-0);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}
.editorial .corner-bl:hover,
.editorial .corner-br:hover{ border-color: rgba(219,174,246,0.24); }

.editorial .corner-tl a{ color: var(--text-2); text-decoration:none; }
.editorial .corner-tl a:hover{ color: var(--text-0); }
.editorial .corner-tr img{ height:26px; width:auto; display:block; }

/* ---- statements ---------------------------------------------------------
   clamp tops out at 6.2rem: the reference runs 72px on a 1280 viewport and
   keeps line-height at exactly 1, which is what makes a three-line statement
   read as a block rather than as a paragraph. */
.editorial .page-hero h1,
.editorial .section-head .h2{
  font-family: "DM Serif Display", Georgia, serif;
  font-weight:400;
  line-height:0.95;
  letter-spacing:-0.028em;
  text-wrap: balance;
  color: var(--text-0);
}
.editorial .page-hero h1{
  font-size: clamp(2.6rem, 7vw, 6.2rem);
  max-width: 15ch;
  margin: 0 0 clamp(20px, 2.4vw, 34px);
}
.editorial .section-head .h2{
  font-size: clamp(2.2rem, 5.6vw, 4.6rem);
  max-width: 17ch;
  margin-inline:auto;
}
.editorial .page-hero h1 .serif-accent{ color: var(--primary); }

/* ---- the lens -----------------------------------------------------------
   The reference holds every content block at blur(4px) and sharpens it as it
   reaches the reading zone, so scrolling reads as a lens travelling down the
   page: whatever you are meant to be reading is sharp, everything else is
   soft. It is a visibility agency, so the whole site is an eye test.

   Continuous, not a one-shot reveal: a block blurs again on the way out,
   which is what makes it feel like a moving circle rather than an entrance
   animation. The band is the middle ~72% of the viewport, generous on
   purpose, so only the far edges are ever soft and the page stays readable.

   .lensable is added by JS, never in the markup. Without it nothing is
   blurred, so a failed script costs the effect and not the legibility. */
.editorial .lensable{
  filter: blur(4px);
  opacity: 0.44;
  transition: filter .55s var(--ease-out), opacity .55s var(--ease-out);
  will-change: filter;
}
.editorial .lensable.lens{
  filter: blur(0px);
  opacity: 1;
}
/* The hero heading arrives from further out of focus, matching the reference's
   deeper blur on its opening statement. */
.editorial .page-hero h1.lensable{ filter: blur(12px); opacity:0.3; }
.editorial .page-hero h1.lensable.lens{ filter: blur(0px); opacity:1; }
.no-js .editorial .lensable{ filter:none; opacity:1; }

/* The echo lives inside the heading, so it inherits the face, size, weight,
   line-height and max-width and cannot wrap differently. isolation keeps the
   negative z-index inside the heading's own stacking context, which is what
   puts it behind the words but still above the page ground. */
.editorial .ghosted{ position:relative; isolation:isolate; }
.editorial .ghost{
  position:absolute;
  inset:0;
  z-index:-1;
  margin:0;
  pointer-events:none;
  user-select:none;
  filter: blur(11px);
  opacity:0;
  color: var(--primary);
  transform: translateX(-14px);
  transition: opacity 1.3s var(--ease-out);
}
.editorial .ghosted.in .ghost{ opacity:0.30; }
.no-js .editorial .ghost{ display:none; }

/* ---- one idea per screen ------------------------------------------------ */
@media (min-width: 900px){
  /* Full height belongs to the HERO ONLY. Giving every section min-height
     plus align-content:center made the leftover space become the gap, so the
     distance between one section's content and the next varied with how tall
     the content happened to be: measured at 1400px, gaps ran from 280px to
     626px down a single page. The reference does the same thing, and this is
     why: min-h on its opening and closing screens, uniform padding between.
     Uniform padding is the only way the rhythm stays a rhythm. */
  /* The hero still owns the screen, but at 90svh with centred content the
     leftover space landed below the copy and made the first gap 528px where
     every other was 224px. Lower min-height plus no bottom padding keeps the
     full-screen feel and hands most of that slack back. */
  .editorial main > .page-hero{
    min-height: 74svh;
    display:grid;
    align-content:center;
    padding-bottom: clamp(72px, 8vw, 132px);
  }
  .editorial main > .section:not(.page-hero){
    padding-block: clamp(72px, 8vw, 132px);
  }
  .editorial .section-head{ margin-bottom: clamp(56px, 6vw, 100px); }
}
.editorial .section-head.center .lead{
  font-size: clamp(1.05rem, 1.4vw, 1.3rem);
  max-width: 52ch;
  margin-inline:auto;
  color: var(--text-2);
}

/* ---- nothing in a box ---------------------------------------------------
   The reference has no cards at all. Every panel here becomes text on the
   page ground, separated by hairlines. */
.editorial .tile,
.editorial .step,
.editorial .xlink,
.editorial .hub-card,
.editorial .factcard,
.editorial .stat-strip,
.editorial .callout,
.editorial .qa details,
.editorial .asks li{
  background:transparent !important;
  border:none;
  box-shadow:none;
  border-radius:0;
}
.editorial .tile::after,
.editorial .step::after,
.editorial .xlink::after,
.editorial .hub-card::after{ display:none; }

.editorial .tile-grid{ gap:0; }
.editorial .tile{
  padding: clamp(26px, 3vw, 40px) clamp(0px, 1.6vw, 26px);
  border-top: 1px solid var(--stroke-0);
}
.editorial .tile-icon{
  background:none; border:none; width:auto; height:auto;
  color: var(--primary);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:0.72rem; letter-spacing:0.13em;
}
.editorial .steps{ gap:0; }
.editorial .step{
  border-top: 1px solid var(--stroke-0);
  padding: clamp(24px, 2.8vw, 38px) 0;
}
.editorial .step::before{
  background:none; border:none;
  color: var(--primary);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:0.72rem; letter-spacing:0.13em;
  width:auto; place-items:start;
}
.editorial .xlinks{ gap:0; }
.editorial .xlink{
  padding: clamp(22px, 2.4vw, 32px) clamp(0px, 1.4vw, 22px);
  border-top: 1px solid var(--stroke-0);
}
.editorial .xlink:hover{ transform:none; background:transparent; }
.editorial .xlink:hover .xlink-title{ color: var(--primary); }
.editorial .hub-grid{ gap:0; }
.editorial .hub-card{
  padding: clamp(24px, 2.6vw, 36px) clamp(0px, 1.4vw, 22px);
  border-top: 1px solid var(--stroke-0);
}
.editorial .hub-card:hover{ transform:none; background:transparent; }
.editorial .hub-card:hover h3{ color: var(--primary); }
.editorial .stat-strip{
  border-top:1px solid var(--stroke-0);
  border-bottom:1px solid var(--stroke-0);
  padding-block: clamp(34px, 4vw, 56px);
}
.editorial .stat-num,
.editorial .factcard-num{
  font-family:"DM Serif Display", Georgia, serif;
  font-weight:400;
  font-size: clamp(2.2rem, 3.8vw, 3.4rem);
}
.editorial .factcard{ padding:0; gap: clamp(22px,2.4vw,34px); }
.editorial .factcard-row{ border-bottom-color: var(--stroke-0); }
.editorial .callout{
  border-top:1px solid rgba(219,174,246,0.22);
  border-bottom:1px solid rgba(219,174,246,0.22);
  padding-block: clamp(26px,3vw,42px);
  padding-inline:0;
}
.editorial .qa details{ border-top:1px solid var(--stroke-0); }
.editorial .qa{ gap:0; }
.editorial .qa summary{ padding-inline:0 44px; font-size:1.05rem; }
.editorial .qa summary::after{ right:0; }
.editorial .qa .qa-body{ padding-inline:0; }
.editorial .asks{ gap:0; }
.editorial .asks li{
  border-top:1px solid var(--stroke-0);
  padding: 18px 0;
}
.editorial .page-cta{
  border:none;
  background:none;
  padding-inline:0;
}

@media (prefers-reduced-motion: reduce){
  .editorial .lensable{ filter:none; opacity:1; transition:none; }
  .editorial .ghost{ transition:none; }
}

/* ==========================================================================
   KINETIC  (.kinetic)   reference: shashwatsharma.vercel.app

   Its two structural signatures, in our colours:

   1. Numbered chapters. A mono index pinned to the section's top-left and a
      violet tag above the heading, so the page reads as a sequence rather
      than a stack.

   2. Lit bands. Full-bleed floods where exactly one is lit at a time, with a
      hard top and bottom edge and a short, dense glow spilling above and
      below. The reference's note on that glow is worth keeping: a neon tube
      reads as light because the room is dark, so the falloff has to be tight.
      Loose blur just hazes the type next to it.

   The reference uses #7C3AED for the flood. Ours is --accent-2 (#8B5CF6),
   which occupies the same role in this palette.
   ========================================================================== */

/* ---- chapter numbering -------------------------------------------------- */
.kinetic main > .section{ position:relative; }
.k-idx{
  position:absolute;
  top: clamp(18px, 3vh, 38px);
  left: clamp(20px, 4vw, 72px);
  z-index:5;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:0.68rem;
  letter-spacing:0.13em;
  text-transform:uppercase;
  color: var(--text-2);
  opacity:0.55;
}
.k-tag{
  display:block;
  margin-bottom: clamp(14px, 1.6vw, 22px);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:0.68rem;
  letter-spacing:0.13em;
  text-transform:uppercase;
  color: var(--primary);
}

/* ---- lit bands ----------------------------------------------------------
   Breaks the container to run edge to edge: 50vw either side of the centre,
   which is the standard full-bleed trick and survives any container width.
   `isolation` keeps the wash's z-index:-1 inside the band. */
.lit{
  position:relative;
  z-index:2;
  /* Full-bleed from a MEASURED viewport width, not 100vw. 100vw includes the
     scrollbar while the content box does not, so the usual
     `margin-inline: calc(50% - 50vw); width:100vw` breaks out about 7px too
     far and every one of these pages reported a horizontal overflow at every
     width. --vw is set from documentElement.clientWidth, which excludes the
     scrollbar; 100vw stays as the fallback for a no-JS render, where the
     small overspill is clipped by body{overflow-x:clip} anyway. */
  width: var(--vw, 100vw);
  margin-inline: calc(50% - (var(--vw, 100vw) / 2));
  border-top:1px solid var(--stroke-0);
}
.band{
  position:relative;
  isolation:isolate;
  cursor:default;
  min-height: clamp(220px, 30vh, 340px);
  display:grid;
  place-items:center;
  text-align:center;
  padding: clamp(30px, 4vh, 56px) clamp(24px, 6vw, 90px);
  border-bottom:1px solid var(--stroke-0);
}
.band__wash{
  position:absolute;
  inset:0;
  z-index:-1;
  opacity:0;
  background: var(--accent-2);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.42), inset 0 -1px 0 rgba(255,255,255,0.22);
  transition: opacity .5s var(--ease);
}
/* Tight falloff, per the reference: a short dense glow, not a soft blur. */
.band__wash::before,
.band__wash::after{
  content:"";
  position:absolute;
  left:0; right:0;
  height: clamp(48px, 8vh, 100px);
  pointer-events:none;
}
.band__wash::before{
  bottom:100%;
  background: linear-gradient(to top, rgba(139,92,246,0.78), rgba(139,92,246,0.18) 46%, rgba(139,92,246,0));
}
.band__wash::after{
  top:100%;
  background: linear-gradient(to bottom, rgba(139,92,246,0.78), rgba(139,92,246,0.18) 46%, rgba(139,92,246,0));
}
.band.is-lit .band__wash{ opacity:1; }

.band__in{ max-width: 58ch; }
.band__head{
  display:flex;
  align-items:flex-start;
  justify-content:center;
  gap:0.6em;
  margin-bottom:10px;
}
.band__n{
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:0.68rem;
  letter-spacing:0.13em;
  color: var(--primary);
  padding-top:0.6em;
  transition: color .6s var(--ease);
}
.band h3{
  margin:0;
  font-size: clamp(1.15rem, 1.9vw, 1.6rem);
  font-weight:600;
  letter-spacing:-0.02em;
  color: var(--text-0);
}
.band p{
  margin:0;
  color: var(--text-1);
  font-size:0.96rem;
}
/* On the lit band the type sits on violet, so it has to go bright. */
.band.is-lit h3{ color:#fff; }
.band.is-lit p{ color: rgba(255,255,255,0.90); }
.band.is-lit .band__n{ color: var(--primary); }
/* A hint that the band answers the pointer before it is the lit one. */
.band:not(.is-lit):hover h3{ color: var(--primary); }

@media (prefers-reduced-motion: reduce){
  .band__wash{ transition:none; }
}

/* ==========================================================================
   VERTICAL RHYTHM

   styles.css gives .h2 a flat 16px bottom margin, which is right at its
   original 2.2rem but absurd under a 4.6rem serif statement: measured, the
   editorial h2 sat 73px tall with 16px of air beneath it. Gaps have to scale
   with the type they follow, so they are set per treatment here.
   ========================================================================== */

/* ---- editorial: generous, because the type is enormous ------------------ */
.editorial .page-hero h1{ margin-bottom: clamp(26px, 3vw, 48px); }
.editorial .section-head .h2{ margin-bottom: clamp(22px, 2.4vw, 38px); }
.editorial .page-hero .lead + .lead{ margin-top: clamp(14px, 1.4vw, 20px); }
.editorial .hero-actions{ margin-top: clamp(32px, 3.4vw, 52px); }
.editorial .section-head .lead{ line-height: 1.6; }
/* Blocks inside a section need their own breathing room now that the section
   itself is centred and tall. */
.editorial .prose p{ margin-bottom: clamp(16px, 1.6vw, 24px); }
.editorial .stat{ padding-block: 6px; }

/* ---- kinetic: tighter, but not 16px ------------------------------------- */
.kinetic .page-hero h1{ margin-bottom: clamp(16px, 1.8vw, 26px); }
.kinetic .section-head .h2{ margin-bottom: clamp(14px, 1.3vw, 20px); }
.kinetic .section-head{ margin-bottom: clamp(36px, 4vw, 60px); }
.kinetic .page-hero .lead + .lead{ margin-top: clamp(12px, 1.2vw, 18px); }
.kinetic .hero-actions{ margin-top: clamp(24px, 2.6vw, 38px); }

/* ---- both: the section-head lead should not touch its heading ----------- */
.section-head .lead{ margin-top: 0; }

/* ---- kinetic: symmetric padding, and room for the pinned index ---------
   Asymmetric top/bottom padding made the first gap 241px where every other
   was 182px. Equal on both sides, and the hero keeps its tighter top so the
   h1 still sits high. */
.kinetic main > .section{ padding-block: clamp(64px, 7vw, 104px); }
.kinetic main > .page-hero{
  padding-block: clamp(28px, 3.5vw, 44px) clamp(64px, 7vw, 104px);
}

/* ---- the band block sits flush; give it air on both sides -------------- */
.lit{ margin-block: clamp(28px, 3.4vw, 56px) 0; }

/* ==========================================================================
   ONE COLUMN

   Measured at 1400px, a single editorial page had four different left edges
   (126, 313, 372, 378) and six different block widths. Headings sat centred
   at 378-1007 while the body ran 126-1259, and .prose was pinned to the
   container edge with nothing to align to. Nothing shared a reference line,
   which is what reads as "the alignment is off".

   Every block now sits on one centred column, so headings (centred text) and
   body (left-aligned text) share the same bounds and the same centre axis.
   Reading measure is preserved by giving prose its own narrower max-width
   INSIDE that column rather than by letting it start wherever it likes.

   .lit is deliberately excluded: it is the full-bleed band and must break out
   of the column, not sit in it.
   ========================================================================== */

.editorial{ --col: min(1080px, 100%); }
.kinetic{   --col: min(1160px, 100%); }

.editorial .section > .container > *:not(.lit),
.kinetic   .section > .container > *:not(.lit){
  max-width: var(--col);
  margin-inline: auto;
}

/* Blocks that carry their own max-width need it re-stated relative to the
   column, or their old value wins and they fall out of alignment again. */
.editorial .section-head.center,
.kinetic   .section-head.center{ max-width: var(--col); }

.editorial .prose,
.kinetic   .prose{
  max-width: min(72ch, var(--col));
  margin-inline: auto;
}
.editorial .asks, .kinetic .asks,
.editorial .qa, .kinetic .qa,
.editorial .callout, .kinetic .callout,
.editorial .steps, .kinetic .steps{ max-width: var(--col); }

.editorial .transcript,
.kinetic .transcript{ max-width: min(760px, var(--col)); }

.editorial .page-cta,
.kinetic .page-cta{ max-width: min(820px, var(--col)); }

/* The hero is a two-column layout and is meant to be left-anchored, so it
   keeps the full container width. */
.editorial .page-hero > .container,
.kinetic .page-hero > .container{ max-width: var(--container); }

/* The generic column rule above matches only DIRECT children of .container,
   so .lead (a grandchild, inside .section-head) is not covered by it. It used
   to inherit its position from .section-head.center's own 70ch max-width;
   now that the header spans the column, the lead's 70ch box sits at the left
   of it while its text is centred. Centre the box too. */
.section-head.center .lead{ margin-inline: auto; }

/* .prose IS a direct child, so the column rule at (0,4,0) beat the earlier
   .editorial .prose at (0,2,0) and the reading measure was lost: the prose
   ran the full 1080px column. Restated at matching specificity, after it. */
.editorial .section > .container > .prose,
.kinetic   .section > .container > .prose{
  max-width: min(70ch, var(--col));
  margin-inline: auto;
}
.editorial .section > .container > .transcript,
.kinetic   .section > .container > .transcript{ max-width: min(760px, var(--col)); }
.editorial .section > .container > .page-cta,
.kinetic   .section > .container > .page-cta{ max-width: min(820px, var(--col)); }

/* A centred heading spanning the full 1160px column produces lines too long
   to read as a statement. Kinetic headings keep a measure; editorial ones
   already have their own. */
.kinetic .section-head .h2{ max-width: 24ch; margin-inline: auto; }
