/* ===== 00-base.css ===== */
@charset "UTF-8";
/* ==========================================================================
   00-base.css: the frame and design system of sefasihlar.tech ("Root access")
   Tokens, reset, typography, every shared class, header/nav, footer,
   command palette and toast. Section files extend these through scoped
   selectors; they never redefine them.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Surfaces: true black plus neutral white overlays, never a tinted near-black */
  --bg: #000;
  --surface: rgba(255, 255, 255, .028);
  --surface-2: rgba(255, 255, 255, .055);
  --line: rgba(255, 255, 255, .09);
  --line-strong: rgba(255, 255, 255, .18);

  /* Text (all three pass 4.5:1 on black) */
  --text: #ecebe9;
  --muted: #a8a6a3;
  --dim: #8a8886;

  /* One UI accent, plus the terminal palette */
  --violet: #7c5cff;
  --violet-deep: #512bd4;
  --violet-soft: rgba(124, 92, 255, .14);
  --phosphor: #3dff9a;
  --phosphor-soft: rgba(61, 255, 154, .12);
  --amber: #ffb547;
  --red: #ff5d5d;

  /* Metallic display type, after the silver "Veni, vidi, vici" lettering */
  --chrome: linear-gradient(180deg, #ffffff 0%, #ececec 28%, #a3a3a3 56%, #d6d6d6 76%, #f7f7f7 100%);

  /* Radius hierarchy: big panels, cards, small UI, chips and buttons */
  --r-lg: 28px;
  --r-md: 16px;
  --r-sm: 10px;
  --r-pill: 999px;

  /* Type: two families, a ~1.333 scale */
  --font-sans: 'Bricolage Grotesque', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
  --step--1: .875rem;
  --step-0: 1.0625rem;
  --step-1: 1.4rem;
  --step-2: 1.875rem;
  --step-3: 2.5rem;
  --step-4: clamp(2.25rem, 4.8vw, 3.5rem);
  --step-5: clamp(3.1rem, 9vw, 6.75rem);
  --wdth-display: 84%;  /* condensed headlines (Bricolage wdth axis 75 to 100) */
  --wdth-heading: 92%;  /* h3 and other small headings */
  --measure: 68ch;      /* longest comfortable line of body copy */

  /* Layout and motion */
  --container: 1200px;
  --nav-h: 72px;
  --ease: cubic-bezier(.2, .8, .2, 1);

  color-scheme: dark;
  accent-color: var(--violet);
}


/* --------------------------------------------------------------------------
   2. Reset (zero-specificity where possible, so section classes always win)
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: #2e2e2e transparent;
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: 1.6;
  font-optical-sizing: auto;
  font-kerning: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-wrap: break-word;
  overflow-x: clip;
}

:where(h1, h2, h3, h4, h5, h6) {
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -.012em;
  text-wrap: balance;
}

:where(h1) {
  font-size: var(--step-5);
  font-stretch: var(--wdth-display);
  line-height: .96;
  letter-spacing: -.035em;
}

:where(h2) {
  font-size: var(--step-4);
  font-stretch: var(--wdth-display);
  line-height: 1.04;
  letter-spacing: -.02em;
}

:where(h3) {
  font-size: var(--step-1);
  font-stretch: var(--wdth-heading);
  font-weight: 650;
  line-height: 1.2;
  letter-spacing: -.01em;
}

:where(h4, h5, h6) {
  font-size: var(--step-0);
  font-weight: 650;
}

:where(p, li, dd, figcaption, blockquote) {
  text-wrap: pretty;
}

:where(img, picture, video, canvas, svg) {
  display: block;
  max-width: 100%;
}

:where(img, video) {
  height: auto;
}

:where(input, button, textarea, select) {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
}

:where(button) {
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}

:where(input, textarea) {
  caret-color: var(--violet);
}

::placeholder {
  color: var(--dim);
  opacity: 1;
}

:where(ul[class], ol[class]) {
  padding: 0;
  list-style: none;
}

:where(li)::marker {
  color: var(--violet);
}

:where(a) {
  color: inherit;
  text-decoration: none;
}

/* A bare link inside copy still reads as a link */
:where(a:not([class])) {
  text-decoration: underline;
  text-decoration-color: var(--violet);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

:where(address) {
  font-style: normal;
}

:where(strong, b) {
  font-weight: 650;
}

:where(code, kbd, samp, pre) {
  font-family: var(--font-mono);
  font-size: .92em;
}

:where(pre) {
  overflow-x: auto;
}

:where(table) {
  border-collapse: collapse;
  border-spacing: 0;
}

:where(hr) {
  height: 0;
  border: 0;
  border-top: 1px solid var(--line);
}

:where(abbr[title]) {
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  cursor: help;
}

:where(summary) {
  cursor: pointer;
}

/* Hash targets clear the fixed header (.section sets its own value below) */
:where([id]) {
  scroll-margin-top: calc(var(--nav-h) + 24px);
}

/* Counters keep their width while they count */
:where([data-count-to]) {
  font-variant-numeric: tabular-nums;
}

/* Author display values must never beat the hidden attribute */
[hidden]:where(:not([hidden="until-found"])) {
  display: none !important;
}

::selection {
  background: var(--violet-deep);
  color: #fff;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: #2e2e2e;
  border: 3px solid var(--bg);
  border-radius: var(--r-pill);
}

::-webkit-scrollbar-thumb:hover {
  background: #444;
}

:focus-visible {
  outline: 2px solid var(--violet);
  outline-offset: 3px;
}

:focus:not(:focus-visible) {
  outline: none;
}


/* --------------------------------------------------------------------------
   3. Layout primitives and the section head
   -------------------------------------------------------------------------- */

.container {
  width: min(100% - 40px, var(--container));
  margin-inline: auto;
}

.section {
  position: relative;
  padding-block: clamp(96px, 12vw, 160px);
  scroll-margin-top: var(--nav-h);
}

.section-head {
  margin-bottom: clamp(48px, 6vw, 80px);
}

/* sefa@sihlar:~/path$ followed by a hairline rule to the edge of the column */
.section-path {
  display: flex;
  align-items: center;
  min-width: 0;
  margin-bottom: 18px;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0;
  color: var(--dim);
  white-space: nowrap;
}

.section-path::after {
  content: "";
  flex: 1 1 auto;
  min-width: 24px;
  height: 1px;
  margin-left: 16px;
  background: var(--line);
  transform-origin: 0 50%;
}

.section-path__user {
  color: var(--dim);
}

.section-path__dir {
  color: var(--violet);
}

.section-title {
  max-width: 24ch;
  font-size: var(--step-4);
  font-stretch: var(--wdth-display);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -.02em;
  text-wrap: balance;
}

.section-lead {
  max-width: 62ch;
  margin-top: 22px;
  font-size: clamp(1.0625rem, 1rem + .3vw, 1.1875rem);
  line-height: 1.6;
  color: var(--muted);
  text-wrap: pretty;
}


/* --------------------------------------------------------------------------
   4. Text treatments
   -------------------------------------------------------------------------- */

/* Chrome on the whole heading. Where the lh unit exists the gradient repeats
   once per line, so a two-line title gets two metal bands instead of one
   stretched fade. The padding and negative margin widen the paint box so
   Turkish accents (İ, Ğ) and descenders (ş, ç, g) are not clipped. */
.chrome-text {
  color: var(--text);
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .chrome-text {
    padding-block: .1em;
    margin-block: -.1em;
    background-image: var(--chrome);
    background-origin: content-box;
    background-size: 100% 100%;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    color: transparent;
  }

  @supports (height: 1lh) {
    .chrome-text {
      background-size: 100% 1lh;
      background-repeat: repeat-y;
    }
  }

  .chrome-text::selection,
  .chrome-text *::selection {
    color: #fff;
  }
}

.link {
  color: var(--text);
  text-decoration-line: underline;
  text-decoration-color: var(--violet);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-skip-ink: auto;
  transition: color .2s ease, text-decoration-color .2s ease, text-decoration-thickness .2s ease;
}

.link:hover {
  color: #fff;
  text-decoration-thickness: 2px;
}


/* --------------------------------------------------------------------------
   5. Controls: buttons, icons, keys
   Buttons never use transform: [data-magnetic] owns it.
   -------------------------------------------------------------------------- */

.btn {
  --btn-h: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6em;
  min-height: var(--btn-h);
  padding: 0 1.4em;
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -.005em;
  white-space: nowrap;
  color: var(--text);
  background-color: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  text-decoration: none;
  transition:
    background-color .25s var(--ease),
    border-color .25s var(--ease),
    color .25s var(--ease),
    box-shadow .4s var(--ease);
}

.btn .icon {
  width: 1.15em;
  height: 1.15em;
}

.btn--primary {
  color: #000;
  background-color: var(--text);
}

.btn--primary:hover {
  background-color: #fff;
  box-shadow: 0 0 0 4px var(--violet-soft), 0 14px 40px -14px rgba(124, 92, 255, .8);
}

.btn--primary:active {
  background-color: #d9d8d6;
}

.btn--ghost {
  color: var(--text);
  border-color: var(--line-strong);
}

.btn--ghost:hover {
  border-color: rgba(124, 92, 255, .6);
  background-color: var(--violet-soft);
}

.btn--ghost:active {
  background-color: rgba(124, 92, 255, .22);
}

.btn--sm {
  --btn-h: 38px;
  padding: 0 1.1em;
  font-size: .875rem;
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: .45;
  pointer-events: none;
}

.icon {
  display: inline-block;
  flex-shrink: 0;
  width: 1.1em;
  height: 1.1em;
  vertical-align: -.16em;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.icon--fill {
  fill: currentColor;
}

.kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.85em;
  height: 1.85em;
  padding: 0 .5em;
  font-family: var(--font-mono);
  font-size: .75rem;
  font-weight: 500;
  font-style: normal;
  line-height: 1;
  letter-spacing: 0;
  white-space: nowrap;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
  border-radius: calc(var(--r-sm) - 4px);
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, .07);
}


/* --------------------------------------------------------------------------
   6. Objects: card, chips, tag, status, mono logos
   Cards are only for discrete objects; hover stays quiet (border only).
   -------------------------------------------------------------------------- */

.card {
  position: relative;
  padding: clamp(24px, 2.4vw, 28px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color .3s var(--ease);
}

.card:hover {
  border-color: var(--line-strong);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0;
  list-style: none;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  padding: 4px 12px;
  font-size: var(--step--1);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}

.chip img,
.chip .icon {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
}

.chip--accent {
  color: #fff;
  background: var(--violet-soft);
  border-color: rgba(124, 92, 255, .45);
}

img.is-mono {
  filter: brightness(0) invert(1);
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px;
  font-family: var(--font-mono);
  font-size: .75rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: calc(var(--r-sm) - 4px);
}

.status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 11px 4px 10px;
  font-family: var(--font-mono);
  font-size: .75rem;
  line-height: 1.4;
  white-space: nowrap;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}

.status::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--dim);
}

.status--live {
  color: var(--phosphor);
  background: var(--phosphor-soft);
  border-color: rgba(61, 255, 154, .28);
}

.status--live::before {
  background: var(--phosphor);
  box-shadow: 0 0 0 3px rgba(61, 255, 154, .16), 0 0 10px rgba(61, 255, 154, .7);
}


/* --------------------------------------------------------------------------
   7. Scroll reveal (only with JS; opacity and the translate property only)
   -------------------------------------------------------------------------- */

.js .reveal {
  opacity: 0;
  translate: 0 24px;
  transition:
    opacity .9s var(--ease) var(--delay, 0ms),
    translate .9s var(--ease) var(--delay, 0ms);
}

.js .reveal.is-visible {
  opacity: 1;
  translate: none;
}

/* The section head's rule draws itself as the head arrives */
.js .section-head.reveal .section-path::after {
  scale: 0 1;
  transition: scale 1.3s var(--ease) calc(var(--delay, 0ms) + 200ms);
}

.js .section-head.reveal.is-visible .section-path::after {
  scale: 1 1;
}


/* --------------------------------------------------------------------------
   8. Accessibility helpers
   -------------------------------------------------------------------------- */

.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0 0 0 0) !important;
  clip-path: inset(50%) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 300;
  padding: 12px 18px;
  font-size: var(--step--1);
  font-weight: 600;
  color: #000;
  background: var(--text);
  border-radius: var(--r-pill);
  translate: 0 calc(-100% - 24px);
  transition: translate .25s var(--ease);
}

.skip-link:focus,
.skip-link:focus-visible {
  translate: none;
}


/* --------------------------------------------------------------------------
   9. Ambient layers: film grain and scroll progress
   -------------------------------------------------------------------------- */

/* Painted between the black canvas and the content; static, so it costs one
   raster and no frames. */
.bg-fx {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}

.bg-fx__grain {
  position: absolute;
  inset: 0;
  opacity: .03;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1.4 -.2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 240px 240px;
}

.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 70;
  width: 100%;
  height: 2px;
  background: var(--violet);
  box-shadow: 0 0 12px rgba(124, 92, 255, .65);
  transform-origin: 0 50%;
  transform: scaleX(var(--progress, 0));
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   10. Site header and navigation
   Transparent over the hero; black glass with a hairline once scrolled.
   -------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  height: var(--nav-h);
  border-bottom: 1px solid transparent;
  transition:
    background-color .45s var(--ease),
    border-color .45s var(--ease),
    -webkit-backdrop-filter .45s var(--ease),
    backdrop-filter .45s var(--ease);
}

.site-header.is-scrolled {
  background-color: rgba(0, 0, 0, .72);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
  border-bottom-color: var(--line);
}

.nav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  column-gap: 20px;
  height: 100%;
}

.nav__logo {
  display: inline-flex;
  align-items: center;
  justify-self: start;
  font-family: var(--font-mono);
  font-size: .9375rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.03em;
  white-space: nowrap;
  color: var(--text);
  border-radius: 4px;
}

.nav__logo-tld {
  font-weight: 400;
  color: var(--dim);
  transition: color .25s ease;
}

/* A resting block cursor: the brand mark of a site that is a shell */
.nav__logo::after {
  content: "";
  width: .55em;
  height: 1.15em;
  margin-left: .22em;
  background: var(--violet);
  border-radius: 1px;
}

.nav__logo:hover .nav__logo-tld {
  color: var(--text);
}

.nav__logo:hover::after {
  animation: caret-blink 1.06s steps(1, end) infinite;
}

@keyframes caret-blink {
  50% { opacity: 0; }
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 9px 12px;
  font-size: .9375rem;
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--muted);
  border-radius: var(--r-sm);
  transition: color .2s ease;
}

.nav__link::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 3px;
  height: 2px;
  background: var(--violet);
  border-radius: 2px;
  scale: 0 1;
  transform-origin: 0 50%;
  transition: scale .45s var(--ease);
}

.nav__link:hover,
.nav__link.is-active,
.nav__link[aria-current]:not([aria-current="false"]) {
  color: var(--text);
}

.nav__link.is-active::after,
.nav__link[aria-current]:not([aria-current="false"])::after {
  scale: 1 1;
}

/* On wide screens the button below covers this destination */
.nav__item--contact {
  display: none;
}

.nav__actions {
  display: flex;
  align-items: center;
  justify-self: end;
  gap: 6px;
}

.nav__cmdk {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: 38px;
  padding: 0 6px 0 12px;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  transition: color .2s ease, border-color .2s ease, background-color .2s ease;
}

.nav__cmdk .icon {
  width: 17px;
  height: 17px;
}

.nav__cmdk .kbd {
  height: 26px;
  border-radius: var(--r-pill);
  padding: 0 9px;
  font-size: .6875rem;
}

.nav__cmdk:hover {
  color: var(--text);
  border-color: var(--line-strong);
  background-color: var(--surface);
}

.nav__lang {
  display: inline-grid;
  place-items: center;
  min-width: 38px;
  height: 38px;
  padding: 0 9px;
  font-family: var(--font-mono);
  font-size: .8125rem;
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--muted);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  transition: color .2s ease, border-color .2s ease;
}

.nav__lang:hover {
  color: var(--text);
  border-color: var(--line);
}

.nav__cta {
  margin-left: 4px;
}

.nav__toggle {
  position: relative;
  display: none;
  width: 44px;
  height: 44px;
  margin-right: -8px;
  color: var(--text);
  border-radius: var(--r-pill);
}

.nav__toggle-bar {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 1.5px;
  margin: -.75px 0 0 -10px;
  background: currentColor;
  border-radius: 2px;
  transition: translate .4s var(--ease), rotate .4s var(--ease);
}

.nav__toggle-bar:first-child {
  translate: 0 -4px;
}

.nav__toggle-bar:last-child {
  translate: 0 4px;
}

.nav__toggle[aria-expanded="true"] .nav__toggle-bar,
body.nav-open .nav__toggle-bar {
  translate: 0 0;
}

.nav__toggle[aria-expanded="true"] .nav__toggle-bar:first-child,
body.nav-open .nav__toggle-bar:first-child {
  rotate: 45deg;
}

.nav__toggle[aria-expanded="true"] .nav__toggle-bar:last-child,
body.nav-open .nav__toggle-bar:last-child {
  rotate: -45deg;
}

/* Controls that only work with JavaScript disappear without it */
html:not(.js) [data-cmdk-open],
html:not(.js) .nav__toggle {
  display: none !important;
}

/* Tablet: all seven links, a compact palette button, no duplicate CTA */
@media (max-width: 1023.98px) {
  .nav {
    column-gap: 12px;
  }

  .nav__item--contact {
    display: list-item;
  }

  .nav__cta {
    display: none;
  }

  .nav__link {
    padding-inline: 9px;
    font-size: .875rem;
  }

  .nav__link::after {
    left: 9px;
    right: 9px;
  }

  .nav__cmdk {
    justify-content: center;
    width: 38px;
    padding: 0;
  }

  .nav__cmdk .kbd {
    display: none;
  }
}

/* Mobile (same 768px line main.js uses): the links fold into a full-width
   dropdown under the bar */
@media (max-width: 768px) {
  .nav {
    display: flex;
    justify-content: space-between;
  }

  .nav__logo {
    font-size: .875rem;
  }

  .nav__toggle {
    display: inline-block;
  }

  .nav__links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    max-height: calc(100vh - var(--nav-h));
    max-height: calc(100dvh - var(--nav-h));
    padding: 4px 20px 28px;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--bg);
    border-bottom: 1px solid var(--line);
    /* dims the page under the open menu; clipped so it never covers the bar */
    box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .6);
    clip-path: inset(0 0 -100vmax 0);
    opacity: 0;
    visibility: hidden;
    translate: 0 -10px;
    transition:
      opacity .3s var(--ease),
      translate .45s var(--ease),
      visibility 0s linear .45s;
  }

  body.nav-open .nav__links {
    opacity: 1;
    visibility: visible;
    translate: none;
    transition-delay: 0s;
  }

  body.nav-open .site-header {
    background-color: var(--bg);
    border-bottom-color: var(--line);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .nav__item,
  .nav__item--contact {
    display: block;
    border-bottom: 1px solid var(--line);
  }

  .nav__link {
    display: flex;
    padding: 14px 0 15px;
    font-size: var(--step-2);
    font-stretch: var(--wdth-display);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.02em;
    color: var(--text);
    border-radius: 0;
  }

  .nav__link::after {
    left: 0;
    right: auto;
    bottom: 8px;
    width: 28px;
  }
}


