@font-face {
  font-family: 'B612 Mono';
  src: url('../fonts/B612Mono-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'B612 Mono';
  src: url('../fonts/B612Mono-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'B612 Mono';
  src: url('../fonts/B612Mono-Italic.ttf') format('truetype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'B612 Mono';
  src: url('../fonts/B612Mono-BoldItalic.ttf') format('truetype');
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/IBMPlexSans-italic-cyrillic.woff2') format('woff2');
  font-weight: 100 700;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/IBMPlexSans-italic-latin.woff2') format('woff2');
  font-weight: 100 700;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/IBMPlexSans-normal-cyrillic-ext.woff2') format('woff2');
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/IBMPlexSans-normal-cyrillic.woff2') format('woff2');
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/IBMPlexSans-normal-latin-ext.woff2') format('woff2');
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/IBMPlexSans-normal-latin.woff2') format('woff2');
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; overflow: hidden; }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* The document itself never scrolls — every page's real content lives
   inside .page-scroll, a full-viewport-height inner container that
   does the actual scrolling. This is what keeps the fixed topbar's
   position perfectly consistent everywhere: it lives OUTSIDE
   .page-scroll as a direct sibling, so it's always positioned against
   the true, un-narrowed viewport — a scrollbar appearing on one page's
   .page-scroll and not another's (e.g. the landing page, which never
   scrolls) can no longer shift where the topbar sits, because the
   scrollbar now only ever affects .page-scroll's own inner width, not
   the fixed topbar's containing block. See js/page-scroll.js for the
   companion script that keeps #fragment links working under this
   setup (native browser anchor-scrolling only scrolls the document
   itself, which no longer scrolls here). */
.page-scroll {
  height: 100vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
body {
  background: var(--bg);
  color: var(--ink);
  font-family: 'B612 Mono', ui-monospace, monospace;
  text-transform: uppercase;
}
a { color: var(--ink); text-decoration: none; }
a:hover { color: var(--accent); }
::selection { background: var(--accent); color: #fff; }

img { max-width: 100%; display: block; }

/* fluid page canvas shared by every case-study-style page (not the
   landing page, which uses its own fixed 1440x900 scaled canvas).
   No max-width — the page keeps resizing past 1440px, held to a
   constant 30px side padding (set on .overview/.grid) rather than
   capping out and leaving dead margin on wide screens. */
.stage {
  position: relative;
  width: 100%;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}

/* body-copy: the one place we drop the mono/uppercase site voice for readable prose */
.copy {
  font-family: 'IBM Plex Sans', Helvetica, Arial, sans-serif;
  text-transform: none;
  letter-spacing: -0.02em;
  line-height: 1.5;
}

/* ---- link-flip hover mechanic ---- */
.link-flip { position: relative; display: inline-block; perspective: 1000px; }
.link-flip:hover, .link-flip:focus-visible { color: inherit; }
.link-flip__front, .link-flip__back {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  white-space: nowrap;
  transition: transform .6s cubic-bezier(.22,1,.36,1), opacity .6s;
  backface-visibility: hidden;
}
.link-flip__front { opacity: 1; transform: translateY(0) rotateX(0deg); }
.link-flip__back { opacity: 0; transform: translateY(-50%) rotateX(90deg); }
.link-flip:hover .link-flip__front,
.link-flip:focus-visible .link-flip__front { opacity: 0; transform: translateY(50%) rotateX(90deg); }
.link-flip:hover .link-flip__back,
.link-flip:focus-visible .link-flip__back { opacity: 1; transform: translateY(0) rotateX(0deg); }
.link-flip__ghost { visibility: hidden; display: inline-block; }
/* scripted equivalent of :hover, for a one-time triggered flip (e.g. the About page intro) rather than a hover interaction */
.link-flip.is-flipped .link-flip__front { opacity: 0; transform: translateY(50%) rotateX(90deg); }
.link-flip.is-flipped .link-flip__back { opacity: 1; transform: translateY(0) rotateX(0deg); }
.link-flip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 2px;
}

/* generic keyboard-focus fallback for any interactive element without a bespoke state */
a:focus-visible, button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

/* ---- shared top bar ---- */
.topbar {
  position: fixed;
  top: 30px;
  left: 30px; right: 30px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  z-index: 20;
  font-size: 12px;
  transition: background-color .3s ease, backdrop-filter .3s ease, padding .3s ease, margin .3s ease;
}
.topbar.over-media {
  background: rgba(240,240,236,0.6);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  margin: -10px;
  padding: 10px;
  border-radius: 8px;
}
.wordmark, .langtoggle, .contact-btn { font-family: 'B612 Mono', ui-monospace, monospace; font-weight: 400; font-size: 12px; color: var(--ink); }
.langtoggle { cursor: pointer; }
.langtoggle:hover { color: var(--accent); }
.rightgroup { display: flex; align-items: center; gap: 20px; }

/* contacts is a button, not a link — it opens a floating list instead
   of navigating anywhere */
button.contact-btn {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}
.contact-menu { position: relative; }
.contact-dropdown {
  position: absolute;
  top: calc(100% + 14px);
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  background: none;
  pointer-events: none;
  z-index: 25;
}
.contact-menu.open .contact-dropdown { pointer-events: auto; }
.contact-dropdown__item {
  font-family: 'B612 Mono', ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.3px;
  color: var(--ink);
  white-space: nowrap;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity .35s ease, transform .35s ease;
}
.contact-dropdown__item:hover { color: var(--accent); }
/* the language picked right now, in the language dropdown */
.lang-menu .contact-dropdown__item.is-current { color: var(--accent); }
/* items appear one after another on open, and disappear in reverse
   (last to first) on close — two delay tables, switched by .open;
   transition-delay is read from the style at the moment each
   transition starts, so removing .open alone flips the order */
.contact-menu.open .contact-dropdown__item { opacity: 1; transform: translateY(0); }
.contact-dropdown__item:nth-child(1) { transition-delay: .24s; }
.contact-dropdown__item:nth-child(2) { transition-delay: .16s; }
.contact-dropdown__item:nth-child(3) { transition-delay: .08s; }
.contact-dropdown__item:nth-child(4) { transition-delay: 0s; }
.contact-menu.open .contact-dropdown__item:nth-child(1) { transition-delay: 0s; }
.contact-menu.open .contact-dropdown__item:nth-child(2) { transition-delay: .08s; }
.contact-menu.open .contact-dropdown__item:nth-child(3) { transition-delay: .16s; }
.contact-menu.open .contact-dropdown__item:nth-child(4) { transition-delay: .24s; }
.monogram-center {
  position: fixed;
  top: 30px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 21;
}
.monogram { color: var(--accent); font-size: 12px; }
/* stays accent-red on hover everywhere — .link-flip:hover{color:inherit}
   would otherwise win (higher specificity than .monogram alone) and
   make it revert to the inherited ink color while hovering */
.link-flip.monogram:hover, .link-flip.monogram:focus-visible { color: var(--accent); }

/* shortened monogram shown inline in the mobile topbar row (between
   the wordmark and RU/CONTACTS) on every page — the full-size
   .monogram-center is desktop-only (see the mobile breakpoint below) */
.monogram-mobile { display: none; }

/* ---- shared bottom bar (in-flow variant; case-study pages override to position:absolute) ---- */
.bottombar {
  padding: 30px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
}
.bottom-left { display: flex; align-items: flex-end; gap: 30px; }
.photo { width: 130px; height: 194px; overflow: hidden; flex: none; }
.photo img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 12%; }
.corner-bio { max-width: 480px; text-align: left; }
.bio {
  font-family: 'IBM Plex Sans', Helvetica, Arial, sans-serif;
  text-transform: none;
  font-weight: 400;
  font-size: 16px;
  line-height: 1.55;
  letter-spacing: -0.1px;
  color: var(--ink);
}
.status { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--ink); }
.status .muted { color: var(--muted); }

@media (max-width: 767px) {
  .topbar { top: 16px; left: 24px; right: 24px; }
  /* same logic as desktop: the monogram is centered independently of
     the topbar's own two ends via position:fixed + left:50% (not a
     3rd flex child of .topbar, which would only land whatever
     space-between computed from the other two items' widths, not the
     true center) — wordmark and rightgroup are then just the topbar's
     only two flex children, so they land flush at its ends on their
     own via the existing justify-content:space-between */
  .monogram-center { display: none; }
  .monogram-mobile {
    display: inline-block;
    position: fixed;
    top: 16px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 21;
  }
  /* when frosted, the topbar's own background grows down to embrace
     the open contacts dropdown instead of it floating over bare page
     background below a smaller frosted box — every page, not just
     landing, since every page's mobile topbar can scroll+frost */
  .topbar.over-media:has(.contact-menu.open) { padding-bottom: 130px; }
}

/* picture magnifier (js/image-loupe.js) */
.img-loupe {
  position: fixed; top: 0; left: 0;
  border-radius: 50%;
  background-repeat: no-repeat;
  background-color: #fff;
  box-shadow: 0 0 0 1px var(--bg), 0 10px 30px rgba(0,0,0,.22);
  pointer-events: none;
  z-index: 40;
  opacity: 0;
  transition: opacity .15s ease;
}
.img-loupe.is-on { opacity: 1; }
/* the system cursor is hidden over the pictures — the loupe circle is the pointer */
.has-loupe { cursor: none; }
