/* ==========================================================================
   agladze.org — Mikhail Agladze
   One design system: 4 surfaces, 2 accents, a single 1.25 fluid type scale.
   Hand-authored. No frameworks, no webfonts, no jQuery.
   ========================================================================== */

:root{
  --bg:        #070A0F;
  --bg-2:      #0B1018;
  --surface:   #101825;
  --surface-2: #16202F;
  --line:      rgba(255,255,255,.09);
  --line-2:    rgba(255,255,255,.16);

  --text:  #E9EFF8;
  --muted: #93A2B8;   /* 6.9:1 on --surface */
  --dim:   #8593A8;   /* 6.1:1 — the darker #64748B failed AA at body size */

  --accent:   #22D3EE;
  --accent-2: #F0B429;
  --glow:     rgba(34,211,238,.20);

  --t--1: clamp(.78rem, .76rem + .12vw, .84rem);
  --t-0:  clamp(1rem, .97rem + .16vw, 1.075rem);
  --t-1:  clamp(1.15rem, 1.09rem + .3vw, 1.35rem);
  --t-2:  clamp(1.4rem, 1.28rem + .6vw, 1.85rem);
  --t-3:  clamp(1.75rem, 1.5rem + 1.2vw, 2.6rem);
  --t-4:  clamp(2.4rem, 1.8rem + 3vw, 4.6rem);

  --sp:   1rem;
  --sp-2: 1.5rem;
  --sp-3: 2.5rem;
  --sp-4: 4rem;
  --sp-5: clamp(4rem, 3rem + 5vw, 7.5rem);
  --wrap: 1140px;
  --r:    14px;

  --sans: system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
@media (prefers-reduced-motion: reduce){ html{ scroll-behavior:auto; } }

body{
  margin:0; background:var(--bg); color:var(--text);
  font-family:var(--sans); font-size:var(--t-0); line-height:1.65;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}

img{ max-width:100%; height:auto; display:block; }
a{ color:var(--accent); text-underline-offset:.2em; text-decoration-thickness:1px; }
a:hover{ color:#7DE9F7; }
:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:4px; }

h1,h2,h3,h4{ line-height:1.12; margin:0; letter-spacing:-.022em; font-weight:650; text-wrap:balance; }
h2{ font-size:var(--t-3); }
h3{ font-size:var(--t-1); letter-spacing:-.015em; }
p{ margin:0 0 var(--sp); text-wrap:pretty; }

.wrap{ width:min(100% - 2.5rem, var(--wrap)); margin-inline:auto; }
@media (max-width:560px){ .wrap{ width:min(100% - 2rem, var(--wrap)); } }

.skip{
  position:absolute; top:0; left:0; z-index:100;
  background:var(--accent); color:#04222A; padding:.7rem 1.1rem;
  border-radius:0 0 var(--r) 0; font-weight:650; text-decoration:none;
  clip-path:inset(50%); white-space:nowrap;
}
.skip:focus{ clip-path:none; }

/* ---------- shared ---------- */
.kicker{
  font-size:var(--t--1); letter-spacing:.16em; text-transform:uppercase;
  color:var(--accent); font-weight:650; margin:0 0 .75rem;
}
.eyebrow{
  display:inline-flex; align-items:center; gap:.6rem;
  font-size:var(--t--1); letter-spacing:.13em; text-transform:uppercase;
  color:var(--muted); font-weight:600; margin:0 0 var(--sp-2);
}
.dot{ width:7px; height:7px; border-radius:50%; background:var(--accent); box-shadow:0 0 0 4px var(--glow); }

.btn{
  display:inline-flex; align-items:center; justify-content:center;
  padding:.85rem 1.5rem; border-radius:999px;
  border:1px solid var(--line-2); background:rgba(255,255,255,.04);
  color:var(--text); font-weight:600; font-size:var(--t-0); text-decoration:none;
  transition:background .18s ease, border-color .18s ease, transform .18s ease;
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
}
.btn:hover{ background:rgba(255,255,255,.09); border-color:var(--accent); color:var(--text); transform:translateY(-1px); }
.btn--primary{ background:var(--accent); border-color:var(--accent); color:#04222A; box-shadow:0 8px 34px -8px var(--glow); }
.btn--primary:hover{ background:#67E8F9; border-color:#67E8F9; color:#04222A; }
.btn--lg{ padding:1.05rem 2rem; font-size:var(--t-1); font-weight:650; }

/* ---------- nav ---------- */
.nav{
  position:sticky; top:0; z-index:50;
  background:rgba(7,10,15,.7);
  backdrop-filter:saturate(160%) blur(14px); -webkit-backdrop-filter:saturate(160%) blur(14px);
  border-bottom:1px solid var(--line);
}
.nav__in{ display:flex; align-items:center; justify-content:space-between; gap:var(--sp-2); min-height:64px; }
.brand{ display:inline-flex; align-items:center; gap:.6rem; color:var(--text); text-decoration:none; font-weight:650; letter-spacing:-.01em; }

/* ---- the mark: a neon brain, slow-pulsing ---------------------------------------
   Fixed 30px box so the nav can never reflow. The halo is the same geometry blurred
   behind the crisp core; only opacity + scale animate, both compositor-only, on a
   5.6s ease-in-out cycle — a heartbeat, not a strobe.                               */
.brand__id{ position:relative; width:30px; height:30px; flex:none; }
.brand__brain{
  position:absolute; inset:0; width:30px; height:30px; overflow:visible;
  color:var(--accent);
}
.brain__core{ opacity:.94; }
.brain__halo{
  color:var(--accent); opacity:.42;
  transform-box:view-box; transform-origin:50% 50%;
  animation:brainPulse 5.6s cubic-bezier(.45,0,.55,1) infinite;
  will-change:opacity, transform;
}
@keyframes brainPulse{
  0%,100%{ opacity:.30; transform:scale(.97); }
  50%    { opacity:.92; transform:scale(1.07); }
}
.brand:hover .brain__core,
.brand:focus-visible .brain__core{ opacity:1; }

.nav__links{ display:flex; gap:1.6rem; list-style:none; margin:0; padding:0; min-width:0; }
.nav__links li{ flex:none; }
.nav__links a{
  color:var(--muted); text-decoration:none; font-size:var(--t--1);
  font-weight:600; letter-spacing:.04em; text-transform:uppercase;
  padding:.3rem 0; border-bottom:1px solid transparent; transition:color .16s, border-color .16s;
}
.nav__links a:hover{ color:var(--text); border-bottom-color:var(--accent); }
@media (max-width:860px){
  .brand__txt{ display:none; }
  .nav__links{ gap:1.05rem; }
  .nav__links a{ font-size:.72rem; letter-spacing:.06em; }
}
/* Narrow phones: five anchors can't share a row with the brand. Two centred rows, and
   drop sticky — on a one-pager a sticky bar costs more viewport than it earns. */
@media (max-width:640px){
  .nav{ position:static; }
  .nav__in{ flex-direction:column; gap:.55rem; min-height:0; padding:.75rem 0; }
  .brand__txt{ display:inline; }
  .nav__links{ flex-wrap:wrap; justify-content:center; gap:0 .8rem; width:100%; }
  .nav__links a{ font-size:.64rem; letter-spacing:.04em; white-space:nowrap; padding:.62rem 0; }
  .brand{ padding:.3rem 0; }
  .social a{ padding:.45rem .3rem; }
  .foot a{ display:inline-block; padding:.45rem 0; }
}

/* ---------- hero — full bleed ---------- */
.hero{
  position:relative; isolation:isolate; overflow:hidden;
  min-height:clamp(560px, 86vh, 900px);
  display:flex; align-items:center;
  padding:clamp(3.5rem,3rem+6vw,7rem) 0 clamp(3rem,2.5rem+4vw,5.5rem);
}
.hero__art{ position:absolute; inset:0; z-index:-2; }
.hero__art img{ width:100%; height:100%; object-fit:cover; object-position:62% 50%; }
/* Scrim, not a panel edge: the image runs the full width and is graded down under the copy. */
.hero__scrim{
  position:absolute; inset:0; z-index:-1;
  background:
    linear-gradient(100deg, rgba(7,10,15,.97) 0%, rgba(7,10,15,.9) 26%, rgba(7,10,15,.62) 48%, rgba(7,10,15,.22) 72%, rgba(7,10,15,.42) 100%),
    linear-gradient(180deg, rgba(7,10,15,.8) 0%, rgba(7,10,15,0) 22%, rgba(7,10,15,0) 62%, rgba(7,10,15,.95) 100%);
}
.hero__in{ position:relative; }
.hero__in > *{ max-width:42rem; }
.hero__h1{ font-size:var(--t-4); font-weight:700; letter-spacing:-.035em; margin:0 0 var(--sp); line-height:1.02; }
.hero__tag{
  font-size:var(--t-2); font-weight:600; letter-spacing:-.02em; line-height:1.22;
  color:var(--text); margin:0 0 var(--sp-2); max-width:34rem;
}
.hero__lede{ font-size:var(--t-1); color:#C6D3E4; max-width:36rem; margin-bottom:var(--sp-3); }
.hero__cta{ display:flex; flex-wrap:wrap; gap:.85rem; }
@media (max-width:720px){ .br-lg{ display:none; } }

/* ---------- proof bar ---------- */
.stats{ border-block:1px solid var(--line); background:var(--bg-2); }
.stats__grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-2); padding:var(--sp-3) 0; }
.stat{ display:flex; flex-direction:column; gap:.4rem; position:relative; padding-left:var(--sp); }
.stat::before{ content:""; position:absolute; left:0; top:.25rem; bottom:.25rem; width:2px; background:linear-gradient(180deg,var(--accent),transparent); border-radius:2px; }
.stat__n{ font-size:var(--t-3); font-weight:700; letter-spacing:-.03em; line-height:1; color:var(--text); font-variant-numeric:tabular-nums; }
.plus{ color:var(--accent); }
.stat__l{ font-size:var(--t--1); color:var(--muted); line-height:1.45; }
.stat__l em{ color:var(--text); font-style:normal; font-weight:650; }
@media (max-width:820px){ .stats__grid{ grid-template-columns:repeat(2,1fr); gap:var(--sp-2) var(--sp); } }
@media (max-width:420px){ .stats__grid{ grid-template-columns:1fr; } }

/* ---------- sections ---------- */
.sec{ padding:var(--sp-5) 0; position:relative; }
.sec--alt{ background:var(--bg-2); border-block:1px solid var(--line); }
.sec__head{ max-width:46rem; margin-bottom:var(--sp-4); }
.sec__sub{ color:var(--muted); font-size:var(--t-1); margin-top:var(--sp); margin-bottom:0; }

/* section band imagery — a motif behind the content so the eye never hits a flat wall */
.sec--band{ isolation:isolate; overflow:hidden; }
.band__art{ position:absolute; inset:0; z-index:-2; }
.band__art img{ width:100%; height:100%; object-fit:cover; opacity:.4; }
.band__art--soft img{ opacity:.40; }
.sec--band::after{
  content:""; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(180deg, var(--bg) 0%, rgba(7,10,15,.72) 30%, rgba(7,10,15,.78) 70%, var(--bg) 100%);
}
.sec--band.sec--alt::after{
  background:linear-gradient(180deg, var(--bg-2) 0%, rgba(11,16,24,.76) 28%, rgba(11,16,24,.8) 72%, var(--bg-2) 100%);
}
.band__in{ position:relative; }

/* ---------- capability cards ---------- */
.cards{ display:grid; grid-template-columns:repeat(3,1fr); gap:var(--sp-2); }
@media (max-width:940px){ .cards{ grid-template-columns:1fr; max-width:34rem; } }
.card{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden; display:flex; flex-direction:column;
  transition:border-color .22s ease, transform .22s ease, box-shadow .22s ease;
}
.card:hover{ border-color:var(--line-2); transform:translateY(-3px); box-shadow:0 18px 50px -30px var(--glow); }
.card__art{ aspect-ratio:16/10; overflow:hidden; border-bottom:1px solid var(--line); background:#0A0F17; }
.card__art img{ width:100%; height:100%; object-fit:cover; opacity:.92; }
.card__body{ padding:var(--sp-2); }
.card__body h3{ margin-bottom:.6rem; }
.card__body p{ color:var(--muted); font-size:var(--t--1); line-height:1.6; }
.ticks{ list-style:none; margin:var(--sp) 0 0; padding:0; display:flex; flex-direction:column; gap:.45rem; }
.ticks li{ position:relative; padding-left:1.35rem; font-size:var(--t--1); color:#B6C4D6; }
.ticks li::before{ content:""; position:absolute; left:0; top:.55em; width:6px; height:6px; border-radius:50%; background:var(--accent); opacity:.85; }

/* ---------- work ---------- */
.work{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:var(--sp-4); }
.work__item{
  display:grid; grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr); gap:var(--sp-3);
  align-items:start;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden;
}
.work__item--flip .work__media{ order:2; }
.work__media{ margin:0; height:100%; min-height:240px; background:#0A0F17; border-right:1px solid var(--line); }
.work__item--flip .work__media{ border-right:0; border-left:1px solid var(--line); }
.work__media img{ width:100%; height:100%; object-fit:cover; opacity:.95; }
.work__body{ padding:var(--sp-3) var(--sp-3) var(--sp-3) 0; }
.work__item--flip .work__body{ padding:var(--sp-3) 0 var(--sp-3) var(--sp-3); }
.work__meta{ display:flex; flex-wrap:wrap; align-items:baseline; gap:.5rem 1rem; margin-bottom:.75rem; }
.work__yr{ font-family:var(--mono); font-size:var(--t--1); color:var(--accent); letter-spacing:.04em; }
.work__role{ font-size:var(--t--1); color:var(--dim); }
.work__body h3{ margin-bottom:var(--sp); }
.work__body p{ color:var(--muted); }
/* The lead engagement carries the architecture diagram, which needs the full card width —
   a 980-unit viewBox in a ~560px column would force a horizontal scroll. Stack it instead,
   which also gives the flagship case study a deliberately more prominent treatment. */
.work__item--lead{ grid-template-columns:1fr; }
.work__item--lead .work__media{ aspect-ratio:24/7; min-height:0; border-right:0; border-bottom:1px solid var(--line); }
.work__item--lead .work__body{ padding:var(--sp-3); }
@media (max-width:900px){
  .work__item--lead .work__media{ aspect-ratio:16/9; }
  .work__item, .work__item--flip{ grid-template-columns:1fr; gap:0; }
  .work__media, .work__item--flip .work__media{ order:0; min-height:0; aspect-ratio:16/9; border:0; border-bottom:1px solid var(--line); }
  .work__body, .work__item--flip .work__body{ padding:var(--sp-2); }
}

.chips{ list-style:none; display:flex; flex-wrap:wrap; gap:.45rem; margin:var(--sp) 0 0; padding:0; }
.chips li{
  font-family:var(--mono); font-size:.76rem;
  padding:.32rem .7rem; border-radius:999px;
  border:1px solid var(--line-2); background:rgba(255,255,255,.03); color:#AFC0D4;
}

/* ---------- architecture diagram ---------- */
.diagram{
  margin:var(--sp-2) 0; padding:var(--sp) var(--sp) .5rem;
  border:1px solid var(--line); border-radius:var(--r);
  background:linear-gradient(180deg, rgba(34,211,238,.05), rgba(255,255,255,.015));
  overflow-x:auto;
}
.diagram__svg{ width:100%; min-width:560px; height:auto; display:block; }
.diagram figcaption{ margin-top:.6rem; font-size:var(--t--1); color:var(--dim); line-height:1.5; }
.d-tier{ fill:var(--accent); font:650 12px var(--mono); letter-spacing:.12em; }
.d-tier--a{ fill:var(--accent-2); }
.d-hd{ fill:#E9EFF8; font:600 15px var(--sans); }
.d-sub{ fill:#8593A8; font:400 12.5px var(--sans); }
.d-esc{ fill:#8593A8; font:500 12px var(--mono); letter-spacing:.04em; }
.d-esc--a{ fill:var(--accent-2); }

/* ---- the cascade runs -------------------------------------------------------------
   Documents enter, most resolve at Tier 1 and peel onto the rail, fewer reach Tier 2,
   fewest reach the model. The thesis performed instead of asserted. Once, on view,
   then it settles back to the static diagram — which stays the resting state.        */
.tok{
  fill:var(--accent); opacity:0;
  transform-box:view-box; transform-origin:0 0;
  transform:translate(67px,112px);
}
.tok--3{ fill:var(--accent-2); }
.diagram.run .tok--1{ animation:tok-t1 2.5s cubic-bezier(.42,0,.58,1) both; }
.diagram.run .tok--2{ animation:tok-t2 2.5s cubic-bezier(.42,0,.58,1) both; }
.diagram.run .tok--3{ animation:tok-t3 2.5s cubic-bezier(.42,0,.58,1) both; }

@keyframes tok-t1{
  0%   { transform:translate(67px,112px);  opacity:0; }
  7%   { opacity:.85; }
  28%  { transform:translate(280px,112px); opacity:.85; }
  40%  { transform:translate(280px,214px); opacity:.85; }
  90%  { transform:translate(930px,214px); opacity:.85; }
  100% { transform:translate(930px,214px); opacity:0; }
}
@keyframes tok-t2{
  0%   { transform:translate(67px,112px);  opacity:0; }
  7%   { opacity:.85; }
  20%  { transform:translate(280px,112px); }
  36%  { transform:translate(532px,112px); opacity:.85; }
  48%  { transform:translate(532px,214px); opacity:.85; }
  90%  { transform:translate(930px,214px); opacity:.85; }
  100% { transform:translate(930px,214px); opacity:0; }
}
@keyframes tok-t3{
  0%   { transform:translate(67px,112px);  opacity:0; }
  7%   { opacity:.9; }
  18%  { transform:translate(280px,112px); }
  32%  { transform:translate(532px,112px); }
  46%  { transform:translate(784px,112px); opacity:.9; }
  58%  { transform:translate(784px,214px); opacity:.9; }
  90%  { transform:translate(930px,214px); opacity:.9; }
  100% { transform:translate(930px,214px); opacity:0; }
}
/* Reduced motion: the tokens simply never exist. The static diagram is already the
   final state, so nothing is lost and nothing needs re-describing. */
@media (prefers-reduced-motion: reduce){ .toks{ display:none; } }

/* ---------- writing / shelf ---------- */
.shelf{ display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-2); }
@media (max-width:980px){ .shelf{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:560px){ .shelf{ grid-template-columns:1fr; } }
.vol{
  border:1px solid var(--line); border-radius:var(--r); overflow:hidden;
  background:rgba(16,24,37,.82); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  display:flex; flex-direction:column;
  transition:transform .22s ease, border-color .22s ease, box-shadow .22s ease;
}
.vol:hover{ transform:translateY(-4px); border-color:var(--line-2); box-shadow:0 20px 50px -32px var(--glow); }
.vol__art{ aspect-ratio:1/1; background:#0A0F17; border-bottom:1px solid var(--line); }
.vol__art img{ width:100%; height:100%; object-fit:cover; opacity:.9; }
.vol__body{ padding:var(--sp-2) var(--sp); }
.vol__cat{
  font-size:var(--t--1); letter-spacing:.14em; text-transform:uppercase;
  color:var(--accent); font-weight:650; margin:0 0 .85rem;
}
.vol__list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.7rem; }
.vol__list li{
  font-size:var(--t--1); font-weight:600; color:var(--text); line-height:1.3;
  padding-left:.8rem; border-left:2px solid rgba(34,211,238,.45);
}
.vol__list span{ display:block; font-weight:400; color:var(--dim); margin-top:.15rem; }
.books__note{ margin-top:var(--sp-3); color:var(--muted); font-size:var(--t--1); }

/* ---------- about ---------- */
.about{ display:grid; grid-template-columns:1.6fr 1fr; gap:var(--sp-4); align-items:start; }
@media (max-width:900px){ .about{ grid-template-columns:1fr; gap:var(--sp-3); } }
.about__text h2{ margin-bottom:var(--sp-2); }
.about__text p{ color:var(--muted); }
.about__side{ display:flex; flex-direction:column; gap:var(--sp); }
.panel{
  padding:var(--sp-2); border:1px solid var(--line); border-radius:var(--r);
  background:rgba(16,24,37,.82); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
}
/* ---- About portrait: duotone resolving into full colour ---------------------------
   One image. The tint is a blend layer, so the "resolve" animates opacity only and
   costs zero extra bytes. Fixed aspect-ratio box + width/height attrs = zero CLS.    */
.portrait{
  position:relative; margin:0;
  border:1px solid var(--line); border-radius:var(--r); overflow:hidden;
  background:#0A0F17; aspect-ratio:1/1; isolation:isolate;
}
.portrait img{
  width:100%; height:100%; object-fit:cover; object-position:50% 42%;
  transform:translateY(0) scale(1.06); will-change:transform;
}
.portrait__tint{
  position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(150deg, #22D3EE 0%, #2A5BD7 55%, #101825 100%);
  mix-blend-mode:color; opacity:1;
  transition:opacity .6s cubic-bezier(.16,1,.3,1) .12s;
}
.portrait.in .portrait__tint{ opacity:0; }

/* Parallax only where scroll-driven animation exists; elsewhere it is simply absent. */
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference) and (min-width:901px){
    @keyframes portrait-drift{ from{ transform:translateY(-14px) scale(1.06); } to{ transform:translateY(14px) scale(1.06); } }
    .portrait img{ animation:portrait-drift linear both; animation-timeline:view(); animation-range:entry 10% exit 90%; }
  }
}
.panel__h{ font-size:var(--t--1); letter-spacing:.14em; text-transform:uppercase; color:var(--accent); margin-bottom:var(--sp); }
.plain{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.75rem; }
.plain li{ font-size:var(--t--1); color:var(--muted); line-height:1.55; }
.plain strong{ color:var(--text); font-weight:650; display:block; }

.stack__h{ margin:var(--sp-5) 0 var(--sp-2); font-size:var(--t-2); }
.stack{ display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-2); }
@media (max-width:900px){ .stack{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:560px){ .stack{ grid-template-columns:1fr; } }
.stack__grp h4{ font-size:var(--t--1); letter-spacing:.13em; text-transform:uppercase; color:var(--dim); margin-bottom:.85rem; font-weight:650; }
.stack__grp .chips{ margin-top:0; }

/* ---------- contact ---------- */
.contact{ position:relative; isolation:isolate; overflow:hidden; padding:var(--sp-5) 0; text-align:center; }
.contact__art{ position:absolute; inset:0; z-index:-2; }
.contact__art img{ width:100%; height:100%; object-fit:cover; opacity:.55; }
.contact::after{
  content:""; position:absolute; inset:0; z-index:-1;
  background:radial-gradient(95% 130% at 50% 100%, rgba(7,10,15,.45) 0%, rgba(7,10,15,.85) 55%, var(--bg) 100%);
}
.contact__in{ position:relative; max-width:44rem; margin-inline:auto; }
.contact__lede{ color:#C6D3E4; font-size:var(--t-1); margin-block:var(--sp-2) var(--sp-3); }
.contact .btn--lg{ word-break:break-word; }
.social{ list-style:none; display:flex; flex-wrap:wrap; justify-content:center; gap:var(--sp-2); margin:var(--sp-3) 0 0; padding:0; }
.social a{ display:inline-flex; align-items:center; gap:.5rem; color:var(--muted); text-decoration:none; font-size:var(--t--1); font-weight:600; transition:color .16s ease; }
.social a:hover{ color:var(--accent); }
.social svg{ width:18px; height:18px; flex:none; }

/* ---------- footer ---------- */
.foot{ border-top:1px solid var(--line); background:var(--bg); padding:var(--sp-2) 0; }
.foot__in{ display:flex; flex-wrap:wrap; gap:var(--sp); justify-content:space-between; align-items:center; }
.foot p{ margin:0; font-size:var(--t--1); color:var(--dim); }
.foot a{ color:var(--muted); text-decoration:none; }
.foot a:hover{ color:var(--accent); }

/* Visually hidden, still in the accessibility tree — and out of flow, so injecting the full
   quote set into it cannot shift the page. */
.sr-only{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0;
}

/* ---------- the reveal ------------------------------------------------------------
   position:fixed throughout, so the overlay is outside layout and contributes zero CLS.
   Two open modes: "hover" (pointer/keyboard — scrim stays click-through so the mouse can
   keep moving) and "tap" (touch — scrim becomes the dismiss target and the ✕ appears).  */
.reveal{ position:fixed; inset:0; z-index:80; pointer-events:none; }
.reveal__scrim{
  position:absolute; inset:0; opacity:0;
  background:rgba(7,10,15,.46);
  backdrop-filter:blur(6px) saturate(.78); -webkit-backdrop-filter:blur(6px) saturate(.78);
  transition:opacity .46s cubic-bezier(.16,1,.3,1);
}
/* The stage lays out plate + quote. Flex rather than absolute positioning, so the quote is
   placed relative to the plate's real box instead of a magic number that drifts per viewport. */
.reveal__stage{
  position:absolute; inset:0; display:flex; align-items:center;
  gap:clamp(1.25rem, 3.5vw, 3.25rem);
  padding-right:clamp(1.25rem, 5vw, 4rem);
}
.reveal__plate{
  --x-in:-96%; --x-out:-7%;
  position:relative; flex:none; margin:0;
  width:min(52vw, 700px);
  opacity:0; filter:blur(16px);
  transform:translate3d(var(--x-in), 0, 0);
  /* Feather EVERY edge, weighted to his face. A rectangle with four hard cuts reads as a
     banner dropped on the page; dissolving all four edges is what makes it read as a
     projection. One radial gradient, so no mask-composite support question. */
  /* Radii are ~the box half-dimensions on purpose: the ellipse must actually REACH the edges,
     or the stops all land inside the box and nothing feathers at all. 72%/62% puts the top and
     bottom edges at .81 of the ray and the right edge at .97 — both inside the fade. */
  -webkit-mask-image:radial-gradient(72% 62% at 30% 50%, #000 40%, rgba(0,0,0,.9) 62%, transparent 97%);
          mask-image:radial-gradient(72% 62% at 30% 50%, #000 40%, rgba(0,0,0,.9) 62%, transparent 97%);
  transition:transform .74s cubic-bezier(.16,1,.3,1),
             filter    .62s cubic-bezier(.16,1,.3,1),
             opacity   .40s cubic-bezier(.16,1,.3,1);
  will-change:transform, filter, opacity;
}
.reveal__plate img{ display:block; width:100%; height:auto; }
.reveal__close{
  position:absolute; top:1.1rem; right:1.1rem; width:44px; height:44px;
  display:none; place-items:center;
  border:1px solid var(--line-2); border-radius:50%;
  background:rgba(7,10,15,.72); color:var(--muted); cursor:pointer;
  -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
}
.reveal__close svg{ width:20px; height:20px; }

/* ---- the thought stream ---- */
.reveal__quote{
  position:relative; flex:1 1 auto; min-width:0; max-width:34rem;
  /* Purely a centring anchor. The layers inside are absolutely positioned and centred on this
     box, so a 4-word aphorism and a 56-word painpoint both balance on the same axis and
     NEITHER can resize anything. The set is meant to grow, so nothing here is sized to the
     current content. */
  height:15rem;
  opacity:0; transform:translate3d(10px, 0, 0);
  transition:opacity .42s cubic-bezier(.16,1,.3,1) .16s,
             transform .56s cubic-bezier(.16,1,.3,1) .16s;
}
/* A soft local darkening, because the blurred page behind is not uniformly dark — the hero's
   amber starburst sits right where this text lands. Guarantees legibility without a hard card. */
/* Sized and weighted from measurement, not taste: against the brightest backdrop pixel (the
   hero's amber starburst bleeding through the blur) the gloss and byline were falling to
   3.2:1 and 2.7:1. This panel is what carries them back over AA. */
/* A blurred solid slab rather than a radial gradient. The gradient's dense core covered the
   quote but had already fallen off by the byline's row, which measured 3.6:1 (desktop) and
   2.3:1 (mobile, over the CTA's cyan glow). A slab covers every row equally and its blur
   keeps the edges soft. It lives on the LAYER, not the container, so it always matches the
   height of the quote actually being shown — a 56-word painpoint gets a taller backdrop. */
.q__layer::before{
  content:""; position:absolute; inset:-1.75rem -2.25rem; z-index:-1;
  border-radius:1.75rem; background:rgba(7,10,15,.88); filter:blur(20px);
}
/* The off layer is display:none, not merely transparent or visibility:hidden. Both of those
   still keep a layout box, and the shift API counts the TEXT reflowing inside it — reserving
   the blockquote's height was not enough, because the line boxes themselves move. Only
   display:none removes the layout entirely, which makes re-showing an appearance rather than
   a shift. Measured across three ticker beats: 0.00163 -> 0.00000.
   The fade is therefore sequenced in JS (display, then a frame, then opacity). */
.q__layer{
  position:absolute; left:0; right:0; top:50%; transform:translateY(-50%);
  display:none; opacity:0;
  /* durations come from the JS constants so there is one source of truth for the feel */
  transition:opacity var(--q-fade-out, 800ms) ease-in;
}
.q__layer.is-on{ display:block; }
.q__layer.is-lit{ opacity:1; transition:opacity var(--q-fade-in, 1200ms) ease-out; }
/* No reserved heights: with the off layer at display:none, a re-shown layer has no previous
   rect to be compared against, so content of any length is shift-free on its own. Sizing is
   scaled to length instead — a four-word aphorism deserves display size, a fifty-word
   painpoint is body copy. Tier is set on the hidden layer, so it costs nothing. */
.q__text{
  margin:0; font-size:var(--t-1); line-height:1.45; font-weight:500;
  color:var(--text); text-wrap:balance;
}
.q__layer[data-len="s"] .q__text{ font-size:var(--t-2); }
.q__layer[data-len="l"] .q__text{ font-size:var(--t-0); line-height:1.55; text-wrap:pretty; }
/* Kept deliberately though no entry currently uses this type: the painpoint→solution lines
   moved to the capability modals, and if any come back to the stream they are prose, not
   sayings — curly quotes around "Painpoint: … We solve it by …" read as a misquotation. */
.q__layer[data-type="painpoint-solution"] .q__text::before,
.q__layer[data-type="painpoint-solution"] .q__text::after{ content:none; }
.q__text::before{ content:"\201C"; color:var(--accent); margin-right:.1em; }
.q__text::after { content:"\201D"; color:var(--accent); margin-left:.06em; }
/* The byline belongs to the QUOTE and sits tight under it, as one unit. The gloss is
   Mikhail's reading of someone else's words and is pushed clearly below and inset behind its
   own label — nobody should be able to read it as something Clausewitz or Breiman said. */
.q__by{
  margin:.7rem 0 0; font-size:var(--t--1); font-weight:600; letter-spacing:.04em;
  text-transform:uppercase; color:#C6D3E4;   /* --dim and --muted both measured under AA here */
}
.q__by::before{ content:"— "; }
.q__by:empty{ visibility:hidden; }

.q__gloss{
  margin:1.6rem 0 0; border-left:2px solid var(--accent); padding-left:.85rem;
}
.q__gloss[hidden]{ display:none; }
.q__gloss-eyebrow{
  margin:0 0 .3rem; font-size:.7rem; font-weight:700;
  letter-spacing:.13em; text-transform:uppercase; color:var(--accent);
}
.q__gloss-text{
  margin:0; font-size:var(--t--1); line-height:1.55; color:var(--muted);
}

:root[data-reveal] .reveal__scrim{ opacity:1; }
:root[data-reveal] .reveal__plate{
  opacity:1; filter:blur(0); transform:translate3d(var(--x-out), 0, 0);
}
:root[data-reveal] .reveal__quote{ opacity:1; transform:none; }
/* Touch only: the overlay becomes interactive so tap-away dismisses. */
:root[data-reveal="tap"] .reveal{ pointer-events:auto; }
:root[data-reveal="tap"] .reveal__close{ display:grid; }

@media (max-width:900px){
  /* Phone/tablet: the quote goes BELOW the plate, and the plate centres instead of bleeding
     off the left — a half-off-screen photo on a 390px viewport is just a cropped photo. */
  .reveal__stage{
    flex-direction:column; justify-content:flex-start;
    gap:clamp(1rem, 3vh, 1.75rem);
    padding:max(3.5rem, 7vh) clamp(1rem, 5vw, 2rem) clamp(1rem, 4vh, 2rem);
  }
  .reveal__quote{ flex:none; max-width:34rem; height:19rem; width:100%; }
  /* Top-aligned here, not centred: a phone has no room to spare, and a centred layer that is
     taller than its box overflows UPWARD into the photo. Measured — the longest quote+gloss
     overlapped the plate by 16px before this. Downward overflow is the only safe direction. */
  .q__layer{ top:0; transform:none; }
  .q__layer::before{ inset:-1.25rem -1.5rem; }
}
@media (max-width:640px){
  .reveal__plate{
    --x-in:-108%; --x-out:0%; width:min(84vw, 460px);   /* smaller plate buys the text room */
    /* Vertical radius deliberately BELOW 50% of the box so the top and bottom edges land late
       on the ray — at 66% they sat at .76 and still read as a hard cut on a phone. */
    -webkit-mask-image:radial-gradient(80% 56% at 44% 50%, #000 40%, rgba(0,0,0,.88) 64%, transparent 99%);
            mask-image:radial-gradient(80% 56% at 44% 50%, #000 40%, rgba(0,0,0,.88) 64%, transparent 99%);
  }
}

/* ---------- motion ---------- */
.rise{ opacity:0; transform:translateY(16px); transition:opacity .6s ease, transform .6s ease; }
.rise.in{ opacity:1; transform:none; }
@media (prefers-reduced-motion: reduce){
  .rise{ opacity:1; transform:none; transition:none; }
  /* Final state immediately. The tint layer is driven by a JS-added class that never
     arrives under reduce, so it must be resolved here or the portrait would sit
     permanently duotone. */
  .portrait__tint{ opacity:0 !important; transition:none !important; }
  .portrait img{ transform:none !important; animation:none !important; }
  .brain__halo{ animation:none !important; opacity:.55 !important; transform:none !important; }
  /* No slide, no focus-pull: the plate is already at its final position and simply fades.
     These survive the blanket `*` duration clamp below on specificity, not source order. */
  .reveal__plate{
    transform:translate3d(var(--x-out), 0, 0) !important;
    filter:none !important;
    transition:opacity .18s linear !important;
  }
  .reveal__scrim{ transition:opacity .18s linear !important; }
  /* The stream still advances; it just doesn't churn. No slide-in, no per-quote crossfade. */
  .reveal__quote{ transform:none !important; transition:opacity .18s linear !important; }
  .q__layer{ transition:none !important; }
  *,*::before,*::after{ animation-duration:.001ms !important; transition-duration:.001ms !important; }
}
/* Below 900px: avatar stays, parallax is dropped (small viewports scroll fast enough
   that parallax reads as jitter). The portrait itself remains — it's the honest one. */
@media (max-width:900px){ .portrait img{ animation:none; transform:none; } }

/* ---------- print ---------- */
@media print{
  .nav,.hero__art,.hero__scrim,.contact__art,.band__art,.skip{ display:none !important; }
  body{ background:#fff; color:#000; }
  .sec,.contact,.hero{ padding:1rem 0; min-height:0; }
}