/* --------------------------------------------------------------------------
   11. Footer: the session ends
   -------------------------------------------------------------------------- */

.site-footer {
  position: relative;
  padding-block: clamp(56px, 8vw, 96px) calc(28px + env(safe-area-inset-bottom, 0px));
  font-size: var(--step--1);
  color: var(--muted);
  border-top: 1px solid var(--line);
}

.site-footer__session {
  margin-bottom: clamp(36px, 5vw, 56px);
  font-family: var(--font-mono);
  font-size: .8125rem;
  line-height: 1.75;
  color: var(--dim);
}

.site-footer__session-cmd {
  color: var(--text);
}

.site-footer__main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 32px 48px;
}

.site-footer__logo {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.03em;
  color: var(--text);
}

.site-footer__logo::after {
  content: "";
  width: .55em;
  height: 1.15em;
  margin-left: .22em;
  background: var(--violet);
  border-radius: 1px;
}

.site-footer__logo-tld {
  font-weight: 400;
  color: var(--dim);
}

.site-footer__tagline {
  max-width: 44ch;
  margin-top: 14px;
  font-size: var(--step-0);
  line-height: 1.55;
  color: var(--muted);
}

.site-footer__social {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0;
  list-style: none;
}

.site-footer__social-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 14px;
  font-size: .875rem;
  font-weight: 500;
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  transition: border-color .25s ease, background-color .25s ease;
}

.site-footer__social-link:hover {
  border-color: var(--line-strong);
  background-color: var(--surface);
}

.site-footer__social-link .icon {
  width: 16px;
  height: 16px;
}

.site-footer__social-link .site-footer__ext {
  width: 13px;
  height: 13px;
  margin-left: -2px;
  color: var(--dim);
}

.site-footer__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 28px;
  margin-top: clamp(40px, 6vw, 64px);
  padding-top: 22px;
  border-top: 1px solid var(--line);
}

.site-footer__hint .kbd {
  margin-inline: 2px;
  vertical-align: .05em;
}

.site-footer__top {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  padding: 6px 0;
  font-weight: 500;
  color: var(--text);
  transition: color .2s ease;
}

.site-footer__top .icon {
  width: 16px;
  height: 16px;
  color: var(--violet);
}

.site-footer__top:hover {
  color: #fff;
}

@media (max-width: 768px) {
  .site-footer__main {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
  }

  .site-footer__meta {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .site-footer__top {
    margin: 10px 0 0;
  }
}


/* --------------------------------------------------------------------------
   12. Command palette
   -------------------------------------------------------------------------- */

.cmdk {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: clamp(16px, 13vh, 132px) 16px 16px;
}

.cmdk__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .62);
  -webkit-backdrop-filter: blur(10px) saturate(120%);
  backdrop-filter: blur(10px) saturate(120%);
}

.cmdk__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 640px;
  max-height: calc(100vh - 32px);
  max-height: calc(100dvh - 32px);
  overflow: hidden;
  background-color: var(--bg);
  background-image: linear-gradient(var(--surface), var(--surface));
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  box-shadow:
    0 40px 120px -32px rgba(81, 43, 212, .55),
    0 24px 48px -24px rgba(0, 0, 0, .9);
}

.cmdk__search {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 60px;
  padding: 0 12px 0 18px;
  border-bottom: 1px solid var(--line);
  transition: border-color .2s ease;
}

.cmdk__search:focus-within {
  border-bottom-color: rgba(124, 92, 255, .55);
}

.cmdk__search > .icon {
  width: 20px;
  height: 20px;
  color: var(--dim);
}

.cmdk__search input {
  flex: 1 1 auto;
  min-width: 0;
  height: 58px;
  font-size: 1.0625rem;
  color: var(--text);
  background: none;
  border: 0;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}

.cmdk__search input:focus-visible {
  outline: none;
}

.cmdk__esc {
  display: inline-flex;
  padding: 4px;
  border-radius: var(--r-sm);
}

.cmdk__esc:hover .kbd {
  color: var(--text);
}

.cmdk__list {
  flex: 1 1 auto;
  min-height: 0;
  max-height: 50vh;
  margin: 0;
  padding: 8px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-padding-block: 8px;
  list-style: none;
}

.cmdk__group-label {
  padding: 14px 12px 6px;
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--dim);
}

.cmdk__group-label:first-child {
  padding-top: 6px;
}

.cmdk__item {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 8px 12px;
  color: var(--text);
  border-radius: var(--r-sm);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}

.cmdk__item > .icon {
  width: 18px;
  height: 18px;
  color: var(--dim);
  transition: color .15s ease;
}

.cmdk__label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  font-size: .9375rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cmdk__hint {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 50%;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: .75rem;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--dim);
}

.cmdk__hint:empty {
  display: none;
}

/* main.js appends an external-link icon to the hint of links that open a tab */
.cmdk__hint .icon {
  width: 12px;
  height: 12px;
  margin-left: 6px;
  vertical-align: -1px;
}

.cmdk__item:hover {
  background: var(--surface-2);
}

.cmdk__item.is-active,
.cmdk__item[aria-selected="true"] {
  background: var(--violet-soft);
}

.cmdk__item.is-active > .icon,
.cmdk__item[aria-selected="true"] > .icon {
  color: var(--violet);
}

.cmdk__item.is-active .cmdk__hint,
.cmdk__item[aria-selected="true"] .cmdk__hint {
  color: var(--muted);
}

.cmdk__label mark {
  color: #fff;
  background: none;
  text-decoration: underline;
  text-decoration-color: var(--violet);
  text-underline-offset: 3px;
}

/* main.js renders the empty state as li.cmdk__group-label.cmdk__empty */
.cmdk__list .cmdk__empty {
  padding: 28px 12px;
  font-size: .9375rem;
  text-align: center;
  color: var(--muted);
}

.cmdk__footer {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  padding: 10px 18px;
  font-size: .75rem;
  color: var(--dim);
  border-top: 1px solid var(--line);
}

.cmdk__keys {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.cmdk__keys .kbd {
  height: 22px;
  min-width: 22px;
  padding: 0 6px;
  font-size: .6875rem;
}

@keyframes cmdk-backdrop-in {
  from { opacity: 0; }
}

@keyframes cmdk-panel-in {
  from {
    opacity: 0;
    translate: 0 -14px;
    scale: .975;
  }
}

.cmdk:not([hidden]) .cmdk__backdrop {
  animation: cmdk-backdrop-in .25s ease-out both;
}

.cmdk:not([hidden]) .cmdk__panel {
  animation: cmdk-panel-in .38s var(--ease) both;
}

/* Key hints mean nothing without a keyboard */
@media (hover: none) and (pointer: coarse) {
  .cmdk__footer,
  .cmdk__esc .kbd {
    display: none;
  }
}

@media (max-width: 768px) {
  .cmdk {
    padding: 12px 12px 16px;
  }

  .cmdk__list {
    max-height: 60vh;
  }
}


/* --------------------------------------------------------------------------
   13. Toast
   -------------------------------------------------------------------------- */

/* Always in the accessibility tree, so the live region announces reliably */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  z-index: 120;
  display: flex;
  align-items: center;
  gap: 10px;
  width: max-content;
  max-width: calc(100vw - 32px);
  padding: 12px 20px 12px 16px;
  font-size: var(--step--1);
  font-weight: 500;
  line-height: 1.4;
  color: var(--text);
  background-color: rgba(0, 0, 0, .86);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  box-shadow: 0 24px 60px -24px rgba(81, 43, 212, .7);
  opacity: 0;
  translate: -50% 18px;
  pointer-events: none;
  transition: opacity .3s var(--ease), translate .5s var(--ease);
}

.toast::before {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--violet);
  box-shadow: 0 0 10px rgba(124, 92, 255, .9);
}

.toast:empty {
  padding: 0;
  border-width: 0;
}

.toast:empty::before {
  display: none;
}

.toast.is-visible {
  opacity: 1;
  translate: -50% 0;
}


/* --------------------------------------------------------------------------
   14. Reduced motion, forced colours, print
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }

  .js .reveal {
    opacity: 1;
    translate: none;
  }

  .js .section-head.reveal .section-path::after {
    scale: 1 1;
  }

  .nav__logo:hover::after {
    animation: none;
  }
}

@media (forced-colors: active) {
  .chrome-text {
    background: none;
    color: CanvasText;
  }

  .scroll-progress,
  .nav__link::after {
    background: Highlight;
  }

  .btn,
  .card,
  .cmdk__panel,
  .toast {
    border: 1px solid CanvasText;
  }

  .cmdk__item.is-active,
  .cmdk__item[aria-selected="true"] {
    outline: 2px solid Highlight;
  }
}

@media print {
  .bg-fx,
  .scroll-progress,
  .site-header,
  .skip-link,
  .cmdk,
  .toast {
    display: none !important;
  }

  body {
    color: #000;
    background: #fff;
  }

  .chrome-text {
    background: none !important;
    color: #000 !important;
  }

  .js .reveal {
    opacity: 1 !important;
    translate: none !important;
  }

  .section {
    padding-block: 32px;
  }
}


/* ===== 05-fx.css ===== */
.perspective-grid{position:absolute;left:-50%;right:-50%;bottom:0;height:55%;pointer-events:none;background-image:linear-gradient(rgba(124,92,255,.35) 1px,transparent 1px),linear-gradient(90deg,rgba(124,92,255,.35) 1px,transparent 1px);background-size:64px 64px;transform:perspective(600px) rotateX(62deg);transform-origin:50% 100%;-webkit-mask-image:linear-gradient(to top,#000 10%,transparent 85%);mask-image:linear-gradient(to top,#000 10%,transparent 85%);opacity:.35}
.reveal-3d{transition:opacity .9s var(--ease),transform .9s var(--ease)}html.js .reveal-3d:not(.is-visible){opacity:0;transform:perspective(1200px) rotateX(14deg) translateY(40px)}


/* ===== 06-scene.css ===== */
/* ==========================================================================
   06-scene: WebGL scene containers ([data-3d], mounted by /assets/js/3d/boot.js)
   The fallback stays in the accessibility tree; only its opacity changes.
   ========================================================================== */

[data-3d] {
  position: relative;
}

.scene-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 1.2s var(--ease, ease);
}

[data-3d].is-ready .scene-canvas {
  opacity: 1;
}

/* Slower than the canvas: the image dissolves while the particles arrive. */
.scene-fallback {
  transition: opacity 1.6s var(--ease, ease);
}

[data-3d].is-ready .scene-fallback {
  opacity: 0;
  pointer-events: none;
}

/* The hero cloud reacts to the pointer: a precise cursor makes that legible. */
@media (hover: hover) and (pointer: fine) {
  [data-3d="hero-scene"].is-ready .scene-canvas {
    cursor: crosshair;
  }
}

@media (prefers-reduced-motion: reduce) {
  .scene-canvas,
  .scene-fallback {
    transition: none;
  }
}


/* ===== 10-hero.css ===== */
/* ==========================================================================
   10-hero (#top)
   The page's one bold moment: the chrome name on the left; on the right a
   layered depth stack of violet backlight, particle mask and live terminal.
   Owns .hero* only. It places the scene container and the terminal but never
   styles .scene-canvas (06-scene) or anything inside .terminal (15-terminal).
   Transform ownership: .btn[data-magnetic] belongs to fx.js; this file sets
   transform only on .hero__term-3d (static 3D turn) and .hero__stage
   (scroll-driven recede).
   Particle framing (hero-scene.js, square container): face at about 12-53%
   of the height, "Veni, vidi, vici" at 64-74%, the small line at 78-82%.
   ========================================================================== */

.hero {
  --hero-gap: clamp(28px, 4.5vw, 72px);
  --hero-mask: min(100%, 620px);
  position: relative;
  isolation: isolate;
  overflow-x: clip;
  padding-top: calc(var(--nav-h) + clamp(12px, 2.5vw, 28px));
  padding-bottom: clamp(56px, 8vw, 96px);
}

/* Floor: the perspective grid (05-fx), low and faded at both ends, so the
   hero melts into the next section instead of ending on a line. */
.hero__floor {
  position: absolute;
  inset: auto 0 0;
  z-index: -1;
  height: 62%;
  opacity: .5;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 48%, #000 70%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 48%, #000 70%, transparent 100%);
}

/* --------------------------------------------------------------------------
   Layout. Mobile first: mask, then copy, then terminal. The stage wrapper
   dissolves (display: contents) so its children join the grid directly.
   -------------------------------------------------------------------------- */
.hero__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "visual" "copy" "term";
  align-items: center;
}

.hero__stage { display: contents; }

.hero__copy {
  grid-area: copy;
  position: relative;
  z-index: 2;
  min-width: 0;
}

.hero__visual {
  grid-area: visual;
  position: relative;
  isolation: isolate;
  justify-self: center;
  width: min(82vw, 400px);
  /* the artwork's top and bottom bands are empty: tuck them under the
     header and under the first line of copy */
  margin-top: calc(min(82vw, 400px) * -.08);
  margin-bottom: calc(min(82vw, 400px) * -.15);
}

.hero__term {
  grid-area: term;
  position: relative;
  z-index: 3;
  min-width: 0;
  margin-top: clamp(40px, 9vw, 56px);
}

/* --------------------------------------------------------------------------
   Copy
   -------------------------------------------------------------------------- */
.hero__prompt {
  margin: 0 0 clamp(14px, 2vw, 22px);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--dim);
}
.hero__prompt-dir { color: var(--violet); }
.hero__cmd { color: var(--text); }

/* The whole name in chrome (00-base repeats the chrome once per line).
   Two stacked lines, tighter and more condensed than the section titles. */
.hero .hero__title {
  display: block;
  font-family: var(--font-sans);
  font-size: var(--step-5);
  font-weight: 760;
  font-stretch: 80%;
  line-height: .9;
  letter-spacing: -.035em;
}
.hero__name { display: block; }

.hero__role {
  margin: clamp(18px, 2.4vw, 28px) 0 0;
  max-width: 36ch;
  font-size: var(--step-1);
  font-weight: 500;
  font-stretch: 90%;
  line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--text);
  text-wrap: balance;
}

.hero__lead {
  margin: clamp(14px, 1.6vw, 18px) 0 0;
  max-width: 46ch;
  font-size: var(--step-0);
  line-height: 1.6;
  color: var(--muted);
  text-wrap: pretty;
}
.hero__lead strong {
  font-weight: 600;
  color: var(--text);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: clamp(26px, 3.2vw, 38px);
}
.hero__actions .hero__ext {
  width: .85em;
  height: .85em;
  margin-left: -.1em;
  opacity: .6;
}

.hero__social {
  display: flex;
  gap: 2px;
  margin: 18px 0 0 -12px; /* optical: the glyphs line up with the text edge */
  padding: 0;
  list-style: none;
}
.hero__social-link {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-sm);
  color: var(--muted);
  transition: color .2s ease, background-color .2s ease;
}
.hero__social-link .icon {
  width: 20px;
  height: 20px;
}
.hero__social-link:focus-visible {
  color: var(--text);
  outline: 2px solid var(--violet);
  outline-offset: 2px;
}
@media (hover: hover) {
  .hero__social-link:hover {
    color: var(--text);
    background-color: var(--surface-2);
  }
}

/* --------------------------------------------------------------------------
   Visual: violet backlight, particle mask (WebGL) and its static fallback
   -------------------------------------------------------------------------- */

/* A light source behind the head: a tight core plus a wide, faint spill
   that reaches down behind the terminal's glass. */
.hero__visual::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -14% -12% -6%;
  background:
    radial-gradient(30% 26% at 50% 38%, rgba(81, 43, 212, .55) 0%, rgba(81, 43, 212, .3) 38%, rgba(81, 43, 212, .1) 70%, transparent 100%),
    radial-gradient(52% 50% at 50% 46%, rgba(81, 43, 212, .2) 0%, rgba(81, 43, 212, .07) 55%, transparent 100%);
  pointer-events: none;
  transition: opacity 1.8s var(--ease);
}

/* The scene container. hero-scene.js fades its own points at the canvas
   edges; this softer vignette also melts the fallback picture into black. */
.hero__mask {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  -webkit-mask-image: radial-gradient(farthest-corner at 50% 48%, #000 60%, transparent 76%);
          mask-image: radial-gradient(farthest-corner at 50% 48%, #000 60%, transparent 76%);
}

/* Static fallback (no JS, no WebGL, reduced motion, Save-Data, low memory):
   the picture framed like the particle cloud, with a slight violet duotone,
   fine scanlines and a soft vignette. */
.hero__mask-fallback {
  position: absolute;
  inset: 0;
  isolation: isolate;
}
.hero__mask-fallback img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  scale: .92;
  filter: grayscale(1) contrast(1.15) brightness(1.1);
}
.hero__mask-fallback::before,
.hero__mask-fallback::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* duotone: blacks stay black, the lettering keeps its light, mid-tones go violet */
.hero__mask-fallback::before {
  z-index: 1;
  background: var(--violet-deep);
  mix-blend-mode: color;
  opacity: .65;
}
.hero__mask-fallback::after {
  z-index: 2;
  background:
    repeating-linear-gradient(to bottom, rgba(0, 0, 0, .38) 0 1px, transparent 1px 3px),
    radial-gradient(closest-side at 50% 46%, transparent 62%, rgba(0, 0, 0, .6));
}

/* Boot: while the scene loads the stage stays dark, so the particles
   assemble out of nothing and the light comes up with them. Static mode
   shows the fallback at once; if nothing happens within a few seconds
   (scripts blocked or failed) the fallback fades in anyway. */
@media (prefers-reduced-motion: no-preference) {
  html.js .hero__mask:not(.is-static):not(.is-ready) .hero__mask-fallback {
    opacity: 0;
    animation: hero-fallback-in 1s var(--ease) 3.2s forwards;
  }
  html.js .hero__visual:not(:has(.is-ready, .is-static))::before {
    opacity: .4;
  }
}
@keyframes hero-fallback-in {
  to { opacity: 1; }
}

/* --------------------------------------------------------------------------
   Tablet: copy and mask side by side, terminal full width below
   -------------------------------------------------------------------------- */
@media (min-width: 768px) {
  .hero__grid {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
    grid-template-areas: "copy visual" "term term";
    column-gap: var(--hero-gap);
  }
  .hero__visual {
    width: 100%;
    margin: 0;
  }
  .hero__term { margin-top: clamp(24px, 4vw, 48px); }
}

/* --------------------------------------------------------------------------
   Desktop: one screen tall. The mask sizes to the viewport height so the
   whole terminal stays above the fold; the terminal sits under the slogan,
   overlapping the mask's lower-left edge, turned a few degrees in 3D, and
   turns to face you when you use it.
   -------------------------------------------------------------------------- */
@media (min-width: 1024px) {
  .hero {
    --hero-mask: min(100%, 620px, max(400px, (100vh - 500px) / .68));
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 100vh;
    min-height: 100svh;
  }
  @supports (height: 100svh) {
    .hero { --hero-mask: min(100%, 620px, max(400px, (100svh - 500px) / .68)); }
  }

  .hero__grid {
    grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
    grid-template-areas: "copy stage";
  }

  .hero__stage {
    grid-area: stage;
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    margin-top: calc(var(--hero-mask) * -.1); /* empty band above the face */
  }

  .hero__visual { width: var(--hero-mask); }

  .hero__term {
    width: calc(var(--hero-mask) * .86 + var(--hero-gap) * .6);
    margin: calc(var(--hero-mask) * -.22) calc(var(--hero-mask) * .14) 0 0;
    perspective: 1400px;
    perspective-origin: 70% 30%;
  }
  .hero__term-3d {
    transform: rotateY(-7deg) rotateX(4deg);
    transform-origin: 50% 0;
    transition: transform .8s var(--ease);
  }
  .hero__term:hover .hero__term-3d { transform: rotateY(-3.5deg) rotateX(2deg); }
  .hero__term:focus-within .hero__term-3d { transform: none; }
}

/* Progressive: the stage recedes into depth as the hero scrolls away. */
@supports (animation-timeline: view()) {
  @media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
    .hero { view-timeline: --hero block; }
    .hero__stage {
      transform-origin: 50% 25%;
      animation: hero-recede linear both;
      animation-timeline: --hero;
      animation-range: exit 0% exit 90%;
    }
  }
}
@keyframes hero-recede {
  to {
    transform: perspective(1600px) translate3d(0, 5%, -200px) rotateX(10deg);
    opacity: .15;
  }
}

/* Small phones: the two buttons share the row or stack at full width. */
@media (max-width: 479.98px) {
  .hero__actions .btn {
    flex: 1 1 auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero__term-3d,
  .hero__visual::before,
  .hero__social-link { transition: none; }
}


/* ===== 15-terminal.css ===== */
.terminal{position:relative;background:rgba(10,10,12,.82);border:1px solid var(--line-strong,rgba(255,255,255,.18));border-radius:12px;overflow:hidden;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);box-shadow:0 30px 80px -30px rgba(81,43,212,.45);font-family:var(--font-mono,ui-monospace,monospace);font-size:13px;line-height:1.7;color:var(--text,#ecebe9)}
.terminal__bar{display:flex;align-items:center;gap:12px;padding:10px 14px;border-bottom:1px solid var(--line,rgba(255,255,255,.09))}
.terminal__dots{display:flex;gap:6px}.terminal__dots i{display:block;width:10px;height:10px;border-radius:50%;background:#3a3a3d}
.terminal__title{flex:1;text-align:center;color:var(--dim,#8a8886);font-size:12px;margin-right:40px}
.terminal__body{padding:16px 18px 18px;max-height:340px;overflow:auto}
.t-line{min-height:1.7em;white-space:pre-wrap;word-break:break-word}.t-prompt{color:var(--phosphor,#3dff9a)}.t-out{color:var(--muted,#a8a6a3)}
.t-accent{color:var(--violet,#7c5cff)}.t-ok{color:var(--phosphor,#3dff9a)}.t-warn,.t-num{color:var(--amber,#ffb547)}.t-err{color:var(--red,#ff5d5d)}.t-dim{color:var(--dim,#8a8886)}.t-key{color:#b7a6ff}.t-str{color:#9ef0c4}
.t-caret{display:inline-block;width:.6em;height:1.1em;vertical-align:-.15em;background:var(--violet,#7c5cff);animation:t-blink 1s steps(1) infinite}
@keyframes t-blink{50%{opacity:0}}@media (prefers-reduced-motion:reduce){.t-caret{animation:none}}


/* ===== 20-about.css ===== */
/* ==========================================================================
   20-about: rendered README.md panel + holographic ID card
   Blocks: .about (layout), .about-readme, .about-lang, .about-cefr, .idcard,
   .about-facts.
   .idcard is a [data-tilt] element: fx.js owns its transform, and its
   [data-depth] children get their translate from fx.js. Nothing in this file
   sets transform or translate on them; the inner layers move instead.
   ========================================================================== */

/* ---------- layout ---------- */

.about {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
  align-items: start;
  gap: clamp(40px, 5.5vw, 88px);
}

.about__id {
  position: sticky;
  top: calc(var(--nav-h) + 32px);
  display: grid;
  justify-items: center;
  gap: 28px;
  min-width: 0;
}

/* ---------- README.md panel ---------- */

.about-readme {
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}

.about-readme__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px clamp(20px, 3.2vw, 32px);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--muted);
}

.about-readme__icon {
  flex: none;
  color: var(--dim);
}

.about-readme__path {
  margin: 0;
  min-width: 0;
}

.about-readme__slash {
  margin-inline: .6ch;
  color: var(--dim);
}

.about-readme__file {
  color: var(--text);
  font-weight: 500;
}

.about-readme__body {
  padding: clamp(24px, 4vw, 48px);
  font-size: var(--step-0);
  line-height: 1.6;
  color: var(--text);
}

.about-readme__body > * {
  max-width: 68ch;
  margin: 0;
}

.about-readme__body > * + * {
  margin-top: 1em;
}

/* rendered markdown headings: GitHub-style hairline under each heading */
.about-readme__body h3 {
  max-width: none;
  margin-top: 2.25em;
  padding-bottom: .45em;
  border-bottom: 1px solid var(--line);
}

.about-readme__body > h3 + * {
  margin-top: .95em;
}

.about-readme__body .about-readme__title {
  margin-top: 0;
  font-size: var(--step-2);
  font-weight: 700;
  font-stretch: var(--wdth-display, 84%);
  letter-spacing: -0.02em;
}

.about-readme__body code {
  padding: .1em .42em;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: .84em;
  white-space: nowrap;
}

/* task list: - [x] item */
.about-readme__tasks {
  display: grid;
  gap: .55em;
  padding: 0;
  list-style: none;
}

.about-readme__task {
  display: grid;
  grid-template-columns: 1.05em minmax(0, 1fr);
  align-items: start;
  column-gap: .8em;
}

.about-readme__check {
  display: grid;
  place-items: center;
  width: 1.05em;
  height: 1.05em;
  margin-top: .28em;
  border: 1.5px solid var(--line-strong);
  border-radius: 5px;
}

.about-readme__task.is-done .about-readme__check {
  border-color: var(--violet);
  background: var(--violet);
}

.about-readme__task.is-done .about-readme__check::after {
  content: "";
  width: .5em;
  height: .27em;
  margin-top: -.14em;
  border-bottom: 2px solid var(--text);
  border-left: 2px solid var(--text);
  rotate: -45deg;
}

.about-readme__task:not(.is-done) {
  color: var(--muted);
}

/* key/value table, sized to its content like a rendered markdown table */
.about-readme__body .about-readme__table {
  max-width: 100%;
  border: 1px solid var(--line);
  border-collapse: separate;
  border-spacing: 0;
  border-radius: var(--r-sm);
  overflow: hidden;
  font-size: .94em;
  line-height: 1.45;
}

.about-readme__table th,
.about-readme__table td {
  padding: .62em 1em;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}

.about-readme__table tr:last-child > * {
  border-bottom: 0;
}

.about-readme__table th {
  white-space: nowrap;
  border-right: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted);
  font-weight: 500;
}

/* ---------- languages + CEFR scale ---------- */

.about-readme__body .about-lang {
  max-width: 30rem;
  padding: 0;
  list-style: none;
}

.about-lang__item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: .5em 1em;
  padding-block: .85em;
  border-bottom: 1px solid var(--line);
}

.about-lang__item:first-child {
  padding-top: .2em;
}

.about-lang__item:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.about-lang__name {
  font-weight: 600;
}

.about-lang__level {
  color: var(--muted);
}

.about-lang__note {
  grid-column: 1 / -1;
  color: var(--dim);
  font-size: var(--step--1);
  line-height: 1.45;
}

.about-cefr {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 4px;
  margin: .2em 0 0;
  padding: 0;
  list-style: none;
  font-family: var(--font-mono);
  font-size: .75rem;
  line-height: 1;
}

.about-cefr__step {
  padding: .55em 0 .5em;
  border: 1px solid var(--line);
  color: var(--dim);
  text-align: center;
}

.about-cefr__step:first-child {
  border-radius: var(--r-pill) 0 0 var(--r-pill);
}

.about-cefr__step:last-child {
  border-radius: 0 var(--r-pill) var(--r-pill) 0;
}

.about-cefr__step.is-reached {
  border-color: rgba(124, 92, 255, .32);
  background: var(--violet-soft);
  color: var(--muted);
}

.about-cefr__step.is-current {
  border-color: var(--violet);
  background: var(--violet);
  color: #000;
  font-weight: 700;
}

/* ---------- holographic ID card ---------- */

.idcard {
  --idcard-pad: 26px;
  --idcard-foil-x: 22%;
  --idcard-foil-y: 18%;
  position: relative;
  display: grid;
  grid-template-columns: clamp(96px, 38%, 136px) minmax(0, 1fr);
  grid-template-areas:
    "brand brand"
    "photo fields"
    "id    id"
    "code  code"
    "foot  foot";
  column-gap: 20px;
  width: 100%;
  max-width: 380px;
  padding: calc(var(--idcard-pad) + 14px) var(--idcard-pad) var(--idcard-pad);
  border-radius: var(--r-md);
  color: var(--text);
  transform-style: preserve-3d;
}

/* content sits above the plate; .tilt-glare (injected by fx.js) comes last */
.idcard__brand,
.idcard__photo,
.idcard__fields,
.idcard__id,
.idcard__barcode,
.idcard__foot {
  position: relative;
}

/* the card body: black plate, chrome edge, violet glow underneath */
.idcard__plate {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border: 1px solid transparent;
  border-radius: inherit;
  background:
    radial-gradient(130% 75% at 15% 0%, rgba(124, 92, 255, .13), transparent 62%) padding-box,
    linear-gradient(#000, #000) padding-box,
    linear-gradient(155deg, rgba(255, 255, 255, .44), rgba(255, 255, 255, .07) 30%, rgba(124, 92, 255, .3) 70%, rgba(255, 255, 255, .26)) border-box;
  box-shadow: 0 44px 90px -48px rgba(81, 43, 212, .65);
}

/* security-print guilloche: two families of hairline rings */
.idcard__guilloche {
  position: absolute;
  inset: 0;
  background:
    repeating-radial-gradient(circle at 106% -6%, transparent 0 8.5px, rgba(124, 92, 255, .16) 9px 9.6px, transparent 10.1px 11px),
    repeating-radial-gradient(circle at -6% 106%, transparent 0 8.5px, rgba(236, 235, 233, .06) 9px 9.6px, transparent 10.1px 11px);
  opacity: .7;
  -webkit-mask-image: linear-gradient(180deg, #000, rgba(0, 0, 0, .25) 55%, #000);
          mask-image: linear-gradient(180deg, #000, rgba(0, 0, 0, .25) 55%, #000);
}

/* holographic foil: a violet and silver band that slides as the card turns */
.idcard__foil {
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg,
      transparent 34%,
      rgba(124, 92, 255, .14) 43%,
      rgba(236, 235, 233, .16) 48%,
      rgba(124, 92, 255, .12) 53%,
      transparent 62%);
  background-size: 260% 260%;
  background-position: var(--idcard-foil-x) var(--idcard-foil-y);
  mix-blend-mode: screen;
  transition: background-position .9s var(--ease);
}

/* lanyard slot */
.idcard__slot {
  position: absolute;
  top: 14px;
  left: 50%;
  width: 52px;
  height: 9px;
  margin-left: -26px;
  border-radius: var(--r-pill);
  background: #000;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .9), 0 0 0 1px rgba(255, 255, 255, .12);
}

.idcard__brand {
  grid-area: brand;
  margin: 0 0 18px;
  font-family: var(--font-mono);
  font-size: .75rem;
  line-height: 1.3;
  letter-spacing: .02em;
  color: var(--muted);
}

.idcard__brand span {
  color: var(--dim);
}

.idcard__photo {
  grid-area: photo;
  aspect-ratio: 1;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: #000;
}

.idcard__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* the same foil laminated over the portrait */
.idcard__photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg,
      transparent 30%,
      rgba(124, 92, 255, .9) 42%,
      rgba(236, 235, 233, .85) 48%,
      rgba(124, 92, 255, .8) 54%,
      transparent 66%);
  background-size: 260% 260%;
  background-position: var(--idcard-foil-x) var(--idcard-foil-y);
  mix-blend-mode: overlay;
  opacity: .8;
  pointer-events: none;
  transition: background-position .9s var(--ease);
}

.idcard__fields {
  grid-area: fields;
  align-self: end;
  display: grid;
  gap: 14px;
  margin: 0;
}

.idcard__field dt {
  font-family: var(--font-mono);
  font-size: .6875rem;
  line-height: 1.3;
  color: var(--dim);
}

.idcard__field dd {
  margin: 3px 0 0;
  font-size: .9375rem;
  line-height: 1.3;
}

.idcard__field .idcard__access {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--violet);
}

.idcard__id {
  grid-area: id;
  margin-top: 24px;
}

.idcard__name {
  font-size: clamp(2rem, 1.6rem + 1.4vw, 2.5rem);
  font-weight: 750;
  font-stretch: var(--wdth-display, 84%);
  line-height: 1.02;
  letter-spacing: -0.02em;
}

.idcard__role {
  max-width: 30ch;
  margin: 8px 0 0;
  font-size: var(--step--1);
  line-height: 1.45;
  color: var(--muted);
}

/* Code 128 (set B) of "sefasihlar": scans as the handle under it */
.idcard__barcode {
  --idcard-bar: rgba(236, 235, 233, .8);
  grid-area: code;
  height: 46px;
  margin-top: 24px;
  background: linear-gradient(90deg,
    var(--idcard-bar) 0% 1.3793%, transparent 1.3793% 2.069%,
    var(--idcard-bar) 2.069% 2.7586%, transparent 2.7586% 4.1379%,
    var(--idcard-bar) 4.1379% 4.8276%, transparent 4.8276% 7.5862%,
    var(--idcard-bar) 7.5862% 8.2759%, transparent 8.2759% 8.9655%,
    var(--idcard-bar) 8.9655% 11.7241%, transparent 11.7241% 13.1034%,
    var(--idcard-bar) 13.1034% 13.7931%, transparent 13.7931% 15.1724%,
    var(--idcard-bar) 15.1724% 15.8621%, transparent 15.8621% 16.5517%,
    var(--idcard-bar) 16.5517% 17.931%, transparent 17.931% 19.3103%,
    var(--idcard-bar) 19.3103% 20%, transparent 20% 22.7586%,
    var(--idcard-bar) 22.7586% 23.4483%, transparent 23.4483% 24.1379%,
    var(--idcard-bar) 24.1379% 25.5172%, transparent 25.5172% 28.2759%,
    var(--idcard-bar) 28.2759% 28.9655%, transparent 28.9655% 30.3448%,
    var(--idcard-bar) 30.3448% 31.0345%, transparent 31.0345% 32.4138%,
    var(--idcard-bar) 32.4138% 33.1034%, transparent 33.1034% 33.7931%,
    var(--idcard-bar) 33.7931% 35.1724%, transparent 35.1724% 37.931%,
    var(--idcard-bar) 37.931% 38.6207%, transparent 38.6207% 39.3103%,
    var(--idcard-bar) 39.3103% 42.069%, transparent 42.069% 43.4483%,
    var(--idcard-bar) 43.4483% 44.1379%, transparent 44.1379% 45.5172%,
    var(--idcard-bar) 45.5172% 46.2069%, transparent 46.2069% 48.9655%,
    var(--idcard-bar) 48.9655% 50.3448%, transparent 50.3448% 51.0345%,
    var(--idcard-bar) 51.0345% 51.7241%, transparent 51.7241% 53.1034%,
    var(--idcard-bar) 53.1034% 53.7931%, transparent 53.7931% 55.1724%,
    var(--idcard-bar) 55.1724% 56.5517%, transparent 56.5517% 59.3103%,
    var(--idcard-bar) 59.3103% 60%, transparent 60% 60.6897%,
    var(--idcard-bar) 60.6897% 62.069%, transparent 62.069% 63.4483%,
    var(--idcard-bar) 63.4483% 64.1379%, transparent 64.1379% 64.8276%,
    var(--idcard-bar) 64.8276% 65.5172%, transparent 65.5172% 68.2759%,
    var(--idcard-bar) 68.2759% 68.9655%, transparent 68.9655% 70.3448%,
    var(--idcard-bar) 70.3448% 71.0345%, transparent 71.0345% 71.7241%,
    var(--idcard-bar) 71.7241% 73.1034%, transparent 73.1034% 75.8621%,
    var(--idcard-bar) 75.8621% 76.5517%, transparent 76.5517% 77.931%,
    var(--idcard-bar) 77.931% 78.6207%, transparent 78.6207% 80%,
    var(--idcard-bar) 80% 82.7586%, transparent 82.7586% 83.4483%,
    var(--idcard-bar) 83.4483% 84.1379%, transparent 84.1379% 84.8276%,
    var(--idcard-bar) 84.8276% 86.8966%, transparent 86.8966% 87.5862%,
    var(--idcard-bar) 87.5862% 88.9655%, transparent 88.9655% 91.0345%,
    var(--idcard-bar) 91.0345% 92.4138%, transparent 92.4138% 94.4828%,
    var(--idcard-bar) 94.4828% 96.5517%, transparent 96.5517% 97.2414%,
    var(--idcard-bar) 97.2414% 97.931%, transparent 97.931% 98.6207%,
    var(--idcard-bar) 98.6207% 100%);
}

.idcard__foot {
  grid-area: foot;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 12px;
  margin-top: 9px;
}

.idcard__handle {
  font-family: var(--font-mono);
  font-size: .6875rem;
  letter-spacing: .14em;
  color: var(--dim);
}

.idcard__motto {
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: .01em;
}

/* hover answers the pointer: the foil slides across (fx.js tilts the card) */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .idcard:hover {
    --idcard-foil-x: 78%;
    --idcard-foil-y: 70%;
  }
}

/* ---------- facts under the card ---------- */

.about-facts {
  width: 100%;
  max-width: 380px;
  margin: 0;
}

.about-facts__item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 2px;
  border-bottom: 1px solid var(--line);
  font-size: var(--step--1);
  line-height: 1.4;
}

.about-facts__item:first-child {
  border-top: 1px solid var(--line);
}

.about-facts dt {
  color: var(--muted);
}

.about-facts dd {
  margin: 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* ---------- responsive ---------- */

@media (max-width: 1024px) {
  .about {
    grid-template-columns: minmax(0, 1fr);
  }

  .about__id {
    position: static;
    order: -1;
  }
}

@media (max-width: 480px) {
  .idcard {
    --idcard-pad: 20px;
    column-gap: 16px;
  }

  .idcard__name {
    font-size: 1.95rem;
  }

  .about-readme__table th,
  .about-readme__table td {
    padding: .55em .75em;
  }
}

@media (prefers-reduced-motion: reduce) {
  .idcard__foil,
  .idcard__photo::after {
    transition: none;
  }
}


/* ===== 30-experience.css ===== */
/* ==========================================================================
   30-experience.css: experience (#experience)
   The career drawn as `git log --graph`: an <ol> of commits on a vertical
   main lane, newest (HEAD) on top. Education sits on a side branch that
   forks from the root commit and merges back into main.
   Scope: .section--experience, .gitlog*. Shared classes (.chips, .chip,
   .status, .reveal) are used as they are.

   The graph is pure CSS. Every piece reads its geometry from custom
   properties on .gitlog, so lanes, nodes and curves stay aligned at every
   breakpoint:
     --gl-x       main lane centre, measured from the left edge of the log
     --gl-gap     main lane to side lane; each S-curve fills a gap-by-gap box
     --gl-anchor  centre of a commit's first text line, where its node sits
   ========================================================================== */

.section--experience .gitlog {
  --gl-stroke: 2px;
  --gl-x: 7px;
  --gl-gap: 22px;
  --gl-rail: 44px;              /* graph column; the text starts after it */
  --gl-node: 12px;
  --gl-dot: 8px;                /* merge and root commits */
  --gl-pad-top: 30px;
  --gl-pad-bottom: 36px;
  --gl-root-y: 14px;            /* root commit, measured up from the end of the log */
  --gl-anchor: calc(var(--step-0) * .75);   /* below 1025px a commit opens with its date (line-height 1.5) */
  --gl-side: rgba(236, 235, 233, .3);
  --gl-side-node: rgba(236, 235, 233, .62);
  position: relative;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Main lane: one line from HEAD down to the root commit, fading with age */
.section--experience .gitlog::before {
  content: "";
  position: absolute;
  top: calc(var(--gl-pad-top) + var(--gl-anchor));
  bottom: var(--gl-root-y);
  left: calc(var(--gl-x) - var(--gl-stroke) / 2);
  width: var(--gl-stroke);
  background: linear-gradient(180deg, var(--violet), rgba(124, 92, 255, .55) 50%, rgba(124, 92, 255, .3));
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   Commit: one open row per entry, separated by hairline rules
   -------------------------------------------------------------------------- */

.section--experience .gitlog__commit {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "date"
    "title"
    "context"
    "meta"
    "body";
  padding: var(--gl-pad-top) 0 var(--gl-pad-bottom) var(--gl-rail);
}

.section--experience .gitlog__commit::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  left: var(--gl-rail);
  height: 1px;
  background: var(--line);
}

.section--experience .gitlog__node {
  position: absolute;
  z-index: 1;
  top: calc(var(--gl-pad-top) + var(--gl-anchor) - var(--gl-node) / 2);
  left: calc(var(--gl-x) - var(--gl-node) / 2);
  width: var(--gl-node);
  height: var(--gl-node);
  box-sizing: border-box;
  border: var(--gl-stroke) solid var(--violet);
  border-radius: 50%;
  background: var(--bg);
  transition: background-color .3s var(--ease), border-color .3s var(--ease);
}

.section--experience .gitlog__commit--head .gitlog__node {
  background: var(--violet);
  box-shadow: 0 0 0 4px var(--violet-soft), 0 0 26px 3px rgba(81, 43, 212, .75);
}

.section--experience .gitlog__title {
  grid-area: title;
  margin: 6px 0 0;
  font-family: var(--font-sans);
  font-size: var(--step-1);
  font-weight: 700;
  font-stretch: var(--wdth-display);
  line-height: 1.1;
  letter-spacing: -.015em;
  color: var(--text);
  text-wrap: balance;
}

.section--experience .gitlog__date {
  grid-area: date;
  margin: 0;
  font-size: var(--step-0);
  font-weight: 600;
  font-stretch: var(--wdth-heading);
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.section--experience .gitlog__context {
  grid-area: context;
  margin: 8px 0 0;
  font-weight: 500;
  color: var(--muted);
}

.section--experience .gitlog__meta {
  grid-area: meta;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  margin-top: 16px;
}

.section--experience .gitlog__refs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
}

/* git decorations: (HEAD -> main), branch names */
.section--experience .gitlog__ref {
  display: inline-flex;
  align-items: center;
  padding: .32em .85em;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  font-family: var(--font-mono);
  font-size: .8125rem;
  font-weight: 500;
  font-variant-ligatures: none;   /* keep git's literal "->" instead of a ligature arrow */
  line-height: 1.25;
  white-space: nowrap;
  color: var(--muted);
}

.section--experience .gitlog__ref--head {
  border-color: rgba(124, 92, 255, .75);
  background: var(--violet-deep);
  color: var(--text);
  box-shadow: 0 0 22px -4px rgba(81, 43, 212, .85);
}

.section--experience .gitlog__place {
  margin: 0;
  font-size: var(--step--1);
  color: var(--muted);
}

.section--experience .gitlog__body {
  grid-area: body;
  min-width: 0;
  margin-top: 20px;
}

/* The commit message body: each change reads like an added line in a diff */
.section--experience .gitlog__changes {
  display: grid;
  gap: 10px;
  max-width: 60ch;               /* about 75 characters of Bricolage per line */
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--muted);
}

.section--experience .gitlog__changes li {
  position: relative;
  padding-left: 1.6em;
  line-height: 1.6;
}

.section--experience .gitlog__changes li::before {
  content: "+";
  content: "+" / "";
  position: absolute;
  top: 0;
  left: .1em;
  font-family: var(--font-mono);
  font-size: .875em;
  font-weight: 500;
  line-height: calc(1.6 / .875);
  color: var(--violet);
}

.section--experience .gitlog__changes strong {
  color: var(--text);
}

/* The stack chips sit under the message, one step quieter than the text */
.section--experience .gitlog__stack {
  max-width: var(--measure);
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

.section--experience .gitlog__stack .chip {
  color: var(--muted);
}


/* --------------------------------------------------------------------------
   Side branch (education): merge commit on main just under the rule, an
   S-curve out to the side lane, the commit, an S-curve back into main and
   the root commit where the main lane ends.
   -------------------------------------------------------------------------- */

.section--experience .gitlog__commit--branch {
  --gl-merge-y: 22px;
  --gl-pad-top: calc(var(--gl-merge-y) + var(--gl-gap) + 28px);
  --gl-pad-bottom: calc(var(--gl-root-y) + var(--gl-gap) + 32px);
}

.section--experience .gitlog__commit--branch .gitlog__node {
  left: calc(var(--gl-x) + var(--gl-gap) - var(--gl-node) / 2);
  border-color: var(--gl-side-node);
}

.section--experience .gitlog__graph {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.section--experience .gitlog__lane {
  position: absolute;
  top: calc(var(--gl-merge-y) + var(--gl-gap));
  bottom: calc(var(--gl-root-y) + var(--gl-gap));
  left: calc(var(--gl-x) + var(--gl-gap) - var(--gl-stroke) / 2);
  width: var(--gl-stroke);
  background: var(--gl-side);
}

/* Each S-curve is two quarter arcs drawn with rounded borders. Both arcs are
   (gap + stroke) / 2 square, so the stroke centre meets both lanes exactly. */
.section--experience .gitlog__curve {
  position: absolute;
  left: calc(var(--gl-x) - var(--gl-stroke) / 2);
  width: calc(var(--gl-gap) + var(--gl-stroke));
  height: var(--gl-gap);
}

.section--experience .gitlog__curve::before,
.section--experience .gitlog__curve::after {
  content: "";
  position: absolute;
  width: calc((var(--gl-gap) + var(--gl-stroke)) / 2);
  height: calc((var(--gl-gap) + var(--gl-stroke)) / 2);
  box-sizing: border-box;
  border: 0 solid var(--gl-side);
}

.section--experience .gitlog__curve--out { top: var(--gl-merge-y); }

.section--experience .gitlog__curve--out::before {
  top: 0;
  left: 0;
  border-bottom-width: var(--gl-stroke);
  border-left-width: var(--gl-stroke);
  border-bottom-left-radius: 100%;
}

.section--experience .gitlog__curve--out::after {
  right: 0;
  bottom: 0;
  border-top-width: var(--gl-stroke);
  border-right-width: var(--gl-stroke);
  border-top-right-radius: 100%;
}

.section--experience .gitlog__curve--in { bottom: var(--gl-root-y); }

.section--experience .gitlog__curve--in::before {
  top: 0;
  right: 0;
  border-right-width: var(--gl-stroke);
  border-bottom-width: var(--gl-stroke);
  border-bottom-right-radius: 100%;
}

.section--experience .gitlog__curve--in::after {
  bottom: 0;
  left: 0;
  border-top-width: var(--gl-stroke);
  border-left-width: var(--gl-stroke);
  border-top-left-radius: 100%;
}

.section--experience .gitlog__merge,
.section--experience .gitlog__root {
  position: absolute;
  z-index: 1;
  left: calc(var(--gl-x) - var(--gl-dot) / 2);
  width: var(--gl-dot);
  height: var(--gl-dot);
  box-sizing: border-box;
  border-radius: 50%;
}

.section--experience .gitlog__merge {
  top: calc(var(--gl-merge-y) - var(--gl-dot) / 2);
  background: var(--violet);
}

.section--experience .gitlog__root {
  bottom: calc(var(--gl-root-y) - var(--gl-dot) / 2);
  border: var(--gl-stroke) solid rgba(124, 92, 255, .7);
  background: var(--bg);
}


/* --------------------------------------------------------------------------
   Pointer feedback: the hovered commit's node fills in, nothing moves
   -------------------------------------------------------------------------- */

@media (hover: hover) {
  .section--experience .gitlog__commit:hover .gitlog__node {
    background: var(--violet);
  }

  .section--experience .gitlog__commit--branch:hover .gitlog__node {
    border-color: var(--text);
    background: var(--text);
  }
}


/* --------------------------------------------------------------------------
   Tablet and up: wider lanes, larger role titles
   -------------------------------------------------------------------------- */

@media (min-width: 769px) {
  .section--experience .gitlog {
    --gl-x: 11px;
    --gl-gap: 32px;
    --gl-rail: 72px;
    --gl-node: 14px;
    --gl-dot: 10px;
    --gl-pad-top: 44px;
    --gl-pad-bottom: 48px;
    --gl-root-y: 16px;
  }

  .section--experience .gitlog__title { font-size: var(--step-2); }
  .section--experience .gitlog__commit--branch .gitlog__title { font-size: var(--step-1); }
}


/* --------------------------------------------------------------------------
   Desktop: dates and refs in a margin column, the message beside them.
   The node now lines up with the role title (line-height 1.1).
   -------------------------------------------------------------------------- */

@media (min-width: 1025px) {
  .section--experience .gitlog {
    --gl-rail: 88px;
    --gl-pad-top: 52px;
    --gl-pad-bottom: 56px;
    --gl-anchor: calc(var(--step-2) * .55);
  }

  .section--experience .gitlog__commit--branch {
    --gl-anchor: calc(var(--step-1) * .55);
  }

  .section--experience .gitlog__commit {
    grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
    grid-template-rows: auto auto 1fr;
    grid-template-areas:
      "date title"
      "meta context"
      "meta body";
    column-gap: clamp(32px, 4vw, 64px);
  }

  .section--experience .gitlog__date,
  .section--experience .gitlog__title {
    align-self: baseline;
    margin-top: 0;
  }

  .section--experience .gitlog__meta {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    margin-top: 14px;
  }
}


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

/* Windows high contrast: keep the graph visible in the system text colour */
@media (forced-colors: active) {
  .section--experience .gitlog::before,
  .section--experience .gitlog__lane,
  .section--experience .gitlog__merge,
  .section--experience .gitlog__curve::before,
  .section--experience .gitlog__curve::after,
  .section--experience .gitlog__node,
  .section--experience .gitlog__root {
    forced-color-adjust: none;
    border-color: CanvasText;
  }

  .section--experience .gitlog::before,
  .section--experience .gitlog__lane,
  .section--experience .gitlog__merge {
    background: CanvasText;
  }

  .section--experience .gitlog__node,
  .section--experience .gitlog__root {
    background: Canvas;
    box-shadow: none;
  }
}


/* ===== 40-skills.css ===== */
/* ==========================================================================
   40-skills.css: skills (#skills)
   Scope: .section--skills, .skills__*, .skills-toggle*, .skills-group*,
   .skills-json*. The tech sphere itself (.techsphere*) belongs to
   45-techsphere.css; this file only places its wrapper (.skills__sphere).
   Shared classes (.chips, .chip, .link, .reveal) are used as they are.
   ========================================================================== */

.section--skills {
  --skills-key: #a995ff;    /* JSON keys: a lighter step of --violet that stays crisp in small mono */
  --skills-gutter: #5d5b59; /* line numbers: decorative and hidden from assistive tech */
  overflow-x: clip;         /* the rotating sphere can never cause sideways page scroll */
}


/* --------------------------------------------------------------------------
   Layout: sphere left, readable stack right; stacked (sphere first) below 1025px
   -------------------------------------------------------------------------- */

.skills__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: clamp(48px, 9vw, 72px);
  margin-top: clamp(40px, 6vw, 72px);
}

.skills__sphere {
  position: relative;
  width: min(100%, 520px);
  margin-inline: auto;
}

.skills__stack {
  min-width: 0;
  container: skills-stack / inline-size;
}

@media (min-width: 1025px) {
  .skills__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    column-gap: clamp(48px, 5.5vw, 88px);
    align-items: start;
  }

  .skills__sphere {
    width: 100%;
    margin-inline: 0;
  }
}

/* The sphere stays in view while the longer stack scrolls past it,
   but only when the screen is tall enough to hold it whole. */
@media (min-width: 1025px) and (min-height: 760px) {
  .skills__sphere {
    position: sticky;
    top: calc(var(--nav-h) + 48px);
  }
}


/* --------------------------------------------------------------------------
   View toggle: "Liste" / "skills.json" (segmented, sliding thumb)
   -------------------------------------------------------------------------- */

.skills__toolbar {
  display: flex;
  align-items: center;
  margin-bottom: clamp(20px, 3vw, 28px);
}

/* Without JavaScript only the list exists, so the switch would do nothing. */
html:not(.js) .skills__toolbar {
  display: none;
}

.skills-toggle {
  position: relative;
  isolation: isolate;
  display: inline-grid;
  grid-template-columns: 1fr 1fr;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
}

.skills-toggle::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 4px;
  bottom: 4px;
  left: 4px;
  width: calc(50% - 4px);
  border-radius: var(--r-pill);
  background: var(--violet-soft);
  box-shadow: inset 0 0 0 1px rgba(124, 92, 255, .5);
}

.skills__stack[data-view="json"] .skills-toggle::before {
  translate: 100% 0;
}

.skills-toggle__btn {
  appearance: none;
  margin: 0;
  min-height: 38px;
  padding: 0 20px;
  border: 0;
  border-radius: var(--r-pill);
  background: none;
  color: var(--muted);
  font: inherit;
  font-family: var(--font-sans);
  font-size: var(--step--1);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: color .2s ease;
  -webkit-tap-highlight-color: transparent;
}

.skills-toggle__btn--file {
  font-family: var(--font-mono);
  font-size: .8125rem;
  letter-spacing: -0.01em;
}

.skills-toggle__btn:hover,
.skills-toggle__btn[aria-pressed="true"] {
  color: var(--text);
}

.skills-toggle__btn[aria-pressed="true"] {
  cursor: default;
}

.skills-toggle__btn:focus-visible {
  outline: 2px solid var(--violet);
  outline-offset: 2px;
}

.skills__view[hidden] {
  display: none;
}


/* --------------------------------------------------------------------------
   List view: hairline-separated groups; term column + definition on wide stacks
   -------------------------------------------------------------------------- */

.skills-list {
  border-top: 1px solid var(--line);
}

.skills-group {
  padding-block: 22px 26px;
  border-bottom: 1px solid var(--line);
}

.skills-group__name {
  margin: 0 0 8px;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--step-1);
  font-weight: 650;
  font-stretch: 84%;
  line-height: 1.12;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.skills-group__note {
  margin: 0 0 16px;
  max-width: 58ch;
  color: var(--muted);
  font-size: var(--step-0);
  line-height: 1.55;
  text-wrap: pretty;
}

.skills-group__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

@container skills-stack (min-width: 560px) {
  .skills-group {
    display: grid;
    grid-template-columns: 10.5rem minmax(0, 1fr);
    column-gap: 28px;
    align-items: baseline;
    padding-block: 26px 30px;
  }

  .skills-group__name {
    margin: 0;
  }
}


/* --------------------------------------------------------------------------
   skills.json view: the same data as a wrapped, line-numbered code block
   -------------------------------------------------------------------------- */

.skills-json {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}

.skills-json__pre {
  margin: 0;
  padding: 22px 24px 24px calc(2ch + 44px);
  border: 0;
  background: none;
  color: var(--dim); /* punctuation; keys and strings are coloured below */
  font-family: var(--font-mono);
  font-size: .8125rem;
  line-height: 1.7;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  tab-size: 2;
}

.skills-json__code {
  display: block;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  font: inherit;
  counter-reset: skills-json-line;
}

/* One block per source line. Real leading spaces stay in the text (so a copy
   keeps the indentation); padding + negative text-indent make wrapped rows
   hang one level deeper than the line they continue. */
.skills-json__ln {
  display: block;
  position: relative;
  padding-left: 2ch;
  text-indent: -2ch;
  counter-increment: skills-json-line;
}

.skills-json__ln--1 {
  padding-left: 4ch;
  text-indent: -4ch;
}

.skills-json__ln--2 {
  padding-left: 6ch;
  text-indent: -6ch;
}

.skills-json__ln::before {
  content: counter(skills-json-line);
  content: counter(skills-json-line) / "";
  position: absolute;
  top: 0;
  right: 100%;
  margin-right: 20px;
  color: var(--skills-gutter);
  text-indent: 0;
  user-select: none;
  -webkit-user-select: none;
}

.skills-json__key {
  color: var(--skills-key);
}

.skills-json__str {
  color: var(--text);
}

.skills-json__link {
  color: var(--text);
}

/* Keep each array item on one row ("Entity Framework Core" never splits);
   the longest item still fits a 360px screen. */
@container skills-stack (min-width: 300px) {
  .skills-json__item {
    white-space: nowrap;
  }
}

@container skills-stack (max-width: 439.98px) {
  .skills-json__pre {
    padding: 16px 16px 18px;
    font-size: .75rem;
    line-height: 1.7;
  }

  .skills-json__ln::before {
    display: none;
  }
}


/* --------------------------------------------------------------------------
   Motion: only in answer to the toggle (the thumb slides, the new view settles)
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .skills-toggle::before {
    transition: translate .42s var(--ease);
  }

  .skills__stack[data-animate] .skills__view:not([hidden]) {
    animation: skills-view-in .42s var(--ease) both;
  }
}

@keyframes skills-view-in {
  from {
    opacity: 0;
    translate: 0 10px;
  }
}


/* ===== 45-techsphere.css ===== */
/* ==========================================================================
   45-techsphere.css: the interactive tech sphere ([data-techsphere])
   Owns every .techsphere* rule. Behaviour lives in 45-techsphere.js.

   Three states:
   1. Static (no JS, or prefers-reduced-motion): a centred, wrapped set of
      logo chips. Nothing moves.
   2. Waiting (JS on, motion allowed, before the script runs): the square is
      reserved and the chips stay hidden, so nothing jumps when the sphere
      takes over. If the script never runs, the chips fade in after 3.5s.
   3. Enhanced (.is-enhanced, added by the script): items sit on a sphere.
      The script owns each item's transform, opacity, filter and z-index
      every frame. Back items pass behind a violet core at the centre; the
      active item (front-most, hovered or focused) gets its colours, a
      violet ring and its label.
   ========================================================================== */

.techsphere {
  --ts-tile: 60px; /* tile size; the script sets it from the container width */
  position: relative;
  width: 100%;
  max-width: 520px;
  margin-inline: auto;
}


/* --------------------------------------------------------------------------
   1. Static: wrapped logo chips
   -------------------------------------------------------------------------- */

.techsphere__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  gap: 10px 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.techsphere__item {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 38px;
  padding: 5px 14px 5px 7px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text);
  font-size: var(--step--1);
  font-weight: 500;
  line-height: 1.2;
}

.techsphere__logo {
  flex: none;
  width: 22px;
  height: 22px;
  object-fit: contain;
}

.techsphere__label {
  white-space: nowrap;
}

/* A logo that failed to load: the label alone carries the name. */
.techsphere__item.is-noimg .techsphere__logo {
  display: none;
}

.techsphere__hint {
  margin: 18px 0 0;
  color: var(--dim);
  font-size: var(--step--1);
  line-height: 1.5;
  text-align: center;
}

/* The hint explains the interaction, so it only shows when there is one. */
.techsphere:not(.is-enhanced) .techsphere__hint {
  display: none;
}

/* Keyboard line, added by the script; replaces the drag hint while an item
   has keyboard focus. Screen readers get it as the items' description. */
.techsphere__hint-keys {
  display: none;
}

.techsphere.is-kbd .techsphere__hint-drag {
  display: none;
}

.techsphere.is-kbd .techsphere__hint-keys {
  display: inline;
  color: var(--muted);
}


/* --------------------------------------------------------------------------
   2. Waiting for the script (JS on, motion allowed)
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  html.js .techsphere:not(.is-enhanced) .techsphere__list {
    aspect-ratio: 1;
    opacity: 0;
    animation: techsphere-fallback .4s ease 3.5s forwards;
  }

  html.js .techsphere:not(.is-enhanced) .techsphere__hint {
    display: block;
    visibility: hidden;
  }
}

@keyframes techsphere-fallback {
  to { opacity: 1; }
}


/* --------------------------------------------------------------------------
   3. Enhanced: the sphere
   -------------------------------------------------------------------------- */

.techsphere.is-enhanced .techsphere__list {
  position: relative;
  display: block;
  aspect-ratio: 1;
  isolation: isolate; /* items and the core share one stacking context */
  touch-action: pan-y; /* horizontal drags rotate, vertical swipes scroll */
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  animation: techsphere-in .8s var(--ease) both;
}

.techsphere.is-dragging .techsphere__list,
.techsphere.is-dragging .techsphere__item {
  cursor: grabbing;
}

@keyframes techsphere-in {
  from { opacity: 0; }
}

/* Violet core at the sphere's centre depth (z-index 50). Items in the back
   half are stacked below it and read as further away; it fades out before
   the rim, so items crossing from back to front never pop. */
.techsphere.is-enhanced .techsphere__list::before {
  content: "";
  position: absolute;
  inset: 12%;
  z-index: 50;
  border-radius: 50%;
  background: radial-gradient(closest-side,
    rgba(124, 92, 255, .32),
    rgba(98, 64, 235, .17) 22%,
    rgba(81, 43, 212, .085) 46%,
    rgba(81, 43, 212, .03) 72%,
    rgba(81, 43, 212, 0));
  pointer-events: none;
}

/* Tile: black glass disc with a top sheen and a brushed-chrome rim. */
.techsphere.is-enhanced .techsphere__item {
  position: absolute;
  top: 50%;
  left: 50%;
  display: grid;
  place-items: center;
  width: var(--ts-tile);
  height: var(--ts-tile);
  min-height: 0;
  margin: calc(var(--ts-tile) / -2) 0 0 calc(var(--ts-tile) / -2);
  padding: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  background:
    radial-gradient(120% 90% at 50% -12%, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0) 60%) padding-box,
    linear-gradient(#000, #000) padding-box,
    linear-gradient(160deg,
      rgba(255, 255, 255, .5),
      rgba(255, 255, 255, .1) 36%,
      rgba(255, 255, 255, .04) 62%,
      rgba(255, 255, 255, .28)) border-box;
  cursor: pointer;
  transform-origin: 50% 50%;
  will-change: transform, opacity, filter;
}

/* Active ring: violet hairline with a soft halo. */
.techsphere.is-enhanced .techsphere__item::after {
  content: "";
  position: absolute;
  inset: -1px;
  border: 1px solid rgba(124, 92, 255, .95);
  border-radius: 50%;
  box-shadow: 0 0 0 4px rgba(124, 92, 255, .12), 0 0 28px rgba(124, 92, 255, .42);
  opacity: 0;
  transition: opacity .3s var(--ease);
  pointer-events: none;
}

.techsphere.is-enhanced .techsphere__item.is-active::after {
  opacity: 1;
}

.techsphere.is-enhanced .techsphere__item:focus {
  outline: none;
}

.techsphere.is-enhanced .techsphere__item:focus-visible {
  outline: 2px solid var(--violet);
  outline-offset: 6px;
}

/* Logos rest in silver and take their own colours when active. */
.techsphere.is-enhanced .techsphere__logo {
  width: 50%;
  height: 50%;
  pointer-events: none;
  -webkit-user-drag: none;
  user-select: none;
}

.techsphere.is-enhanced .techsphere__logo:not(.is-mono) {
  filter: grayscale(1) brightness(1.3) contrast(.94);
  transition: filter .45s var(--ease);
}

.techsphere.is-enhanced .techsphere__logo.is-mono {
  filter: brightness(0) invert(.84);
  transition: filter .45s var(--ease);
}

.techsphere.is-enhanced .techsphere__item.is-active .techsphere__logo:not(.is-mono) {
  filter: grayscale(0) brightness(1) contrast(1);
}

.techsphere.is-enhanced .techsphere__item.is-active .techsphere__logo.is-mono {
  filter: brightness(0) invert(1);
}

/* Monogram in place of a logo that failed to load. */
.techsphere.is-enhanced .techsphere__item.is-noimg::before {
  content: attr(data-mono);
  color: var(--muted);
  font-size: calc(var(--ts-tile) * .3);
  font-weight: 600;
  line-height: 1;
}

/* Label: a small pill under the active tile. It stays in the accessibility
   tree when hidden, so the list always reads in full. */
.techsphere.is-enhanced .techsphere__label {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  translate: -50% -3px;
  padding: 3px 10px 4px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: rgba(0, 0, 0, .82);
  color: var(--text);
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: .005em;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s var(--ease), translate .2s var(--ease);
}

.techsphere.is-enhanced .techsphere__item.is-active .techsphere__label {
  opacity: 1;
  translate: -50% 0;
}

/* clear the focus outline */
.techsphere.is-enhanced .techsphere__item:focus-visible .techsphere__label {
  top: calc(100% + 16px);
}

/* No labels while the sphere is being dragged or is still spinning fast. */
.techsphere.is-enhanced.is-dragging .techsphere__item.is-active .techsphere__label,
.techsphere.is-enhanced.is-spinning .techsphere__item.is-active .techsphere__label {
  opacity: 0;
}

@media (forced-colors: active) {
  .techsphere.is-enhanced .techsphere__item {
    border-color: CanvasText;
    background: Canvas;
  }

  .techsphere.is-enhanced .techsphere__list::before {
    display: none;
  }
}


/* ===== 50-security.css ===== */
/* ==========================================================================
   50-security: SOC monitor, hands-on capabilities, certificate flip cards
   Blocks: .security-monitor, .security-radar, .security-checks/.security-check,
   .security-caps/.security-cap, .certs, .cert.
   .cert is a [data-tilt] element: fx.js owns its transform. Nothing here sets
   transform on it; the flip turns the inner .cert__inner instead.
   Phosphor green is used only as security status (radar, [ OK ] marks).
   ========================================================================== */


/* --------------------------------------------------------------------------
   SOC monitor: radar on the left, secure-by-design checklist on the right
   -------------------------------------------------------------------------- */

.security-monitor {
  margin-top: clamp(40px, 5vw, 64px);
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}

.security-monitor__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 20px;
  padding: 14px clamp(16px, 3vw, 28px);
  border-bottom: 1px solid var(--line);
}

.security-monitor__proc {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--text);
}

.security-monitor__proc .icon {
  flex: none;
  color: var(--phosphor);
}

.security-monitor__flag {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--dim);
}

.security-monitor__bar .status {
  flex: none;
}

.security-monitor__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.security-monitor__scope {
  display: grid;
  place-items: center;
  padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 48px);
  border-bottom: 1px solid var(--line);
}

.security-monitor__checks {
  min-width: 0;
  padding: clamp(28px, 4vw, 48px) clamp(16px, 4vw, 48px) clamp(24px, 4vw, 44px);
}

.security-monitor__title {
  margin: 0;
  font-size: var(--step-2);
  font-weight: 700;
  font-stretch: var(--wdth-display);
  line-height: 1.08;
  letter-spacing: -0.015em;
  color: var(--text);
  text-wrap: balance;
}

.security-monitor__note {
  max-width: 60ch;
  margin: 12px 0 0;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--dim);
}

@media (min-width: 768px) {
  .security-monitor__body {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }

  .security-monitor__scope {
    border-bottom: 0;
    border-right: 1px solid var(--line);
  }
}

@media (max-width: 480px) {
  .security-monitor__flag {
    display: none;
  }
}


/* ---------- checklist ---------- */

.security-checks {
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
}

.security-check {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "mark name   key"
    ".    detail detail";
  align-items: baseline;
  column-gap: 14px;
  row-gap: 2px;
  padding: 14px 10px;
  border-bottom: 1px solid var(--line);
  transition: background-color .25s ease;
}

.security-check:hover,
.security-check.is-active {
  background: var(--surface-2);
}

.security-check__mark {
  grid-area: mark;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 700;
  line-height: 1.6;
  white-space: pre;
  color: var(--dim);
}

.security-check__state {
  display: inline-block;
  min-width: 4ch;
  text-align: center;
  color: var(--phosphor);
  text-shadow: 0 0 14px rgba(61, 255, 154, .45);
  transition: color .2s ease, text-shadow .2s ease;
}

.security-check__name {
  grid-area: name;
  margin: 0;
  font-weight: 600;
  line-height: 1.45;
  color: var(--text);
  transition: opacity .45s var(--ease);
}

.security-check__detail {
  grid-area: detail;
  margin: 0;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--muted);
  transition: opacity .45s var(--ease);
}

.security-check__key {
  grid-area: key;
  font-family: var(--font-mono);
  font-size: .75rem;
  line-height: 1.6;
  color: var(--dim);
  transition: color .2s ease;
}

.security-check.is-active .security-check__key {
  color: var(--phosphor);
}

/* one self-test pass (50-security.js) the first time the list is seen */
.security-check.is-pending .security-check__state {
  color: var(--dim);
  text-shadow: none;
}

.security-check.is-checking .security-check__state {
  color: var(--text);
}

.security-check.is-pending .security-check__name,
.security-check.is-pending .security-check__detail {
  opacity: .45;
}

@media (max-width: 480px) {
  .security-check {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "mark name"
      ".    detail";
    column-gap: 12px;
    padding-inline: 4px;
  }

  .security-check__key {
    display: none;
  }
}


/* ---------- radar (pure CSS; static under reduced motion) ---------- */

.security-radar {
  --sweep: 5s;
  position: relative;
  width: min(100%, 360px);
  aspect-ratio: 1;
  overflow: hidden;
  isolation: isolate;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background:
    radial-gradient(circle closest-side, rgba(61, 255, 154, .055), rgba(61, 255, 154, 0) 72%),
    #000;
  contain: layout paint;
}

.security-radar > span {
  position: absolute;
}

.security-radar__ring {
  inset: 12.5%;
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 50%;
}

.security-radar__ring--2 {
  inset: 25%;
}

.security-radar__ring--3 {
  inset: 37.5%;
  border-style: dashed;
  border-color: rgba(255, 255, 255, .07);
}

.security-radar__cross {
  inset: 0;
}

.security-radar__cross::before,
.security-radar__cross::after {
  content: "";
  position: absolute;
  background: rgba(255, 255, 255, .07);
}

.security-radar__cross::before {
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
}

.security-radar__cross::after {
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
}

/* bezel: fine ticks every 6deg, longer ones every 30deg */
.security-radar__ticks {
  inset: 0;
  border-radius: 50%;
}

.security-radar__ticks::before,
.security-radar__ticks::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
}

.security-radar__ticks::before {
  background: repeating-conic-gradient(from -.3deg, rgba(255, 255, 255, .26) 0deg .6deg, transparent .6deg 6deg);
  -webkit-mask: radial-gradient(circle closest-side, transparent calc(100% - 6px), #000 calc(100% - 5px));
          mask: radial-gradient(circle closest-side, transparent calc(100% - 6px), #000 calc(100% - 5px));
}

.security-radar__ticks::after {
  background: repeating-conic-gradient(from -.5deg, rgba(255, 255, 255, .5) 0deg 1deg, transparent 1deg 30deg);
  -webkit-mask: radial-gradient(circle closest-side, transparent calc(100% - 12px), #000 calc(100% - 11px));
          mask: radial-gradient(circle closest-side, transparent calc(100% - 12px), #000 calc(100% - 11px));
}

.security-radar__deg {
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1;
  letter-spacing: .04em;
  color: var(--dim);
}

.security-radar__deg--n { top: 20px; left: calc(50% + 6px); }
.security-radar__deg--e { right: 20px; top: calc(50% + 6px); }
.security-radar__deg--s { bottom: 20px; left: calc(50% + 6px); }
.security-radar__deg--w { left: 20px; top: calc(50% + 6px); }

/* the sweep: leading edge at 0deg, phosphor trail fading behind it */
.security-radar__sweep {
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg,
      rgba(61, 255, 154, 0) 0deg 220deg,
      rgba(61, 255, 154, .05) 290deg,
      rgba(61, 255, 154, .18) 345deg,
      rgba(61, 255, 154, .38) 359deg,
      rgba(61, 255, 154, 0) 360deg);
  animation: security-sweep var(--sweep) linear infinite;
  will-change: transform;
}

.security-radar__sweep::after {
  content: "";
  position: absolute;
  top: 0;
  left: calc(50% - .5px);
  width: 1px;
  height: 50%;
  background: linear-gradient(to top, rgba(61, 255, 154, .1), rgba(61, 255, 154, .9));
  box-shadow: 0 0 8px rgba(61, 255, 154, .55);
}

/* blips: one per checklist row; lit when the sweep passes their bearing.
   --p = bearing / 360deg, so the negative delay lines each blip up with the sweep. */
.security-radar__blip {
  --p: 0;
  left: var(--x, 50%);
  top: var(--y, 50%);
  width: 0;
  height: 0;
}

.security-radar__blip[data-key="tls"]  { --x: 69.9%; --y: 26.3%; --p: .111; }
.security-radar__blip[data-key="jwt"]  { --x: 67.2%; --y: 58%;   --p: .319; }
.security-radar__blip[data-key="xss"]  { --x: 43.7%; --y: 85.5%; --p: .528; }
.security-radar__blip[data-key="ddos"] { --x: 25.9%; --y: 56.5%; --p: .708; }
.security-radar__blip[data-key="log"]  { --x: 41%;   --y: 39.3%; --p: .889; }

.security-radar__dot {
  position: absolute;
  top: -3.5px;
  left: -3.5px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--phosphor);
  box-shadow: 0 0 12px 1px rgba(61, 255, 154, .6);
  opacity: .2;
  animation: security-blip var(--sweep) linear infinite;
  animation-delay: calc((var(--p) - 1) * var(--sweep));
}

.security-radar__dot::after {
  content: "";
  position: absolute;
  inset: -1px;
  border: 1px solid var(--phosphor);
  border-radius: 50%;
  opacity: 0;
  animation: security-ping var(--sweep) ease-out infinite;
  animation-delay: calc((var(--p) - 1) * var(--sweep));
}

.security-radar__label {
  position: absolute;
  top: -6px;
  left: 11px;
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1;
  white-space: nowrap;
  color: var(--phosphor);
  opacity: .2;
  animation: security-blip var(--sweep) linear infinite;
  animation-delay: calc((var(--p) - 1) * var(--sweep));
}

/* lock-on reticle: hovering a checklist row (or the self-test) targets its blip */
.security-radar__blip::before {
  content: "";
  position: absolute;
  top: -12px;
  left: -12px;
  width: 24px;
  height: 24px;
  background:
    linear-gradient(var(--phosphor), var(--phosphor)) left top / 6px 1px,
    linear-gradient(var(--phosphor), var(--phosphor)) left top / 1px 6px,
    linear-gradient(var(--phosphor), var(--phosphor)) right top / 6px 1px,
    linear-gradient(var(--phosphor), var(--phosphor)) right top / 1px 6px,
    linear-gradient(var(--phosphor), var(--phosphor)) left bottom / 6px 1px,
    linear-gradient(var(--phosphor), var(--phosphor)) left bottom / 1px 6px,
    linear-gradient(var(--phosphor), var(--phosphor)) right bottom / 6px 1px,
    linear-gradient(var(--phosphor), var(--phosphor)) right bottom / 1px 6px;
  background-repeat: no-repeat;
  opacity: 0;
  scale: 1.7;
  transition: opacity .25s ease, scale .4s var(--ease);
}

.security-radar__blip.is-active::before {
  opacity: 1;
  scale: 1;
}

/* !important is the only way to hold an animated value; the animation keeps
   running underneath, so the blip stays in step with the sweep afterwards */
.security-radar__blip.is-active .security-radar__dot,
.security-radar__blip.is-active .security-radar__label {
  opacity: 1 !important;
}

/* a single ring when the self-test confirms a check */
.security-radar__blip.is-hit::after {
  content: "";
  position: absolute;
  top: -5px;
  left: -5px;
  width: 10px;
  height: 10px;
  border: 1px solid var(--phosphor);
  border-radius: 50%;
  animation: security-hit .9s ease-out forwards;
}

.security-radar__core {
  top: 50%;
  left: 50%;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: var(--text);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, .06);
}

/* paused by 50-security.js while the radar is off screen */
.security-radar.is-paused .security-radar__sweep,
.security-radar.is-paused .security-radar__dot,
.security-radar.is-paused .security-radar__dot::after,
.security-radar.is-paused .security-radar__label {
  animation-play-state: paused;
}

@keyframes security-sweep {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

@keyframes security-blip {
  0%   { opacity: 1; }
  6%   { opacity: 1; }
  55%  { opacity: .2; }
  100% { opacity: .2; }
}

@keyframes security-ping {
  0%   { opacity: .85; scale: 1; }
  26%  { opacity: 0;   scale: 4.4; }
  100% { opacity: 0;   scale: 4.4; }
}

@keyframes security-hit {
  from { opacity: 1; scale: 1; }
  to   { opacity: 0; scale: 5; }
}


/* --------------------------------------------------------------------------
   Capabilities: open two-column list with rules, not boxes
   -------------------------------------------------------------------------- */

.security-caps {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 28px clamp(32px, 5vw, 80px);
  margin-top: clamp(80px, 10vw, 136px);
}

.security-caps__title {
  margin: 0;
  font-size: var(--step-3);
  font-weight: 700;
  font-stretch: var(--wdth-display);
  line-height: 1.04;
  letter-spacing: -0.02em;
  color: var(--text);
  text-wrap: balance;
}

.security-caps__lead {
  max-width: 40ch;
  margin: 14px 0 0;
  color: var(--muted);
}

.security-caps__list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  column-gap: clamp(28px, 4vw, 48px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.security-cap {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 16px;
  padding: 24px 0 28px;
  border-top: 1px solid var(--line);
}

.security-cap__icon {
  width: 22px;
  height: 22px;
  margin-top: 3px;
  color: var(--violet);
}

.security-cap__body {
  min-width: 0;
}

.security-cap__title {
  margin: 0;
  font-size: var(--step-1);
  font-weight: 650;
  font-stretch: var(--wdth-heading);
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--text);
}

.security-cap__text {
  max-width: 52ch;
  margin: 8px 0 0;
  line-height: 1.6;
  color: var(--muted);
}

.security-cap__cert {
  display: inline-block;
  margin-top: 12px;
  font-size: var(--step--1);
}

@media (min-width: 768px) {
  .security-caps__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .security-caps {
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  }

  .security-caps__intro {
    position: sticky;
    top: calc(var(--nav-h) + 40px);
    align-self: start;
  }
}


/* --------------------------------------------------------------------------
   Certificates: credential cards that flip on Y
   -------------------------------------------------------------------------- */

.certs {
  margin-top: clamp(96px, 12vw, 168px);
  scroll-margin-top: calc(var(--nav-h) + 24px);
}

.certs__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: end;
  gap: 16px clamp(32px, 5vw, 80px);
  margin-bottom: clamp(28px, 4vw, 48px);
}

.certs__path {
  margin: 0 0 12px;
}

/* the long sub-path must fit at 360px: its rule may shrink to nothing */
.certs__path::after {
  min-width: 0;
}

/* the rule draws itself as the block arrives, like the section head */
.js .certs.reveal .certs__path::after {
  scale: 0 1;
  transition: scale 1.3s var(--ease) 200ms;
}

.js .certs.reveal.is-visible .certs__path::after {
  scale: 1 1;
}

.certs__title {
  margin: 0;
  font-size: var(--step-3);
  font-weight: 700;
  font-stretch: var(--wdth-display);
  line-height: 1.04;
  letter-spacing: -0.02em;
}

.certs__lead {
  max-width: 48ch;
  margin: 0;
  color: var(--muted);
}

@media (min-width: 1024px) {
  .certs__head {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .certs__lead {
    justify-self: end;
  }
}

.certs__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(16px, 2vw, 24px);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 768px) {
  .certs__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.certs__item {
  display: grid;
  min-width: 0;
}

/* ---------- the card ---------- */

.cert {
  --cert-pad: clamp(20px, 2.6vw, 30px);
  --cert-metal: linear-gradient(135deg,
      rgba(255, 255, 255, .46),
      rgba(255, 255, 255, .08) 26%,
      rgba(255, 255, 255, .26) 50%,
      rgba(255, 255, 255, .06) 74%,
      rgba(255, 255, 255, .38));
  position: relative;
  display: grid;
  min-width: 0;
  border-radius: var(--r-md);
  scroll-margin-top: calc(var(--nav-h) + 32px);
  -webkit-tap-highlight-color: transparent;
}

html.js .cert {
  cursor: pointer;
}

/* quiet hover: the metal edge catches more light */
.cert:hover,
.cert:focus-within {
  --cert-metal: linear-gradient(135deg,
      rgba(255, 255, 255, .72),
      rgba(255, 255, 255, .14) 26%,
      rgba(255, 255, 255, .44) 50%,
      rgba(255, 255, 255, .1) 74%,
      rgba(255, 255, 255, .6));
}

.cert__inner {
  position: relative;
  display: grid;
  grid-template: minmax(0, 1fr) / minmax(0, 1fr);
  min-width: 0;
  transform-style: preserve-3d;
  transform: perspective(1600px) rotateY(0deg);
  transition: transform .85s var(--ease);
}

.cert.is-flipped .cert__inner {
  transform: perspective(1600px) rotateY(180deg);
}

.cert__face {
  grid-area: 1 / 1;
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: clamp(250px, 22vw, 300px);
  padding: var(--cert-pad);
  overflow: hidden;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    linear-gradient(#000, #000) padding-box,
    var(--cert-metal) border-box;
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
}

.cert__face--front {
  transform: rotateY(0deg);
}

.cert__face--back {
  transform: rotateY(180deg);
  background:
    linear-gradient(rgba(124, 92, 255, .075), rgba(124, 92, 255, .015)) padding-box,
    linear-gradient(#000, #000) padding-box,
    var(--cert-metal) border-box;
}

.cert__face > * {
  position: relative;
  z-index: 1;
}

/* security print: two families of hairline rings that make a moire */
.cert__face--front::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    repeating-radial-gradient(circle at 104% -8%, transparent 0 6px, rgba(255, 255, 255, .07) 6.5px 7.2px, transparent 7.7px 8px),
    repeating-radial-gradient(circle at 82% -30%, transparent 0 8px, rgba(255, 255, 255, .05) 8.5px 9.2px, transparent 9.7px 10px);
  -webkit-mask-image: radial-gradient(115% 95% at 100% 0%, #000, transparent 64%);
          mask-image: radial-gradient(115% 95% at 100% 0%, #000, transparent 64%);
}

/* the back: fine diagonal hatching, like the reverse of a printed document */
.cert__face--back::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: repeating-linear-gradient(135deg, rgba(255, 255, 255, .03) 0 1px, transparent 1px 7px);
  -webkit-mask-image: linear-gradient(to top, #000, transparent 75%);
          mask-image: linear-gradient(to top, #000, transparent 75%);
}

/* silver foil sheen; 50-security.js moves it with the pointer (--mx, 0..1) */
.cert__face--front::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(105deg,
      transparent 38%,
      rgba(255, 255, 255, .06) 45%,
      rgba(255, 255, 255, .11) 49%,
      rgba(124, 92, 255, .09) 52%,
      rgba(255, 255, 255, .04) 56%,
      transparent 63%) no-repeat;
  background-size: 300% 100%;
  background-position: calc((1.5 - var(--mx, -.2)) * 50%) 0;
  transition: background-position .6s var(--ease);
}

.cert__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

/* rosette seal: engraved teeth around a black core */
.cert__seal {
  display: grid;
  flex: none;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  color: var(--text);
  background:
    radial-gradient(circle closest-side, #000 calc(100% - 9px), rgba(255, 255, 255, .3) calc(100% - 9px) calc(100% - 8px), transparent calc(100% - 8px)),
    repeating-conic-gradient(from 0deg, rgba(255, 255, 255, .55) 0deg 2deg, rgba(255, 255, 255, .1) 2deg 7.5deg);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .12);
}

.cert__seal .icon {
  width: 22px;
  height: 22px;
}

.cert__tag {
  margin-top: 4px;
  text-align: right;
}

.cert__title {
  max-width: 20ch;
  margin: auto 0 0;
  padding-top: 28px;
  font-size: var(--step-2);
  font-weight: 700;
  font-stretch: var(--wdth-display);
  line-height: 1.06;
  letter-spacing: -0.02em;
  color: var(--text);
  text-wrap: balance;
}

.cert__issuer {
  margin: 10px 0 0;
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--muted);
}

.cert__levels {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}

/* bottom rule: engraved file name on the left, flip button over the right */
.cert__foot {
  display: flex;
  align-items: center;
  min-width: 0;
  margin-top: 22px;
  padding: 14px 150px 0 0;
  border-top: 1px solid rgba(255, 255, 255, .08);
}

.cert__engraving {
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: .75rem;
  font-weight: 500;
  line-height: 38px;
  letter-spacing: .04em;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: rgba(255, 255, 255, .36);
  text-shadow: 0 1px 0 rgba(255, 255, 255, .08), 0 -1px 0 #000;
}

/* back face content */
.cert__back-title {
  max-width: 34ch;
  margin: 0;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
}

.cert__fields {
  display: grid;
  gap: 14px;
  margin: 18px 0 0;
}

.cert__field {
  display: grid;
  gap: 4px;
}

.cert__fields dt {
  font-family: var(--font-mono);
  font-size: .75rem;
  line-height: 1.4;
  color: var(--dim);
}

.cert__fields dd {
  max-width: 52ch;
  margin: 0;
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--text);
}

.cert__face--back .cert__foot {
  margin-top: auto;
}

.cert__face--back .cert__fields {
  margin-bottom: 22px;
}

/* the flip toggle sits outside both faces, so focus never lands in a hidden one */
.cert__flip {
  position: absolute;
  right: var(--cert-pad);
  bottom: var(--cert-pad);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  margin: 0;
  padding: 0 16px 0 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: rgba(0, 0, 0, .78);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--step--1);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  translate: 0 0 1px;
  transition: border-color .25s ease, background-color .25s ease;
}

.cert__flip:hover {
  border-color: var(--violet);
}

.cert__flip:focus-visible {
  outline: 2px solid var(--violet);
  outline-offset: 3px;
}

.cert__flip[aria-pressed="true"] {
  border-color: var(--violet);
  background: rgba(124, 92, 255, .16);
}

.cert__flip .icon {
  width: 16px;
  height: 16px;
  transition: rotate .6s var(--ease);
}

.cert__flip[aria-pressed="true"] .icon {
  rotate: 180deg;
}

/* arriving from the "see certificate" links (main.js focuses the card title) */
.cert:target .cert__face,
.cert:has(.cert__title:focus) .cert__face {
  box-shadow: 0 0 0 1px var(--violet), 0 0 48px -12px rgba(124, 92, 255, .55);
}

@media (max-width: 480px) {
  .cert__title {
    padding-top: 22px;
  }

  .cert__foot {
    padding-right: 140px;
  }
}

/* No JavaScript: show both faces stacked, no flip control */
html:not(.js) .cert__inner {
  gap: 8px;
  transform: none;
}

html:not(.js) .cert__face {
  grid-area: auto;
  transform: none;
  -webkit-backface-visibility: visible;
          backface-visibility: visible;
}

html:not(.js) .cert__flip {
  display: none;
}

html:not(.js) .cert__foot {
  padding-right: 0;
}


/* --------------------------------------------------------------------------
   Reduced motion: still radar, instant flip, no sheen travel
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .security-radar__sweep,
  .security-radar__dot,
  .security-radar__dot::after,
  .security-radar__label,
  .security-radar__blip.is-hit::after {
    animation: none;
  }

  .security-radar__sweep {
    transform: rotate(64deg);
  }

  .security-radar__dot,
  .security-radar__label {
    opacity: .85;
  }

  .security-radar__dot::after {
    opacity: 0;
  }

  .security-radar__blip::before,
  .security-check,
  .security-check__name,
  .security-check__detail,
  .cert__inner,
  .cert__face--front::after,
  .cert__flip .icon {
    transition: none;
  }
}


/* ===== 60-projects.css ===== */
/* ==========================================================================
   60-projects: #projects
   Owns .projects*, .project*, .arch3d*, .repo-index*, .repo-row*.
   The globe (.globe*) belongs to the globe agent; this file only sizes its column.
   Transform ownership: .arch3d carries [data-tilt] (fx.js owns its transform);
   the isometric transform lives on the inner .arch3d__stage.
   ========================================================================== */

/* Spread factor of the exploded 3D stack (animated once when the panel is revealed). */
@property --arch-k {
  syntax: '<number>';
  inherits: true;
  initial-value: 1;
}

.projects {
  display: grid;
  gap: clamp(20px, 3vw, 32px);
}

/* --------------------------------------------------------------------------
   Feature panels
   -------------------------------------------------------------------------- */
.project {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.project__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
  padding: clamp(24px, 5vw, 56px);
}

.project__title {
  margin: 0;
  font-size: var(--step-3);
  font-weight: 700;
  font-stretch: 84%;
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--text);
  text-wrap: balance;
}

.project__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 20px;
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--muted);
}

.project__badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  color: var(--text);
}

.project__badge .icon {
  width: 1em;
  height: 1em;
  margin-left: -2px;
}

.project__desc {
  margin: 22px 0 0;
  max-width: 60ch;
  color: var(--muted);
}

/* The two numbers, read as a spec sheet */
.project__stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  width: 100%;
  margin: 32px 0 0;
  padding: 0;
  list-style: none;
  border-block: 1px solid var(--line);
}

.project__stat {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  padding: 22px 0 20px;
}

.project__stat + .project__stat {
  padding-left: clamp(18px, 3vw, 32px);
  border-left: 1px solid var(--line);
}

.project__stat-value {
  align-self: flex-start;
  font-size: clamp(2.5rem, 5.4vw, 4.25rem);
  font-weight: 700;
  font-stretch: 78%;
  line-height: .92;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.project__stat-label {
  font-size: var(--step--1);
  line-height: 1.35;
  color: var(--muted);
}

.project__points {
  display: grid;
  gap: 12px;
  max-width: 62ch;
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
}

.project__points li {
  position: relative;
  padding-left: 26px;
}

/* Marker: a small isometric tile, echoing the architecture diagram */
.project__points li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: .62em;
  width: 8px;
  height: 8px;
  border: 1.5px solid var(--violet);
  border-radius: 2px;
  transform: scale(1, .62) rotate(45deg);
}

.project__chips {
  margin-top: 28px;
}

.project__actions {
  margin: 32px 0 0;
}

.project__visual {
  position: relative;
  min-width: 0;
  margin: 0;
  border-top: 1px solid var(--line);
}

/* Globe column: provides the width only; .globe sizes itself (globe agent). */
.project__visual--globe {
  display: grid;
  align-content: center;
  padding-block: clamp(20px, 4vw, 40px);
  padding-inline: max(clamp(16px, 4vw, 40px), calc((100% - 560px) / 2));
}

@media (min-width: 1024px) {
  .project {
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr);
  }

  .project__visual {
    border-top: 0;
    border-left: 1px solid var(--line);
  }

  .project--freecourse {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
  }

  .project--freecourse .project__visual {
    order: -1;
    border-left: 0;
    border-right: 1px solid var(--line);
  }

  .project__visual--globe {
    padding: clamp(24px, 3vw, 40px);
  }
}

/* --------------------------------------------------------------------------
   FreeCourse architecture diagram
   Default (mobile, reduced motion): a clean vertical 2D diagram.
   >= 768px with motion allowed: an exploded isometric stack in CSS 3D.
   -------------------------------------------------------------------------- */
.project__visual--arch {
  display: grid;
  align-content: center;
  gap: 18px;
  padding: clamp(24px, 4vw, 40px) clamp(16px, 4vw, 40px);
}

.arch3d {
  position: relative;
}

.arch3d__stage {
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.arch3d__layer {
  position: relative;
  padding: 14px 14px 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, .02);
}

.arch3d__layer--gateway {
  border-color: rgba(124, 92, 255, .55);
  background: rgba(124, 92, 255, .06);
}

/* Request path between layers */
.arch3d__layer + .arch3d__layer::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 100%;
  width: 1px;
  height: 28px;
  background: linear-gradient(180deg, var(--line-strong), var(--violet));
}

.arch3d__layer + .arch3d__layer::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 100%;
  width: 5px;
  height: 5px;
  margin: 0 0 -3px -2px;
  border-radius: 50%;
  background: var(--violet);
}

.arch3d__name {
  margin: 0 0 10px;
  font-size: .75rem;
  line-height: 1.3;
  color: var(--dim);
}

.arch3d__tiles {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.arch3d__label {
  display: inline-flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 10px 7px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: #000;
  font-size: .8125rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--text);
  white-space: nowrap;
}

.arch3d__sub {
  font-size: .6875rem;
  font-weight: 400;
  color: var(--muted);
}

.arch3d__tile--accent .arch3d__label {
  border-color: var(--violet);
  background: #0b0717;
}

.arch3d__tile--accent .arch3d__sub {
  color: #b9a8ff;
}

.arch3d__wire,
.arch3d__traces {
  display: none;
}

.arch3d__caption {
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--dim);
  text-align: center;
}

@media (min-width: 768px) and (prefers-reduced-motion: no-preference) {
  .arch3d {
    --arch-scale: 1;
  }

  /* Flat on purpose: the stack renders orthographically into this plane, so the
     tilt on .arch3d turns it like a card and never adds a perspective jump. */
  .arch3d__scene {
    position: relative;
    height: calc(470px * var(--arch-scale));
    transform-style: flat;
  }

  .arch3d__stage {
    position: absolute;
    left: calc(50% - 14px * var(--arch-scale));
    top: calc(50% + 104px * var(--arch-scale));
    display: block;
    width: 0;
    height: 0;
    transform-style: preserve-3d;
    transform: scale(var(--arch-scale)) rotateX(55deg) rotateZ(-40deg);
    transition: --arch-k 1.6s var(--ease) .15s;
  }

  html.js .project--freecourse.reveal:not(.is-visible) .arch3d__stage {
    --arch-k: .12;
  }

  /* Layers: plates stacked along Z */
  .arch3d__layer {
    position: absolute;
    left: calc(var(--w) * -.5px);
    top: calc(var(--d) * -.5px);
    width: calc(var(--w) * 1px);
    height: calc(var(--d) * 1px);
    padding: 0;
    border: 1px solid rgba(236, 235, 233, .2);
    border-radius: 16px;
    background-color: rgba(236, 235, 233, .022);
    background-image: radial-gradient(circle, rgba(236, 235, 233, .17) 1px, transparent 1.4px);
    background-size: 20px 20px;
    background-position: 0 0;
    transform-style: preserve-3d;
    transform: translateZ(calc(var(--z) * var(--arch-k) * 1px));
  }

  .arch3d__layer + .arch3d__layer::before,
  .arch3d__layer + .arch3d__layer::after {
    display: none;
  }

  .arch3d__layer--client   { --w: 170; --d: 110; --z: 345; --drop: 95; }
  .arch3d__layer--gateway  { --w: 270; --d: 150; --z: 250; --drop: 140; }
  .arch3d__layer--services { --w: 380; --d: 220; --z: 110; --drop: 110; }
  .arch3d__layer--data     { --w: 400; --d: 230; --z: 0;   --drop: 0; }

  .arch3d__layer--gateway {
    border-color: rgba(124, 92, 255, .6);
    background-color: rgba(124, 92, 255, .06);
    background-image: radial-gradient(circle, rgba(124, 92, 255, .32) 1px, transparent 1.4px);
    box-shadow: 0 0 70px -12px rgba(81, 43, 212, .7);
  }

  /* Layer names sit just left of each plate's left corner, facing the viewer */
  .arch3d__name {
    position: absolute;
    left: 0;
    top: 0;
    margin: 0;
    transform-origin: 0 0;
    transform: rotateZ(40deg) rotateX(-55deg) translateZ(400px) translate(calc(-100% - 14px), -50%);
    white-space: nowrap;
  }

  .arch3d__tiles {
    display: block;
    position: absolute;
    inset: 0;
    gap: 0;
    transform-style: preserve-3d;
  }

  /* Tiles: small raised pads on the plate */
  .arch3d__tile {
    position: absolute;
    left: calc(50% + var(--x) * 1px);
    top: calc(50% + var(--y) * 1px);
    width: 34px;
    height: 34px;
    margin: -17px 0 0 -17px;
    border: 1px solid rgba(236, 235, 233, .32);
    border-radius: 9px;
    background: rgba(236, 235, 233, .07);
    transform-style: preserve-3d;
  }

  .arch3d__tile::before {
    content: "";
    position: absolute;
    inset: -1px;
    border: 1px solid rgba(236, 235, 233, .6);
    border-radius: inherit;
    background: #050505;
    transform: translateZ(10px);
  }

  .arch3d__tile--accent {
    border-color: rgba(124, 92, 255, .7);
    background: rgba(124, 92, 255, .25);
    box-shadow: 0 0 26px 2px rgba(124, 92, 255, .55);
  }

  .arch3d__tile--accent::before {
    border-color: var(--violet);
    background: #120a2e;
  }

  .arch3d__tile--web         { --x: 0;    --y: 0; }
  .arch3d__tile--ocelot      { --x: 0;    --y: 0; }
  .arch3d__tile--identity    { --x: 105;  --y: -35; }
  .arch3d__tile--catalog,
  .arch3d__tile--mongo       { --x: -150; --y: 55; }
  .arch3d__tile--basket,
  .arch3d__tile--redis       { --x: -50;  --y: 55; }
  .arch3d__tile--discount,
  .arch3d__tile--postgres    { --x: 50;   --y: 55; }
  .arch3d__tile--order,
  .arch3d__tile--sqlserver   { --x: 150;  --y: 55; }
  .arch3d__tile--photostock  { --x: -150; --y: -55; }
  .arch3d__tile--fakepayment { --x: -50;  --y: -55; }

  /* Labels: counter-rotated so they face the viewer, pushed forward in depth so
     plates never cover them, then offset in screen space (--lx/--ly). */
  .arch3d__label {
    --lx: -50%;
    --ly: calc(-100% - 20px);
    position: absolute;
    left: 50%;
    top: 50%;
    display: block;
    padding: 4px 9px 5px;
    border-color: rgba(236, 235, 233, .26);
    transform-origin: 0 0;
    transform: translateZ(10px) rotateZ(40deg) rotateX(-55deg) translateZ(400px) translate(var(--lx), var(--ly));
  }

  .arch3d__sub {
    display: block;
  }

  /* Leader line from label to pad */
  .arch3d__label::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 100%;
    width: 1px;
    height: 20px;
    background: rgba(236, 235, 233, .32);
  }

  .arch3d__tile--mongo .arch3d__label,
  .arch3d__tile--redis .arch3d__label,
  .arch3d__tile--postgres .arch3d__label {
    --ly: 20px;
  }

  .arch3d__tile--mongo .arch3d__label::after,
  .arch3d__tile--redis .arch3d__label::after,
  .arch3d__tile--postgres .arch3d__label::after {
    top: auto;
    bottom: 100%;
  }

  .arch3d__tile--ocelot .arch3d__label {
    --lx: calc(-100% - 24px);
    --ly: -50%;
  }

  .arch3d__tile--identity .arch3d__label,
  .arch3d__tile--sqlserver .arch3d__label {
    --lx: 24px;
    --ly: -50%;
  }

  .arch3d__tile--ocelot .arch3d__label::after,
  .arch3d__tile--identity .arch3d__label::after,
  .arch3d__tile--sqlserver .arch3d__label::after {
    top: 50%;
    width: 24px;
    height: 1px;
  }

  .arch3d__tile--ocelot .arch3d__label::after {
    left: 100%;
  }

  .arch3d__tile--identity .arch3d__label::after,
  .arch3d__tile--sqlserver .arch3d__label::after {
    left: auto;
    right: 100%;
  }

  .arch3d__tile--accent .arch3d__label::after {
    background: var(--violet);
  }

  /* Vertical connectors: hang from a pad down to the layer below */
  .arch3d__wire {
    display: block;
    position: absolute;
    left: 50%;
    top: 50%;
    width: 1px;
    height: calc(var(--drop) * 1px);
    margin-left: -.5px;
    transform-origin: 50% 0;
    transform: rotateX(-90deg) scaleY(var(--arch-k));
    background: linear-gradient(180deg, rgba(124, 92, 255, .95), rgba(236, 235, 233, .3));
  }

  /* The travelling light: one request moving down the stack */
  .arch3d__wire::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 0;
    width: 5px;
    height: 5px;
    margin: -2.5px 0 0 -2.5px;
    border-radius: 50%;
    background: #ddd5ff;
    box-shadow: 0 0 0 2px rgba(124, 92, 255, .35), 0 0 12px 3px rgba(124, 92, 255, .9);
    opacity: 0;
    animation: arch3d-flow 3.6s cubic-bezier(.45, 0, .55, 1) infinite;
    animation-delay: var(--flow-delay, 0s);
  }

  .arch3d__tile--web      { --flow-delay: 0s; }
  .arch3d__tile--ocelot   { --flow-delay: 1.2s; }
  .arch3d__tile--catalog  { --flow-delay: 2.4s; }
  .arch3d__tile--basket   { --flow-delay: 2.6s; }
  .arch3d__tile--discount { --flow-delay: 2.8s; }
  .arch3d__tile--order    { --flow-delay: 3s; }

  @keyframes arch3d-flow {
    0%   { translate: 0 0; opacity: 0; }
    6%   { opacity: 1; }
    30%  { opacity: 1; }
    36%  { translate: 0 calc(var(--drop) * 1px); opacity: 0; }
    100% { translate: 0 calc(var(--drop) * 1px); opacity: 0; }
  }

  /* Traces drawn on the plates (gateway to auth, service bus) */
  .arch3d__traces {
    display: block;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
  }

  .arch3d__trace {
    fill: none;
    stroke: rgba(124, 92, 255, .7);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .arch3d__trace--auth {
    stroke-dasharray: 4 5;
  }

  .arch3d__hub {
    fill: #000;
    stroke: var(--violet);
    stroke-width: 1.5;
  }
}

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .arch3d {
    --arch-scale: .86;
  }
}

@media (min-width: 1280px) and (prefers-reduced-motion: no-preference) {
  .arch3d {
    --arch-scale: 1;
  }
}

/* --------------------------------------------------------------------------
   Repository index: a table-like list, stacked blocks on small screens
   -------------------------------------------------------------------------- */
.repo-index {
  margin-top: clamp(72px, 9vw, 120px);
}

.repo-index__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 32px;
  margin-bottom: 24px;
}

.repo-index__title {
  margin: 0;
  font-size: var(--step-2);
  font-weight: 700;
  font-stretch: 84%;
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--text);
}

.repo-index__intro {
  margin: 0;
  color: var(--muted);
}

.repo-index__cols {
  display: none;
}

.repo-index__list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line-strong);
}

.repo-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "name link"
    "desc desc"
    "stack stack";
  gap: 12px 16px;
  padding: 22px 0;
  border-bottom: 1px solid var(--line);
}

.repo-row__name {
  grid-area: name;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  margin: 0;
}

.repo-row__slug {
  font-family: var(--font-mono);
  font-size: .9375rem;
  font-weight: 500;
  line-height: 1.35;
  color: var(--text);
  overflow-wrap: anywhere;
}

.repo-row__title {
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--muted);
}

.repo-row__desc {
  grid-area: desc;
  max-width: 68ch;
  margin: 0;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--muted);
}

.repo-row__stack {
  grid-area: stack;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.repo-row__link {
  grid-area: link;
  align-self: start;
  white-space: nowrap;
}

@media (min-width: 900px) {
  .repo-index__cols,
  .repo-row {
    grid-template-columns: minmax(0, 13.5rem) minmax(0, 1fr) minmax(0, 15rem) 7.25rem;
    column-gap: clamp(20px, 2.6vw, 40px);
  }

  .repo-index__cols {
    display: grid;
    padding: 0 16px 12px;
    font-size: var(--step--1);
    color: var(--dim);
  }

  .repo-index__cols span:last-child {
    grid-column: 3;
  }

  .repo-row {
    grid-template-areas: "name desc stack link";
    align-items: start;
    padding: 24px 16px;
    transition: background-color .25s var(--ease);
  }

  .repo-row:hover,
  .repo-row:focus-within {
    background: var(--surface);
  }

  .repo-row__link {
    justify-self: end;
  }
}

/* --------------------------------------------------------------------------
   Closing line
   -------------------------------------------------------------------------- */
.projects__outro {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 28px;
  margin: 36px 0 0;
  color: var(--muted);
}

.projects__profile {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}


/* ===== 65-globe.css ===== */
/* ==========================================================================
   65-globe: WebGL globe for the global fuel management feature
   Markup (projects section): <div class="globe" data-3d="globe">
     <div class="scene-fallback globe__fallback" aria-hidden="true"></div>
     <p class="globe__caption">…</p></div>
   The canvas is added by /assets/js/3d/globe.js. The pure-CSS fallback is what
   static mode shows (reduced motion, no WebGL 2, Save-Data, low memory).
   Both draw the sphere at 76% of the square, centred, so the cross-fade lines up.
   ========================================================================== */

.globe {
  position: relative;
  width: 100%;
  max-width: 560px;
  margin-inline: auto;
  aspect-ratio: 1;
  touch-action: pan-y; /* horizontal drags turn the globe, vertical swipes still scroll the page */
  -webkit-tap-highlight-color: transparent;
}

.globe.is-ready {
  cursor: grab;
  -webkit-user-select: none;
  user-select: none;
}

.globe.is-ready.is-dragging {
  cursor: grabbing;
}

/* --- static fallback: dark sphere, drifting dot texture, violet rim light --- */

.globe__fallback {
  position: absolute;
  top: 12%;
  left: 12%;
  width: 76%;
  height: 76%;
  border-radius: 50%;
  background:
    radial-gradient(circle at 32% 28%, rgba(124, 92, 255, 0.16), transparent 58%),
    radial-gradient(circle at 36% 32%, #100e1a 0%, #07060c 48%, #000 78%);
  box-shadow:
    inset 0 0 0 1px rgba(124, 92, 255, 0.2),
    inset 14px 16px 36px -18px rgba(124, 92, 255, 0.55),
    inset -26px -34px 60px rgba(0, 0, 0, 0.9),
    0 0 36px 2px rgba(81, 43, 212, 0.42),
    0 0 110px 14px rgba(81, 43, 212, 0.16);
}

/* Dot texture: a fine grid that fades toward the limb and the night side. */
.globe__fallback::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: radial-gradient(circle, rgba(236, 235, 233, 0.62) 0 0.9px, transparent 1.5px);
  background-size: 7px 7px;
  -webkit-mask-image: radial-gradient(circle at 38% 34%, #000 0%, rgba(0, 0, 0, 0.75) 38%, rgba(0, 0, 0, 0.18) 62%, transparent 71%);
          mask-image: radial-gradient(circle at 38% 34%, #000 0%, rgba(0, 0, 0, 0.75) 38%, rgba(0, 0, 0, 0.18) 62%, transparent 71%);
  animation: globe-drift 80s linear infinite;
}

/* İstanbul, the hub of the network. */
.globe__fallback::after {
  content: "";
  position: absolute;
  top: 30%;
  left: 47%;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: var(--text, #ecebe9);
  box-shadow:
    0 0 0 5px rgba(124, 92, 255, 0.3),
    0 0 0 12px rgba(124, 92, 255, 0.1),
    0 0 26px 8px rgba(124, 92, 255, 0.5);
}

/* 420px is a whole number of 7px and 6px tiles, so the loop is seamless at both sizes. */
@keyframes globe-drift {
  to {
    background-position: 420px 0;
  }
}

.globe__caption {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 1;
  margin: 0;
  font-size: var(--step--1, 0.875rem);
  line-height: 1.4;
  color: var(--dim, #8a8886);
  text-align: center;
  pointer-events: none;
}

@media (max-width: 480px) {
  .globe__fallback::before {
    background-size: 6px 6px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .globe__fallback::before {
    animation: none;
  }
}


/* ===== 70-github.css ===== */
/* ==========================================================================
   70-github.css: live GitHub data (#github)
   Profile, stat figures, language bar, filterable repository list and the
   contribution graph. Scoped to .section--github and the gh-* blocks.
   Rows stay quiet: hover changes colour and background only, no tilt.
   ========================================================================== */

/* GitHub linguist colours. Data colours for dots and bar segments only; text
   beside them always stays in the text tokens. */
.section--github [data-lang] { --lang: #8b949e; }
.section--github [data-lang="C#"] { --lang: #178600; }
.section--github [data-lang="HTML"] { --lang: #e34c26; }
.section--github [data-lang="JavaScript"] { --lang: #f1e05a; }
.section--github [data-lang="Python"] { --lang: #3572a5; }
.section--github [data-lang="CSS"] { --lang: #563d7c; }

.gh-dot {
  display: inline-block;
  flex: none;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--lang, #8b949e);
}

/* Small block headings inside the section (h3) */
.gh-title {
  font-size: var(--step-0);
  font-weight: 650;
  font-stretch: var(--wdth-heading);
  line-height: 1.3;
  letter-spacing: -.005em;
  color: var(--text);
}

.gh-title__sub {
  margin-left: .35em;
  font-size: var(--step--1);
  font-weight: 400;
  color: var(--dim);
}


/* --------------------------------------------------------------------------
   Data status in the section head
   -------------------------------------------------------------------------- */

.section--github .gh-state {
  margin-top: 24px;
}

.gh-state .status[data-state="loading"]::before {
  animation: gh-pulse .9s ease-in-out infinite alternate;
}

@keyframes gh-pulse {
  from { opacity: .3; }
  to { opacity: 1; }
}


/* --------------------------------------------------------------------------
   Layout: profile column beside the repository list
   -------------------------------------------------------------------------- */

.gh {
  display: grid;
  gap: clamp(56px, 7vw, 72px);
}

.gh__side {
  display: grid;
  align-content: start;
  gap: 40px;
  min-width: 0;
}

.gh__main {
  min-width: 0;
}

@media (min-width: 1024px) {
  .gh {
    grid-template-columns: minmax(260px, 300px) minmax(0, 1fr);
    align-items: start;
    gap: clamp(64px, 7vw, 104px);
  }
}

/* Keep the profile column in view while the expanded list scrolls past,
   only where the whole column fits under the header. */
@media (min-width: 1024px) and (min-height: 860px) {
  .gh__side {
    position: sticky;
    top: calc(var(--nav-h) + 32px);
  }
}


/* --------------------------------------------------------------------------
   Profile
   -------------------------------------------------------------------------- */

.gh-profile {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 18px 18px;
}

.gh-profile__avatar {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: 50%;
  background: var(--surface-2);
  /* Hairline ring, a black gap, then a fainter outer ring */
  box-shadow: 0 0 0 1px var(--line-strong), 0 0 0 5px var(--bg), 0 0 0 6px var(--line);
  filter: grayscale(1) contrast(1.06);
}

.gh-profile__id {
  min-width: 0;
}

.gh-profile__name {
  font-size: var(--step-1);
  font-stretch: var(--wdth-heading);
  line-height: 1.15;
}

.gh-profile__handle {
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--muted);
}

.gh-profile__about,
.gh-profile__follow {
  grid-column: 1 / -1;
}

.gh-profile__bio {
  color: var(--text);
  line-height: 1.5;
}

.gh-profile__since {
  margin-top: 2px;
  font-size: var(--step--1);
  color: var(--dim);
}

.gh-profile__follow {
  justify-self: start;
}


/* --------------------------------------------------------------------------
   Stat figures: typographic, set between two hairlines, no boxes
   -------------------------------------------------------------------------- */

.gh-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 30px 20px;
  padding-block: 30px;
  border-block: 1px solid var(--line);
}

.gh-stat {
  display: flex;
  flex-direction: column-reverse;
  justify-content: flex-end;
  gap: 10px;
  min-width: 0;
}

.gh-stat__label {
  font-size: var(--step--1);
  line-height: 1.35;
  color: var(--muted);
}

.gh-stat__value {
  display: flex;
  align-items: center;
  gap: .16em;
  margin: 0;
  font-size: clamp(2.5rem, 2.1rem + 1.2vw, 3.25rem);
  font-weight: 700;
  font-stretch: 78%;
  line-height: 1;
  letter-spacing: -.03em;
  font-variant-numeric: lining-nums proportional-nums;
  white-space: nowrap;
}

.gh-stat__value .gh-dot {
  width: .26em;
  height: .26em;
}


/* --------------------------------------------------------------------------
   Language distribution: one stacked bar, 2px black gaps, legend below
   -------------------------------------------------------------------------- */

.gh-langs__data {
  margin-top: 16px;
}

.gh-langs__track {
  overflow: hidden;
  border-radius: 4px;
}

.gh-langs__bar {
  width: 100%;
  height: 12px;
}

.gh-seg {
  fill: var(--lang, #8b949e);
  stroke: var(--bg);
  stroke-width: 2px;
  vector-effect: non-scaling-stroke;
  transition: opacity .3s var(--ease);
}

.gh-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  margin-top: 16px;
  font-size: var(--step--1);
  line-height: 1.3;
}

.gh-legend__item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  transition: opacity .3s var(--ease);
}

.gh-legend__pct {
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}

/* A hovered segment or an active filter brings its language forward */
.gh-langs__data.has-focus .gh-seg:not(.is-focus),
.gh-langs__data.has-focus .gh-legend__item:not(.is-focus) {
  opacity: .32;
}

.gh-langs__note {
  max-width: 52ch;
  margin-top: 18px;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--dim);
}


/* --------------------------------------------------------------------------
   Toolbar and language filters
   -------------------------------------------------------------------------- */

.gh-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px 24px;
  margin-bottom: 14px;
}

/* Filters only work with JavaScript */
.gh-filters {
  display: none;
  flex-wrap: wrap;
  gap: 8px;
}

.js .gh-filters {
  display: flex;
}

.gh-filter {
  color: var(--muted);
  transition: color .2s var(--ease), border-color .2s var(--ease), background-color .2s var(--ease);
}

.gh-filter:hover {
  color: var(--text);
  border-color: var(--line-strong);
}

.gh-filter[aria-pressed="true"] {
  color: #fff;
  background: var(--violet-soft);
  border-color: rgba(124, 92, 255, .55);
}

.gh-filter .gh-dot {
  width: 8px;
  height: 8px;
}


/* --------------------------------------------------------------------------
   Repository list: rows in the manner of a code host, each row one link
   -------------------------------------------------------------------------- */

.gh-repos {
  margin: 0;
}

.gh-repo {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "name meta"
    "desc desc";
  align-items: baseline;
  gap: 6px 24px;
  margin-inline: -16px;
  padding: 18px 16px 19px;
  border-radius: var(--r-sm);
  transition: background-color .25s var(--ease);
}

/* Hairline between rows, aligned with the text column */
.gh-repo::before {
  content: "";
  position: absolute;
  top: 0;
  left: 16px;
  right: 16px;
  height: 1px;
  background: var(--line);
  transition: opacity .25s var(--ease);
}

.gh-repo:hover {
  background-color: var(--surface-2);
}

.gh-repo:hover::before,
.gh-repo:hover + .gh-repo::before {
  opacity: 0;
}

/* Before github.js takes over, show the first eight rows (no jump on hydrate) */
.js .gh-repos:not(.is-managed) > .gh-repo:nth-child(n + 9) {
  display: none;
}

.gh-repo__name {
  grid-area: name;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: .9375rem;
  font-weight: 500;
  line-height: 1.4;
}

.gh-repo__icon {
  color: var(--dim);
}

.gh-repo__link {
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--text);
  text-decoration-line: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: color .2s var(--ease), text-decoration-color .2s var(--ease);
}

/* The link covers the whole row */
.gh-repo__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.gh-repo__link:focus-visible {
  outline: none;
}

.gh-repo__link:focus-visible::after {
  outline: 2px solid var(--violet);
  outline-offset: -2px;
}

.gh-repo__ext {
  width: .95em;
  height: .95em;
  color: var(--dim);
  transition: color .2s var(--ease);
}

.gh-repo:hover .gh-repo__link,
.gh-repo:focus-within .gh-repo__link {
  color: #fff;
  text-decoration-color: var(--violet);
}

.gh-repo:hover .gh-repo__ext,
.gh-repo:focus-within .gh-repo__ext {
  color: var(--violet);
}

.gh-repo__desc {
  grid-area: desc;
  max-width: 68ch;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--muted);
}

.gh-repo__meta {
  grid-area: meta;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 6px 18px;
  font-size: .8125rem;
  line-height: 1.4;
  white-space: nowrap;
  color: var(--dim);
}

.gh-repo__lang,
.gh-repo__stars {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.gh-repo__lang {
  color: var(--muted);
}

.gh-repo__lang .gh-dot {
  width: 9px;
  height: 9px;
}

.gh-repo__stars .icon {
  width: 1.05em;
  height: 1.05em;
}

.gh-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 28px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

/* "Show more" needs JavaScript; hidden is handled by the base [hidden] rule */
.gh-more {
  display: none;
}

.js .gh-more {
  display: inline-flex;
}

.gh-all {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  font-size: var(--step--1);
}

.gh-all .icon {
  color: var(--dim);
  transition: color .2s var(--ease);
}

.gh-all:hover .icon {
  color: var(--violet);
}


/* --------------------------------------------------------------------------
   Contribution graph (recoloured to the site's violet ramp by github.js)
   -------------------------------------------------------------------------- */

.gh-graph {
  margin-top: clamp(64px, 8vw, 96px);
}

.gh-graph__caption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 16px;
  margin-bottom: 28px;
  padding-top: 28px;
  border-top: 1px solid var(--line);
}

.gh-graph__desc {
  font-size: var(--step--1);
  color: var(--muted);
}

.gh-graph__legend {
  display: none;
  align-items: center;
  gap: 4px;
  margin-left: auto;
  font-size: .75rem;
  line-height: 1;
  color: var(--dim);
}

.gh-graph.is-recoloured .gh-graph__legend {
  display: inline-flex;
}

.gh-graph__legend span:first-child {
  margin-right: 4px;
}

.gh-graph__legend span:last-child {
  margin-left: 4px;
}

/* Same steps as the recoloured graph: empty, then four violet levels */
.gh-graph__legend i {
  width: 11px;
  height: 11px;
  border-radius: 3px;
  background: #161616;
}

.gh-graph__legend i:nth-of-type(2) { background: #3f2f99; }
.gh-graph__legend i:nth-of-type(3) { background: #5a43cf; }
.gh-graph__legend i:nth-of-type(4) { background: #7c5cff; }
.gh-graph__legend i:nth-of-type(5) { background: #b3a3ff; }

/* Space is reserved before the image arrives: github.js crops the snk canvas to
   the snake lanes and the day grid, or to the grid alone under reduced motion.
   Without JavaScript the untouched original is shown. */
.gh-graph__frame {
  position: relative;
  aspect-ratio: 864 / 144;
}

.gh-graph.is-still .gh-graph__frame {
  aspect-ratio: 848 / 112;
}

html:not(.js) .gh-graph__frame {
  aspect-ratio: 880 / 192;
}

.gh-graph__img {
  width: 100%;
  height: auto;
}

.js .gh-graph__img {
  opacity: 0;
  transition: opacity .9s var(--ease);
}

.js .gh-graph.is-ready .gh-graph__img {
  opacity: 1;
}

/* Without JavaScript the original graph animates forever: skip it under reduced motion */
@media (prefers-reduced-motion: reduce) {
  html:not(.js) .gh-graph {
    display: none;
  }
}


/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1023px) {
  .gh__side {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 40px 48px;
  }

  .gh-langs {
    grid-column: 1 / -1;
  }

  .gh-stats {
    align-self: start;
  }
}

@media (max-width: 767px) {
  .gh__side {
    grid-template-columns: minmax(0, 1fr);
  }

  .gh-repo {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "name"
      "desc"
      "meta";
    gap: 6px;
  }

  .gh-repo__meta {
    justify-content: flex-start;
    margin-top: 4px;
  }

  .gh-graph__legend {
    margin-left: 0;
  }
}

@media (max-width: 479px) {
  .gh-profile__avatar {
    width: 64px;
    height: 64px;
  }

  .gh-stats {
    gap: 26px 16px;
  }

  .gh-stat__value {
    font-size: 2.375rem;
  }

  .gh-actions {
    flex-direction: column;
    align-items: flex-start;
  }

  .gh-all {
    margin-left: 0;
  }
}

@media (forced-colors: active) {
  .gh-dot,
  .gh-graph__legend i {
    forced-color-adjust: none;
  }

  .gh-repo__link:focus-visible::after {
    outline-color: Highlight;
  }
}


/* ===== 80-contact.css ===== */
/* ==========================================================================
   80-contact.css: FAQ (#faq) and contact (#contact)
   Scope: .section--faq, .faq__*, .faq-item*, .section--contact, .contact*
   Shared classes (.section-head, .section-title, .btn, .kbd, .link, .icon)
   are only extended through scoped selectors here, never redefined.
   ========================================================================== */


/* --------------------------------------------------------------------------
   FAQ: quiet two-column reading layout, hairline-separated disclosures
   -------------------------------------------------------------------------- */

.faq__more {
  margin-top: 28px;
  max-width: 44ch;
  color: var(--muted);
}

.faq__list {
  --delay: 120ms;
  border-top: 1px solid var(--line);
}

.faq-item {
  border-bottom: 1px solid var(--line);
  interpolate-size: allow-keywords; /* inherited by ::details-content so it can animate to auto */
}

.faq-item > summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  padding: 26px 0;
  list-style: none;
  border-radius: var(--r-sm);
  color: var(--text);
  font-size: clamp(1.1875rem, 1.05rem + .5vw, var(--step-1));
  font-weight: 600;
  font-stretch: var(--wdth-heading);
  line-height: 1.3;
  letter-spacing: -.012em;
}

.faq-item > summary::-webkit-details-marker {
  display: none;
}

.faq-item > summary:focus-visible {
  outline-offset: 4px;
}

.faq-item__q {
  min-width: 0;
  text-wrap: pretty;
}

.faq-item .faq-item__icon {
  width: 22px;
  height: 22px;
  margin-top: .2em;
  color: var(--dim);
  transition: rotate .45s var(--ease), color .2s ease;
}

.faq-item[open] > summary .faq-item__icon {
  rotate: 180deg;
  color: var(--violet);
}

@media (hover: hover) {
  .faq-item:not([open]) > summary:hover .faq-item__icon {
    color: var(--text);
  }
}

.faq-item__answer {
  max-width: var(--measure);
  padding: 0 clamp(0px, 4vw, 48px) 30px 0;
  color: var(--muted);
}

.faq-item__answer p {
  line-height: 1.65;
}

/* Smooth height where ::details-content exists. Without interpolate-size the
   height simply snaps; without ::details-content the native toggle remains. */
@supports selector(::details-content) {
  .faq-item::details-content {
    block-size: 0;
    overflow-y: clip;
    opacity: 0;
    transition:
      block-size .5s var(--ease),
      opacity .35s ease,
      content-visibility .5s allow-discrete;
  }

  .faq-item[open]::details-content {
    block-size: auto;
    opacity: 1;
  }

  /* the global reduced-motion reset does not reach this pseudo-element */
  @media (prefers-reduced-motion: reduce) {
    .faq-item::details-content {
      transition: none;
    }
  }
}

@media (min-width: 1025px) {
  .section--faq .container {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    column-gap: clamp(56px, 7vw, 120px);
    align-items: start;
  }

  .section--faq .section-head {
    position: sticky;
    top: calc(var(--nav-h) + 40px);
    margin-bottom: 0;
  }

  /* first rule of the list continues the path's hairline (half its line box down) */
  .faq__list {
    margin-top: calc(var(--step--1) * .75);
  }
}

@media (max-width: 480px) {
  .faq-item > summary {
    gap: 16px;
    padding-block: 22px;
  }

  .faq-item__answer {
    padding-right: 0;
  }
}


/* --------------------------------------------------------------------------
   Contact: the closing moment
   -------------------------------------------------------------------------- */

.section--contact {
  isolation: isolate;
}

/* Faint violet floor behind the lower half. The grid itself comes from
   .perspective-grid (05-fx.css); this wrapper only places, clips and fades it. */
.contact__floor {
  position: absolute;
  inset: auto 0 0;
  z-index: -1;
  display: grid;
  height: min(72%, 680px);
  overflow: hidden;
  pointer-events: none;
  opacity: .55;
  -webkit-mask-image:
    linear-gradient(to bottom, #000 82%, transparent),
    radial-gradient(ellipse 72% 100% at 50% 100%, #000 22%, transparent 74%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to bottom, #000 82%, transparent),
    radial-gradient(ellipse 72% 100% at 50% 100%, #000 22%, transparent 74%);
  mask-composite: intersect;
}

/* The closing headline: same chrome and width axis as every title, set huge */
.section--contact .section-title.contact__title {
  max-width: none;
  font-size: clamp(2.75rem, 1rem + 7.4vw, 7.5rem);
  font-variation-settings: "opsz" 96; /* display cut at every size, so phones keep two lines */
  font-weight: 720;
  line-height: .94;
  letter-spacing: -.025em;
}

.contact {
  --delay: 120ms;
  display: grid;
  gap: 56px;
}

@media (min-width: 1025px) {
  .contact {
    grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
    column-gap: clamp(56px, 8vw, 140px);
    align-items: start;
  }
}

.contact__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.contact .contact__mail,
.contact .contact__copy {
  --btn-h: 64px;
}

.contact .contact__mail {
  gap: 12px;
  max-width: 100%;
  padding-inline: 26px 30px;
  font-size: clamp(1rem, .92rem + .4vw, 1.1875rem);
}

.contact__mail-address {
  min-width: 0;
  white-space: normal;
  overflow-wrap: anywhere;
}

.contact .contact__copy {
  gap: 10px;
  padding-inline: 22px 24px;
}

/* Copy confirmation: main.js sets .is-copied for 1.8s; the icon turns into a check */
.contact__copy-icons {
  display: inline-grid;
}

.contact__copy-icons > .icon {
  grid-area: 1 / 1;
  transition: opacity .2s ease, scale .35s var(--ease);
}

.contact__copy .contact__copy-done {
  opacity: 0;
  scale: .5;
  color: var(--violet);
}

.contact .contact__copy.is-copied {
  border-color: rgba(124, 92, 255, .6);
}

.contact__copy.is-copied .contact__copy-idle {
  opacity: 0;
  scale: .5;
}

.contact__copy.is-copied .contact__copy-done {
  opacity: 1;
  scale: 1;
}

.contact__hint {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 20px;
  margin-top: 40px;
}

.contact .contact__cmdk {
  gap: 12px;
}

.contact__hint p {
  flex: 1 1 260px;
  max-width: 46ch;
  color: var(--dim);
  font-size: var(--step--1);
  line-height: 1.6;
}

.contact__code {
  color: var(--text);
}

/* <address>: social channels as directory-style rows, then the city */
.contact__channels {
  border-top: 1px solid var(--line);
}

.contact__channels > li {
  border-bottom: 1px solid var(--line);
}

.contact__channel {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  column-gap: 14px;
  padding: 18px 2px;
  border-radius: var(--r-sm);
  color: var(--text);
}

.contact__channel:focus-visible {
  outline-offset: 2px;
}

.contact__channel .contact__channel-icon {
  width: 22px;
  height: 22px;
  color: var(--muted);
  transition: color .2s ease;
}

.contact__channel-name {
  font-weight: 500;
}

.contact__channel-handle {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--dim);
  transition: color .2s ease;
}

.contact__channel .contact__channel-ext {
  width: 16px;
  height: 16px;
  color: var(--dim);
  transition: color .2s ease, translate .3s var(--ease);
}

@media (hover: hover) {
  .contact__channel:hover .contact__channel-icon,
  .contact__channel:hover .contact__channel-handle {
    color: var(--text);
  }

  .contact__channel:hover .contact__channel-ext {
    color: var(--violet);
    translate: 2px -2px;
  }
}

.contact__location {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
  color: var(--muted);
  font-size: var(--step--1);
}

.contact__location .icon {
  color: var(--dim);
}

/* Touch devices have no Ctrl K: the button still opens the palette */
@media (pointer: coarse) {
  .contact__cmdk .kbd {
    display: none;
  }
}

@media (max-width: 480px) {
  .contact .contact__mail,
  .contact .contact__copy {
    flex: 1 1 100%;
  }

  .contact__floor {
    height: 46%;
  }
}

@media (forced-colors: active) {
  .contact__floor {
    display: none;
  }
}


/* ===== hero v2: tech sphere in the hero, small avatar, refined name ===== */
.hero__id {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 clamp(16px, 2.2vw, 26px);
}
.hero__avatar {
  flex: none;
  display: block;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  box-shadow: 0 0 0 4px rgba(124, 92, 255, .12), 0 12px 32px -12px rgba(81, 43, 212, .9);
  transition: box-shadow .4s var(--ease);
}
.hero__avatar img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  scale: 1.75;
  translate: 0 30%; /* centre the mask's face, the slogan sits below */
}
.hero__avatar:hover { box-shadow: 0 0 0 4px rgba(124, 92, 255, .3), 0 12px 32px -10px rgba(81, 43, 212, 1); }
.hero__id .hero__prompt { margin: 0; }
.hero__motto {
  margin: 3px 0 0;
  font-family: var(--font-mono);
  font-size: 11px;
  font-style: italic;
  letter-spacing: .04em;
  color: var(--dim);
}

/* The name: one confident line where it fits, brushed-metal light that drifts slowly. */
.hero .hero__title {
  font-size: clamp(2.9rem, 6.4vw, 5.5rem);
  font-weight: 680;
  font-stretch: 92%;
  line-height: 1;
  letter-spacing: -.04em;
}
.hero .hero__name {
  display: inline-block;
  white-space: nowrap;
  padding-bottom: .1em; /* room for the Ş cedilla inside the clipped background */
  background: linear-gradient(100deg, #74747c 0%, #f4f4f6 16%, #bcbcc3 30%, #ffffff 44%, #8d8d95 58%, #e7e7eb 74%, #6e6e76 100%);
  background-size: 240% 100%;
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  filter: drop-shadow(0 10px 34px rgba(124, 92, 255, .22));
  animation: hero-name-shine 11s ease-in-out infinite alternate;
}
@keyframes hero-name-shine {
  from { background-position: 100% 0; }
  to { background-position: 0 0; }
}

/* The sphere replaces the particle mask on the right. */
.hero__visual {
  width: min(86vw, 420px);
  margin: 0 auto 4px;
}
.hero__visual::before { opacity: .55; }
.hero__visual .techsphere { max-width: none; }
@media (min-width: 768px) {
  .hero__visual { width: 100%; margin: 0; }
}
@media (min-width: 1024px) {
  .hero__stage { margin-top: 0; align-items: center; }
  .hero__visual { width: min(var(--hero-mask), 520px); }
  .hero__term {
    width: min(100%, calc(var(--hero-mask) * .9 + var(--hero-gap) * .6));
    margin: 14px 0 0; /* clear the sphere's "drag to rotate" hint */
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero .hero__name { animation: none; background-position: 30% 0; }
}

/* Skills: the stack takes the full width now that the sphere lives in the hero. */
.skills__grid { grid-template-columns: minmax(0, 1fr); }


/* ===== hero v3: copy and sphere share the first screen; the terminal is a console strip below ===== */
.hero__grid { grid-template-areas: "visual" "copy"; }
.hero__role-line { display: block; }
.hero__console { position: relative; z-index: 3; }
.hero__console .hero__term {
  width: min(100%, 880px);
  margin: clamp(48px, 7vw, 88px) auto 0;
}
@media (min-width: 768px) {
  .hero__grid { grid-template-areas: "copy visual"; }
}
@media (min-width: 1024px) {
  .hero { justify-content: flex-start; }
  .hero__grid {
    grid-template-areas: "copy stage";
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    min-height: calc(100vh - var(--nav-h) - 64px);
    min-height: calc(100svh - var(--nav-h) - 64px);
  }
  .hero__stage { justify-content: center; }
  .hero__visual {
    width: min(100%, 540px, calc(100vh - var(--nav-h) - 150px));
    width: min(100%, 540px, calc(100svh - var(--nav-h) - 150px));
  }
  .hero__console .hero__term {
    width: min(100%, 920px);
    margin: clamp(16px, 3vw, 40px) auto 0;
    perspective: 1600px;
    perspective-origin: 50% 0;
  }
  .hero__console .hero__term-3d { transform: rotateX(7deg); transform-origin: 50% 0; }
  .hero__console .hero__term:hover .hero__term-3d { transform: rotateX(3deg); }
  .hero__console .hero__term:focus-within .hero__term-3d { transform: none; }
}
