/* ==========================================================================
   hesam.ir — one stylesheet, no build step.

   Rules that hold everywhere in this file:

   1. COLOUR LIVES IN THE THREE TOKEN BLOCKS AND NOWHERE ELSE. `:root` is the
      light theme; the two blocks after it restate the same names for dark,
      once for a device that asks for dark and once for an explicit
      [data-theme="dark"], so an explicit choice beats the device either way.
      A rule that needs a tint writes rgba(var(--mint-rgb), .12), never a
      second hex.
   2. LOGICAL PROPERTIES ONLY. The site runs RTL in Persian and LTR in English
      and German from the same rules, so it is padding-inline-start, never
      padding-left. The two exceptions — the tooltip and the nav indicator —
      are placed by JavaScript in viewport pixels and say so where they are.
   3. The palette is four pastels, each with one meaning:
        mint  — the work: projects, navigation, anything actionable
        sky   — the career: the timeline, the résumé, the facts
        peach — the person: availability, «این روزها», contact
        lilac — writing, and nothing else
   ========================================================================== */

/* ── fonts: all self-hosted. Nothing this page draws with comes off a CDN,
   because in Iran fonts.googleapis.com is slow at best. ─────────────────── */
@font-face {
  font-family: 'Vazirmatn';
  src: url("../fonts/Vazirmatn-Variable.f6d31671339d.woff2") format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: 'Fraunces';
  src: url("../fonts/Fraunces-Variable-latin.069cb90e11a3.woff2") format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+2000-206F, U+2190-21FF, U+2212;
}
@font-face {
  font-family: 'Plex Mono';
  src: url("../fonts/IBMPlexMono-400-latin.79936b18df9f.woff2") format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Plex Mono';
  src: url("../fonts/IBMPlexMono-500-latin.b1c8a895f5fd.woff2") format('woff2');
  font-weight: 500;
  font-display: swap;
}

/* ═══════════════════════════════════════════════════════════════════════════
   1 · TOKENS

   Each hue is a five-step ramp — tint, soft, mid, strong, deep — plus -rgb
   for alpha tints. What the steps are FOR is the part to keep:

     --x-tint    a ground you can barely see: a band, a chip, a hover
     --x-soft    a fill: a pill, the active nav item, an icon tile
     --x         the pastel itself: a button, a dot, a blob, a hover border
     --x-strong  text on --surface or --x-tint          (≥ 4.5:1)
     --x-deep    text on anything, including --x-soft   (≥ 6:1)

   So only -strong and -deep may colour a letterform, and on a -soft fill
   only -deep. Text on the pastel mid itself is --on-accent (ink), which is
   why a primary button is pastel with dark lettering rather than a saturated
   fill with white — that is what keeps the page pastel and still AA.

   In dark the ramp inverts: -deep is the LIGHTEST step. A rule that asked for
   -deep because it was drawing text keeps getting the readable step without
   having to know which theme it is in.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  /* light is a cool, quiet paper grey: the pastels are accents on it, not
     the ground itself */
  --bg:        #f4f5f7;
  --bg-inset:  #eceef2;
  --surface:   #ffffff;
  --surface-2: #f9fafb;
  --glass:     rgba(255, 255, 255, .78);
  --ambient:   .2;    /* strength of the site-wide drifting colour field */
  --net:       .5;    /* strength of the network + code glyphs drawn over it */
  --build:     .55;   /* strength of the building the scroll puts up over both */
  --aurora:    .45;   /* strength of the hero's colour fields */
  --photo:     .2;    /* strength of a page's backdrop photograph */
  --photo-stand: .13; /* the standing one, which the whole page scrolls over */
  --photo-fx:  none;  /* and how its light is bent to sit on this ground */

  --wash-mint:  #eef2f1;
  --wash-sky:   #edf1f5;
  --wash-peach: #f4f1ef;
  --wash-lilac: #f0eff5;

  --ink:    #1b2030;
  --ink-2:  #4a5263;
  --mute:   #636b7c;   /* 4.9:1 on --bg, 5.3:1 on --surface */
  --line:   #e2e5ea;
  --line-2: #eceef2;

  --mint-tint:   #effaf5;
  --mint-soft:   #dcf3e8;
  --mint:        #a6dfc6;
  --mint-strong: #2a7a5e;
  --mint-deep:   #1d5e48;
  --mint-rgb:    120, 205, 168;

  --sky-tint:   #f0f7fe;
  --sky-soft:   #deedfc;
  --sky:        #a9d0f5;
  --sky-strong: #2d69a0;
  --sky-deep:   #225282;
  --sky-rgb:    130, 182, 236;

  --peach-tint:   #fff5ef;
  --peach-soft:   #ffe5d6;
  --peach:        #f8c4a4;
  --peach-strong: #a35a2e;
  --peach-deep:   #834521;
  --peach-rgb:    244, 170, 128;

  --lilac-tint:   #f6f3fe;
  --lilac-soft:   #e9e3fc;
  --lilac:        #c4b8f3;
  --lilac-strong: #6450b0;
  --lilac-deep:   #4e3e92;
  --lilac-rgb:    170, 150, 238;

  --on-accent: #1f2433;
  --shine:     rgba(255, 255, 255, .6);
  --tip-bg:    #262b3a;
  --tip-ink:   #f5f6fa;
  --scrim:     rgba(31, 36, 51, .32);

  /* The QR plate stays light in BOTH themes, on purpose: many phone cameras
     cannot read a light-on-dark code, and the card exists to be scanned.
     Defined here once and deliberately not restated in the dark blocks. */
  --qr-plate: #ffffff;
  --qr-ink:   #1f2433;

  /* elevation: cool-neutral and very soft, so pastel cards float rather
     than sit in a grey puddle */
  --shadow-1: 0 1px 2px rgba(31, 36, 51, .04), 0 4px 14px rgba(31, 36, 51, .045);
  --shadow-2: 0 2px 6px rgba(31, 36, 51, .05), 0 18px 44px -8px rgba(31, 36, 51, .12);
  --shadow-3: 0 30px 80px -20px rgba(31, 36, 51, .22);
  --glow: 0 14px 34px -14px rgba(var(--accent-rgb), .95);
  --ring: 0 0 0 3px rgba(var(--accent-rgb), .45), 0 0 0 1px rgba(var(--accent-rgb), .95);

  --dots: radial-gradient(rgba(31, 36, 51, .075) 1px, transparent 1.2px);

  /* type */
  --sans: 'Vazirmatn', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --display: 'Fraunces', 'Vazirmatn', Georgia, serif;
  --mono: 'Plex Mono', ui-monospace, SFMono-Regular, Consolas, monospace;

  --step--2: clamp(.72rem, .7rem + .08vw, .76rem);
  --step--1: clamp(.82rem, .8rem + .1vw, .88rem);
  --step-0:  clamp(.96rem, .93rem + .15vw, 1.03rem);
  --step-1:  clamp(1.1rem, 1.04rem + .3vw, 1.26rem);
  --step-2:  clamp(1.34rem, 1.2rem + .65vw, 1.7rem);
  --step-3:  clamp(1.75rem, 1.45rem + 1.4vw, 2.55rem);
  --step-4:  clamp(2.3rem, 1.7rem + 2.9vw, 4.1rem);

  /* geometry and motion */
  --r-xs: 8px;
  --r-sm: 12px;
  --r:    18px;
  --r-lg: 24px;
  --r-xl: 34px;
  --gap: clamp(1rem, .6rem + 1.6vw, 1.6rem);
  --pad: clamp(1.15rem, .85rem + 1.2vw, 1.8rem);
  --sec: clamp(3.5rem, 2.4rem + 4.5vw, 6.5rem);
  --shell: 1180px;
  --header-h: 80px;
  --ease: cubic-bezier(.22, 1, .36, 1);
  --spring: cubic-bezier(.34, 1.56, .64, 1);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:        #12141b;
    --bg-inset:  #171a22;
    --surface:   #1a1d26;
    --surface-2: #1f232d;
    --glass:     rgba(26, 29, 38, .72);
    --ambient:   .2;
    --net:       .75;
    --build:     .6;
    --aurora:    1;
    --photo:     .2;
    --photo-stand: .2;
    --photo-fx:  brightness(.72) contrast(1.2);

    --wash-mint:  #141c1b;
    --wash-sky:   #141a23;
    --wash-peach: #1d1a1a;
    --wash-lilac: #191826;

    --ink:    #eceef4;
    --ink-2:  #b6bcc9;
    --mute:   #8c93a2;
    --line:   #2a2e39;
    --line-2: #22252f;

    --mint-tint:   rgba(143, 217, 186, .07);
    --mint-soft:   rgba(143, 217, 186, .15);
    --mint:        #8fd9ba;
    --mint-strong: #aee6cf;
    --mint-deep:   #c9f1e0;
    --mint-rgb:    143, 217, 186;

    --sky-tint:   rgba(153, 198, 242, .07);
    --sky-soft:   rgba(153, 198, 242, .15);
    --sky:        #99c6f2;
    --sky-strong: #b6d7f7;
    --sky-deep:   #cfe5fb;
    --sky-rgb:    153, 198, 242;

    --peach-tint:   rgba(244, 182, 144, .07);
    --peach-soft:   rgba(244, 182, 144, .15);
    --peach:        #f4b690;
    --peach-strong: #f8caad;
    --peach-deep:   #fbdcc8;
    --peach-rgb:    244, 182, 144;

    --lilac-tint:   rgba(179, 164, 240, .08);
    --lilac-soft:   rgba(179, 164, 240, .16);
    --lilac:        #b3a4f0;
    --lilac-strong: #c8bdf5;
    --lilac-deep:   #dcd4fa;
    --lilac-rgb:    179, 164, 240;

    --on-accent: #141821;
    --shine:     rgba(255, 255, 255, .32);
    --tip-bg:    #eceef4;
    --tip-ink:   #141821;
    --scrim:     rgba(5, 6, 10, .6);

    --shadow-1: 0 1px 2px rgba(0, 0, 0, .3), 0 4px 14px rgba(0, 0, 0, .22);
    --shadow-2: 0 2px 6px rgba(0, 0, 0, .34), 0 18px 44px -8px rgba(0, 0, 0, .5);
    --shadow-3: 0 30px 80px -20px rgba(0, 0, 0, .7);
    --glow: 0 14px 34px -16px rgba(var(--accent-rgb), .6);
    --dots: radial-gradient(rgba(236, 238, 244, .055) 1px, transparent 1.2px);
  }
}

:root[data-theme="dark"] {
  --bg:        #12141b;
  --bg-inset:  #171a22;
  --surface:   #1a1d26;
  --surface-2: #1f232d;
  --glass:     rgba(26, 29, 38, .72);
  --ambient:   .2;
  --net:       .75;
  --build:     .6;
  --aurora:    1;
  --photo:     .2;
  --photo-stand: .2;
  --photo-fx:  brightness(.72) contrast(1.2);

  --wash-mint:  #141c1b;
  --wash-sky:   #141a23;
  --wash-peach: #1d1a1a;
  --wash-lilac: #191826;

  --ink:    #eceef4;
  --ink-2:  #b6bcc9;
  --mute:   #8c93a2;
  --line:   #2a2e39;
  --line-2: #22252f;

  --mint-tint:   rgba(143, 217, 186, .07);
  --mint-soft:   rgba(143, 217, 186, .15);
  --mint:        #8fd9ba;
  --mint-strong: #aee6cf;
  --mint-deep:   #c9f1e0;
  --mint-rgb:    143, 217, 186;

  --sky-tint:   rgba(153, 198, 242, .07);
  --sky-soft:   rgba(153, 198, 242, .15);
  --sky:        #99c6f2;
  --sky-strong: #b6d7f7;
  --sky-deep:   #cfe5fb;
  --sky-rgb:    153, 198, 242;

  --peach-tint:   rgba(244, 182, 144, .07);
  --peach-soft:   rgba(244, 182, 144, .15);
  --peach:        #f4b690;
  --peach-strong: #f8caad;
  --peach-deep:   #fbdcc8;
  --peach-rgb:    244, 182, 144;

  --lilac-tint:   rgba(179, 164, 240, .08);
  --lilac-soft:   rgba(179, 164, 240, .16);
  --lilac:        #b3a4f0;
  --lilac-strong: #c8bdf5;
  --lilac-deep:   #dcd4fa;
  --lilac-rgb:    179, 164, 240;

  --on-accent: #141821;
  --shine:     rgba(255, 255, 255, .32);
  --tip-bg:    #eceef4;
  --tip-ink:   #141821;
  --scrim:     rgba(5, 6, 10, .6);

  --shadow-1: 0 1px 2px rgba(0, 0, 0, .3), 0 4px 14px rgba(0, 0, 0, .22);
  --shadow-2: 0 2px 6px rgba(0, 0, 0, .34), 0 18px 44px -8px rgba(0, 0, 0, .5);
  --shadow-3: 0 30px 80px -20px rgba(0, 0, 0, .7);
  --glow: 0 14px 34px -16px rgba(var(--accent-rgb), .6);
  --dots: radial-gradient(rgba(236, 238, 244, .055) 1px, transparent 1.2px);
}

/* ── the accent indirection ────────────────────────────────────────────────
   Mint is the default everywhere. An element carrying data-accent re-points
   the whole ramp for itself and everything inside it, so re-colouring a
   section is one attribute in the template and no new CSS at all.

   `.rhythm` is the second use of the same mechanism: its children take turns
   through all four hues. That is for rows of near-identical boxes — covers,
   skill groups, fact tiles, contact channels — where the colour carries no
   meaning and what it buys is that four boxes read as four boxes.
   ─────────────────────────────────────────────────────────────────────── */
:root, [data-accent="mint"], .rhythm > :nth-child(4n+1) {
  --accent:        var(--mint);
  --accent-strong: var(--mint-strong);
  --accent-deep:   var(--mint-deep);
  --accent-soft:   var(--mint-soft);
  --accent-tint:   var(--mint-tint);
  --accent-wash:   var(--wash-mint);
  --accent-rgb:    var(--mint-rgb);
}
[data-accent="sky"], .rhythm > :nth-child(4n+2) {
  --accent:        var(--sky);
  --accent-strong: var(--sky-strong);
  --accent-deep:   var(--sky-deep);
  --accent-soft:   var(--sky-soft);
  --accent-tint:   var(--sky-tint);
  --accent-wash:   var(--wash-sky);
  --accent-rgb:    var(--sky-rgb);
}
[data-accent="peach"], .rhythm > :nth-child(4n+3) {
  --accent:        var(--peach);
  --accent-strong: var(--peach-strong);
  --accent-deep:   var(--peach-deep);
  --accent-soft:   var(--peach-soft);
  --accent-tint:   var(--peach-tint);
  --accent-wash:   var(--wash-peach);
  --accent-rgb:    var(--peach-rgb);
}
[data-accent="lilac"], .rhythm > :nth-child(4n+4) {
  --accent:        var(--lilac);
  --accent-strong: var(--lilac-strong);
  --accent-deep:   var(--lilac-deep);
  --accent-soft:   var(--lilac-soft);
  --accent-tint:   var(--lilac-tint);
  --accent-wash:   var(--wash-lilac);
  --accent-rgb:    var(--lilac-rgb);
}

/* ══════════════════════════════════════════════════════════════════════════
   2 · BASE
   ══════════════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }

/* `hidden` must win over any component's own display, or a card the filter
   hides, a closed popover and the pre-JS back-to-top button all stay visible. */
[hidden] { display: none !important; }

/* clip, not hidden: the hero's aurora deliberately bleeds past the viewport
   on both sides, and `overflow-x: hidden` on <body> alone did not stop the
   document from growing to fit it — which showed up as the whole page
   shifted sideways in RTL. `hidden` first is the fallback for browsers
   without `clip` (Safari before 16); on <html> it propagates to the viewport,
   so it does not break the sticky header the way it would on <body>. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: hidden; overflow-x: clip; scroll-padding-top: calc(var(--header-h) + 12px); }
html.is-locked { overflow: hidden; }

body {
  margin: 0;
  background-color: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--step-0);
  line-height: 1.9;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* No overflow-x here. With `clip` on <html>, a `hidden` on <body> stops
     propagating to the viewport and turns <body> into its own scroll
     container — and the sticky header then sticks to nothing. */
  scrollbar-color: rgba(var(--mint-rgb), .7) transparent;
}
body[dir="ltr"] { line-height: 1.68; }

/* The AMBIENT field: the whole site sits on four very faint pastel lights —
   one per hue — that drift on long, unequal cycles so the pattern never
   visibly repeats, plus a fine grain that keeps the gradients from banding.
   It is `position: fixed` and clipped to the viewport by its own
   `overflow: hidden`, so it can never become sideways overflow in RTL. The
   drift is `translate`/`scale` on each light; scrolling turns the whole field
   through `rotate` on its parent (scroll-driven, no JS), so the two never
   overwrite each other. Opaque surfaces — cards, bands — simply cover it.

   Under the lights sits a faint BLUEPRINT grid — minor and major lines, the
   paper a construction schedule is drawn on. Over them, app.js draws the
   NETWORK on a canvas: activity boxes and milestone diamonds linked
   finish-to-start when near, progress travelling along those links, Gantt
   bars slipping behind their own baselines, and a planner's vocabulary
   (WBS, CPM, float, EOT) rising and fading — a project schedule, quietly
   running. The mask keeps the reading column calmer than the edges. */
/* Its height is the LARGE viewport (lvh) and it hangs from the bottom
   edge: when a phone's address bar slides away the viewport grows, and a
   layer sized to it would resize and jump at the start of every scroll.
   lvh never changes, so the field neither resizes nor moves on screen. */
.ambient {
  position: fixed; inset: auto 0 0; height: 100vh; height: 100lvh;
  z-index: -1; pointer-events: none;
  overflow: hidden; contain: strict;
}
.ambient-field { position: absolute; inset: -30%; }
.ambient-field i {
  position: absolute; border-radius: 50%; opacity: var(--ambient);
  will-change: translate, scale;
}
.ambient-field i:nth-child(1) { width: 52vmax; height: 52vmax; top: 18%; inset-inline-start: 16%; background: radial-gradient(closest-side, rgb(var(--mint-rgb)), transparent); }
.ambient-field i:nth-child(2) { width: 46vmax; height: 46vmax; top: 22%; inset-inline-end: 14%;  background: radial-gradient(closest-side, rgb(var(--sky-rgb)), transparent); }
.ambient-field i:nth-child(3) { width: 50vmax; height: 50vmax; bottom: 16%; inset-inline-end: 22%; background: radial-gradient(closest-side, rgb(var(--lilac-rgb)), transparent); }
.ambient-field i:nth-child(4) { width: 40vmax; height: 40vmax; bottom: 20%; inset-inline-start: 20%; background: radial-gradient(closest-side, rgb(var(--peach-rgb)), transparent); }
.ambient-net {
  position: absolute; inset: 0; width: 100%; height: 100%; direction: ltr; opacity: var(--net);
  -webkit-mask-image: radial-gradient(ellipse 46% 60% at 50% 50%, rgba(0, 0, 0, .4), #000 100%);
          mask-image: radial-gradient(ellipse 46% 60% at 50% 50%, rgba(0, 0, 0, .4), #000 100%);
}
/* The BUILDING (app.js, initBuild) is the top layer: the scroll is the
   project's progress, so a page opens on a surveyed plot and closes on a
   handed-over building at the inline end. It is drawn full-strength and
   dimmed here, and dimmer again on a phone, where the reading column is
   the whole width of the screen. */
.ambient-build { position: absolute; inset: 0; width: 100%; height: 100%; direction: ltr; opacity: var(--build); }
@media (max-width: 700px) { .ambient-build { opacity: calc(var(--build) * .55); } }
.ambient::before {
  content: ""; position: absolute; inset: 0; opacity: calc(var(--ambient) * 2.2);
  background-image:
    linear-gradient(rgba(var(--sky-rgb), .5) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--sky-rgb), .5) 1px, transparent 1px),
    linear-gradient(rgba(var(--sky-rgb), .22) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--sky-rgb), .22) 1px, transparent 1px);
  background-size: 120px 120px, 120px 120px, 24px 24px, 24px 24px;
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000, transparent 85%);
          mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000, transparent 85%);
}
.ambient::after {
  content: ""; position: absolute; inset: 0; opacity: .045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .5 0 0 0 0 .5 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

h1, h2, h3, h4 { margin: 0; line-height: 1.25; text-wrap: balance; font-weight: 800; letter-spacing: -.015em; }
body[dir="ltr"] :is(h1, h2, h3, h4) { letter-spacing: -.022em; }
p { margin: 0; text-wrap: pretty; }
img, svg { max-width: 100%; height: auto; display: block; }
ul, ol { margin: 0; padding: 0; }
button { font: inherit; color: inherit; }
figure { margin: 0; }

a { color: var(--accent-strong); text-decoration: none; }
a:hover { color: var(--accent-deep); }

:focus-visible { outline: none; box-shadow: var(--ring); border-radius: 8px; }
::selection { background: var(--accent-soft); color: var(--ink); }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: rgba(var(--mint-rgb), .55); border-radius: 99px;
  border: 3px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: rgba(var(--mint-rgb), .9); background-clip: content-box; }

/* Latin runs — names, tech, URLs — get their own direction, so a Latin word
   never flips inside a Persian sentence. */
.lat { font-family: var(--display); direction: ltr; unicode-bidi: isolate; }
.mono { font-family: var(--mono); direction: ltr; unicode-bidi: isolate; font-size: .9em; }
.num { font-variant-numeric: tabular-nums; }

/* "forward" icons are drawn pointing left (forward in Persian); mirror for LTR.
   `scale` rather than `transform`, so a hover can still translate them. */
body[dir="ltr"] .fwd { scale: -1 1; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; inset-inline-start: 12px; top: -60px; z-index: 100;
  background: var(--mint); color: var(--on-accent);
  padding: 10px 18px; border-radius: var(--r-sm); font-weight: 700;
  transition: top .2s var(--ease);
}
.skip:focus { top: 12px; }

.shell { width: min(100% - 2.4rem, var(--shell)); margin-inline: auto; }

/* Single-column grids get an explicit minmax(0, 1fr). An implicit `auto`
   column grows to its widest unbreakable child — an email address, a stack
   name — and on a phone that pushes the whole page sideways. */
.cases, .timeline, .post-list, .channels, .cv-aside, .cv-main, .cv-projects,
.facts, .aside-card, .aside-actions, .form, .field, .vcard, .profile-actions, .cv-contact { grid-template-columns: minmax(0, 1fr); }
.narrow { width: min(100% - 2.4rem, 72ch); margin-inline: auto; }

.kbd {
  display: inline-flex; align-items: center; gap: 2px;
  font-family: var(--mono); font-size: 10.5px; font-weight: 500; line-height: 1;
  padding: 4px 6px; border-radius: 6px; direction: ltr;
  color: var(--mute); background: var(--surface-2);
  border: 1px solid var(--line); border-bottom-width: 2px;
}

/* ══════════════════════════════════════════════════════════════════════════
   3 · PRIMITIVES — button, icon button, pill, tag, chip, stack, eyebrow
   ══════════════════════════════════════════════════════════════════════════ */
.btn {
  position: relative; overflow: hidden; isolation: isolate;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 11px 20px; border-radius: 14px; border: 1px solid transparent;
  font-size: var(--step--1); font-weight: 700; line-height: 1.2; white-space: nowrap;
  cursor: pointer; text-align: center; color: var(--ink);
  transition: transform .25s var(--spring), box-shadow .25s var(--ease), background-color .2s, border-color .2s, color .2s;
}
.btn svg { width: 17px; height: 17px; flex: none; transition: translate .3s var(--spring), rotate .3s var(--spring); }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0) scale(.97); transition-duration: .08s; }
.btn:hover .fwd { translate: -3px 0; }
body[dir="ltr"] .btn:hover .fwd { translate: 3px 0; }
.btn-lg { padding: 14px 24px; font-size: var(--step-0); border-radius: 16px; }
.btn-sm { padding: 8px 14px; border-radius: 12px; }
.btn-block { width: 100%; }

/* the shine: one soft sweep across the face on hover */
.btn-primary::before, .btn-soft::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(105deg, transparent 30%, var(--shine) 50%, transparent 70%);
  translate: -110% 0; transition: translate .75s var(--ease);
}
.btn-primary:hover::before, .btn-soft:hover::before { translate: 110% 0; }

.btn-primary {
  background: linear-gradient(140deg, var(--accent) 0%, color-mix(in srgb, var(--accent) 55%, var(--surface)) 130%);
  color: var(--on-accent);
  border-color: rgba(var(--accent-rgb), .9);
  box-shadow: inset 0 1px 0 var(--shine), var(--glow);
}
.btn-primary:hover { color: var(--on-accent); box-shadow: inset 0 1px 0 var(--shine), 0 18px 38px -14px rgba(var(--accent-rgb), 1); }
.btn-soft { background: var(--accent-soft); color: var(--accent-deep); border-color: rgba(var(--accent-rgb), .45); }
.btn-soft:hover { color: var(--accent-deep); border-color: rgba(var(--accent-rgb), .9); box-shadow: var(--glow); }
.btn-ghost { background: var(--surface); color: var(--ink); border-color: var(--line); box-shadow: var(--shadow-1); }
.btn-ghost:hover { color: var(--accent-deep); border-color: rgba(var(--accent-rgb), .8); background: var(--accent-tint); }
.btn-quiet { background: transparent; color: var(--ink-2); border-color: var(--line); }
.btn-quiet:hover { color: var(--accent-deep); border-color: rgba(var(--accent-rgb), .7); background: var(--accent-tint); }

/* the busy state the contact form puts on its button while it posts */
.btn .spinner {
  display: none; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid currentColor; border-inline-end-color: transparent;
  animation: spin .7s linear infinite;
}
.btn.is-loading { pointer-events: none; }
.btn.is-loading svg { display: none; }
.btn.is-loading .spinner { display: inline-block; }
@keyframes spin { to { rotate: 360deg; } }

.icon-btn {
  position: relative; width: 40px; height: 40px; flex: none;
  display: inline-grid; place-items: center;
  border: 1px solid var(--line); border-radius: 13px;
  background: var(--surface); color: var(--ink-2);
  cursor: pointer;
  transition: color .2s, border-color .2s, background-color .2s, transform .25s var(--spring), box-shadow .2s;
}
.icon-btn svg { width: 18px; height: 18px; transition: rotate .45s var(--spring), scale .3s var(--spring); }
.icon-btn:hover { color: var(--accent-deep); border-color: rgba(var(--accent-rgb), .85); background: var(--accent-tint); transform: translateY(-1px); }
.icon-btn:hover svg { scale: 1.1; }
.icon-btn:active { transform: scale(.94); }

/* small square buttons that live inside a row: copy, open */
.mini-btn {
  flex: none; width: 32px; height: 32px; display: inline-grid; place-items: center;
  border: 1px solid var(--line); border-radius: 10px; background: var(--surface);
  color: var(--mute); cursor: pointer;
  transition: color .2s, border-color .2s, background-color .2s, transform .25s var(--spring);
}
.mini-btn svg { width: 15px; height: 15px; }
.mini-btn:hover { color: var(--accent-deep); border-color: rgba(var(--accent-rgb), .85); background: var(--accent-tint); transform: translateY(-1px); }
.mini-btn:active { transform: scale(.9); }
.mini-btn.is-done { color: var(--mint-deep); border-color: var(--mint); background: var(--mint-soft); }
.mini-btn.is-done svg { animation: popIn .4s var(--spring); }

.pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 14px 5px 12px; border-radius: 999px;
  font-size: var(--step--1); font-weight: 700; line-height: 1.7;
  background: var(--accent-soft); color: var(--accent-deep);
  border: 1px solid rgba(var(--accent-rgb), .55);
}
.pill-dot { position: relative; width: 8px; height: 8px; border-radius: 999px; background: var(--accent-strong); flex: none; }
.pill-dot.live::after {
  content: ""; position: absolute; inset: -4px; border-radius: inherit;
  border: 2px solid var(--accent-strong); opacity: 0;
  animation: ping 2.2s var(--ease) infinite;
}
@keyframes ping { 0% { scale: .5; opacity: .8; } 80%, 100% { scale: 1.6; opacity: 0; } }

.tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 11px; border-radius: 999px;
  font-size: 12px; line-height: 1.9; font-weight: 600;
  background: var(--accent-tint); color: var(--accent-strong);
  border: 1px solid rgba(var(--accent-rgb), .5);
  transition: background-color .2s, border-color .2s, transform .25s var(--spring);
}
a.tag:hover { background: var(--accent-soft); color: var(--accent-deep); border-color: var(--accent); transform: translateY(-1px); }

.chipbar { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 8px 7px 15px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink-2);
  font-size: var(--step--1); font-weight: 600; cursor: pointer; box-shadow: var(--shadow-1);
  transition: all .25s var(--ease);
}
body[dir="rtl"] .chip { padding: 7px 15px 7px 8px; }
.chip-n {
  min-width: 24px; padding: 0 7px; border-radius: 999px; font-size: 11px; line-height: 20px; text-align: center;
  background: var(--bg-inset); color: var(--mute); font-weight: 700;
  transition: inherit;
}
.chip:hover { border-color: rgba(var(--accent-rgb), .85); color: var(--accent-deep); background: var(--accent-tint); transform: translateY(-1px); }
.chip[aria-pressed="true"] {
  background: var(--accent); border-color: rgba(var(--accent-rgb), 1); color: var(--on-accent);
  box-shadow: var(--glow);
}
.chip[aria-pressed="true"] .chip-n { background: var(--glass); color: var(--on-accent); }

/* technology names: always Latin, always mono, never coloured by meaning */
.stack { display: flex; flex-wrap: wrap; gap: 6px; direction: ltr; justify-content: flex-start; }
body[dir="rtl"] .stack { justify-content: flex-end; }
.stack i {
  font-style: normal; font-family: var(--mono); font-size: 11px; line-height: 1;
  padding: 6px 9px; border-radius: 8px; color: var(--ink-2);
  background: var(--surface-2); border: 1px solid var(--line);
  transition: border-color .25s, background-color .25s, color .25s;
}
.stack i.more-n { color: var(--accent-deep); background: var(--accent-soft); border-color: rgba(var(--accent-rgb), .5); cursor: help; }

.eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--accent-deep);
  background: var(--accent-soft);
  border: 1px solid rgba(var(--accent-rgb), .55);
  padding: 4px 13px 4px 11px; border-radius: 999px;
  margin-bottom: 14px; direction: ltr;
}
.eyebrow::before {
  content: ""; width: 7px; height: 7px; border-radius: 3px; flex: none; rotate: 45deg;
  background: var(--accent-strong);
}

.more {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: var(--step--1); font-weight: 700; color: var(--accent-deep);
  padding: 8px 12px 8px 16px; border-radius: 999px;
  background: var(--accent-tint); border: 1px solid rgba(var(--accent-rgb), .55);
  transition: background-color .2s, border-color .2s, box-shadow .25s, transform .25s var(--spring);
}
body[dir="rtl"] .more { padding: 8px 16px 8px 12px; }
.more svg { width: 16px; height: 16px; transition: translate .3s var(--spring); }
.more:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-deep); box-shadow: var(--glow); transform: translateY(-1px); }
.more:hover .fwd { translate: -4px 0; }
body[dir="ltr"] .more:hover .fwd { translate: 4px 0; }

.note {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 16px; border-radius: var(--r);
  background: var(--accent-soft); color: var(--accent-deep);
  border: 1px solid rgba(var(--accent-rgb), .6);
  font-size: var(--step--1); font-weight: 600;
  animation: rise .6s var(--spring) both;
}
.note-ico {
  flex: none; width: 28px; height: 28px; border-radius: 9px; display: grid; place-items: center;
  background: var(--accent); color: var(--on-accent);
}
.note-ico svg { width: 16px; height: 16px; }
.note-ok .note-ico svg { stroke-dasharray: 24; stroke-dashoffset: 24; animation: draw .6s .25s var(--ease) forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }

/* ══════════════════════════════════════════════════════════════════════════
   4 · HEADER
   A floating glass bar. Transparent over the hero, frosted once the page
   has moved, with a four-hue reading progress line along its top edge.
   ══════════════════════════════════════════════════════════════════════════ */
.hdr { position: sticky; top: 0; z-index: 60; padding-block: 10px; }
.hdr-progress { position: absolute; inset-block-start: 0; inset-inline: 0; height: 3px; overflow: hidden; pointer-events: none; }
.hdr-progress span {
  display: block; height: 100%; transform: scaleX(0); transform-origin: left center;
  background: linear-gradient(90deg, var(--mint), var(--sky), var(--lilac), var(--peach));
}
body[dir="rtl"] .hdr-progress span { transform-origin: right center; }

.hdr-bar {
  display: flex; align-items: center; gap: 12px;
  min-height: 60px; padding-block: 8px; padding-inline: 14px 10px;
  border-radius: 20px; border: 1px solid transparent;
  transition: background-color .3s var(--ease), border-color .3s, box-shadow .3s, backdrop-filter .3s;
}
.hdr.is-stuck .hdr-bar, .hdr.is-open .hdr-bar {
  background: var(--glass);
  -webkit-backdrop-filter: saturate(1.6) blur(18px);
          backdrop-filter: saturate(1.6) blur(18px);
  border-color: var(--line); box-shadow: var(--shadow-2);
}

.brand { display: flex; align-items: center; gap: 11px; color: var(--ink); min-width: 0; }
.brand:hover { color: var(--ink); }
.brand-mark {
  position: relative; width: 40px; height: 40px; border-radius: 13px; flex: none; overflow: hidden;
  display: grid; place-items: center;
  /* a monogram, not a sticker: ink ground, paper letters, one mint rule */
  background: var(--ink);
  color: var(--bg);
  font-family: var(--mono); font-weight: 600; font-size: 13px; letter-spacing: .04em; direction: ltr;
  box-shadow: var(--shadow-1);
  transition: transform .4s var(--ease);
}
.brand-mark span { position: relative; }
.brand-mark::before {
  content: ""; position: absolute; inset-inline: 10px; bottom: 8px; height: 2px;
  background: var(--mint); transform-origin: left; scale: .35 1;
  transition: scale .5s var(--ease);
}
.brand-mark::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, .14) 50%, transparent 65%);
  translate: -120% 0; transition: translate .9s var(--ease);
}
.brand:hover .brand-mark { transform: translateY(-1px); }
.brand:hover .brand-mark::before { scale: 1 1; }
.brand:hover .brand-mark::after { translate: 120% 0; }
.brand-name { font-size: var(--step-0); font-weight: 800; letter-spacing: -.02em; line-height: 1.3; min-width: 0; }
.brand-name small {
  display: block; font-weight: 500; font-size: 11.5px; color: var(--mute); letter-spacing: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* The indicator is placed by app.js in pixels from the nav's own left edge
   (offsetLeft), which is physical in both directions — hence `left` and a
   translateX here, and nowhere else in the header. */
.nav { position: relative; display: flex; gap: 2px; margin-inline-start: auto; padding: 4px; border-radius: 16px; }
.nav a {
  position: relative; z-index: 1; padding: 8px 14px; border-radius: 12px;
  color: var(--ink-2); font-size: var(--step--1); font-weight: 600; white-space: nowrap;
  transition: color .2s;
}
.nav a:hover { color: var(--accent-deep); }
.nav a.is-active { color: var(--accent-deep); background: var(--accent-soft); }
.nav.has-ind a.is-active { background: transparent; }
.nav-ind {
  position: absolute; z-index: 0; left: 0; top: 4px; bottom: 4px; width: 0; border-radius: 12px;
  background: var(--accent-soft); border: 1px solid rgba(var(--accent-rgb), .55); opacity: 0;
  transition: transform .45s var(--spring), width .45s var(--spring), opacity .25s;
}
.nav-ind.no-anim { transition: none; }

.hdr-tools { display: flex; align-items: center; gap: 6px; }

.theme-btn .ti { display: none; }
:root:not([data-theme]) .theme-btn .ti-system,
:root[data-theme="light"] .theme-btn .ti-light,
:root[data-theme="dark"] .theme-btn .ti-dark { display: block; }
.theme-btn.is-turning svg { animation: turn .55s var(--spring); }
@keyframes turn { from { rotate: -120deg; scale: .5; opacity: 0; } }

.lang { position: relative; }
.lang-btn { width: auto; padding-inline: 10px; gap: 6px; font-size: var(--step--1); font-weight: 700; display: inline-flex; }
.lang-btn .chev { width: 14px; height: 14px; transition: rotate .3s var(--spring); }
.lang-btn[aria-expanded="true"] .chev { rotate: 180deg; }

.pop {
  position: absolute; inset-inline-end: 0; top: calc(100% + 10px); z-index: 70;
  min-width: 190px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--shadow-3);
  display: grid; gap: 2px; transform-origin: top;
}
.pop:not([hidden]) { animation: popDown .28s var(--spring); }
@keyframes popDown { from { opacity: 0; translate: 0 -6px; scale: .96; } }
.lang-menu a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border-radius: 11px; color: var(--ink-2); font-size: var(--step--1); font-weight: 600;
  transition: background-color .18s, color .18s;
}
.lang-menu a:hover { background: var(--accent-tint); color: var(--accent-deep); }
.lang-menu a[aria-current="true"] { color: var(--accent-deep); background: var(--accent-soft); }
.lang-menu .code {
  margin-inline-start: auto; font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em;
  color: var(--mute); padding: 1px 6px; border-radius: 6px; border: 1px solid var(--line);
}
.lang-menu .tick { width: 15px; height: 15px; opacity: 0; }
.lang-menu a[aria-current="true"] .tick { opacity: 1; }

.hdr-cta { margin-inline-start: 4px; }

.burger { display: none; }
.burger-lines { position: relative; width: 18px; height: 12px; }
.burger-lines i {
  position: absolute; inset-inline: 0; height: 2px; border-radius: 2px; background: currentColor;
  transition: top .3s var(--spring), rotate .3s var(--spring), opacity .2s;
}
.burger-lines i:nth-child(1) { top: 0; }
.burger-lines i:nth-child(2) { top: 5px; }
.burger-lines i:nth-child(3) { top: 10px; }
.burger[aria-expanded="true"] .burger-lines i:nth-child(1) { top: 5px; rotate: 45deg; }
.burger[aria-expanded="true"] .burger-lines i:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] .burger-lines i:nth-child(3) { top: 5px; rotate: -45deg; }

.mnav { display: none; }

@media (max-width: 960px) {
  .nav { display: none; }
  .hdr-tools { margin-inline-start: auto; }
  .burger { display: inline-grid; }
  .mnav:not([hidden]) {
    display: grid; gap: 12px; margin-top: 8px; padding: 12px;
    border-radius: var(--r-lg); background: var(--glass);
    -webkit-backdrop-filter: saturate(1.6) blur(18px); backdrop-filter: saturate(1.6) blur(18px);
    border: 1px solid var(--line); box-shadow: var(--shadow-3);
    animation: popDown .35s var(--spring);
  }
  .mnav-links { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; list-style: none; }
  .mnav-links a {
    display: flex; align-items: center; gap: 11px;
    padding: 10px; border-radius: 15px; color: var(--ink); font-weight: 700; font-size: var(--step--1);
    background: var(--surface); border: 1px solid var(--line);
    transition: border-color .2s, background-color .2s, transform .25s var(--spring);
  }
  .mnav-links a:hover, .mnav-links a.is-active { border-color: var(--accent); background: var(--accent-tint); color: var(--accent-deep); }
  .mnav-links .mi {
    width: 36px; height: 36px; border-radius: 11px; flex: none; display: grid; place-items: center;
    background: var(--accent-soft); color: var(--accent-deep);
  }
  .mnav-links .mi svg { width: 18px; height: 18px; }
  .mnav-links li { animation: rise .45s var(--spring) both; }
  .mnav-links li:nth-child(2) { animation-delay: .03s; } .mnav-links li:nth-child(3) { animation-delay: .06s; }
  .mnav-links li:nth-child(4) { animation-delay: .09s; } .mnav-links li:nth-child(5) { animation-delay: .12s; }
  .mnav-links li:nth-child(6) { animation-delay: .15s; } .mnav-links li:nth-child(7) { animation-delay: .18s; }
  .mnav-foot { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; padding-top: 4px; border-top: 1px dashed var(--line); }
  .mnav-foot a {
    padding: 6px 14px; border-radius: 999px; font-size: var(--step--1); font-weight: 600;
    color: var(--ink-2); border: 1px solid var(--line); background: var(--surface);
  }
  .mnav-foot a[aria-current="true"] { background: var(--mint-soft); color: var(--mint-deep); border-color: var(--mint); }
}
@media (max-width: 620px) {
  .hdr-cta, .brand-name small { display: none; }
  .hdr-bar { padding-inline: 10px 8px; gap: 8px; }
  .hdr-tools { gap: 4px; }
  .lang-btn .chev { display: none; }
}
@media (max-width: 400px) { .brand-name { display: none; } }

/* ══════════════════════════════════════════════════════════════════════════
   5 · SECTION FURNITURE
   ══════════════════════════════════════════════════════════════════════════ */
/* `overflow-x: clip` on <main> as well as <html>. A phone browser sizes its
   layout viewport to the widest thing on the page BEFORE the root's clip
   applies, so a decoration that pokes out — the portrait's blurred halo, whose
   box grows by √2 as it turns — made the page 420px wide on a 375px phone and
   swayed it sideways on the halo's 16-second cycle. Clipped here, nothing in
   the content can widen the page. `clip` makes no scroll container, so sticky
   children still stick, and the vertical bleed behind the header survives. */
main { display: block; min-height: 60vh; overflow-x: clip; }
.sec { padding-block: var(--sec); position: relative; }
.sec + .sec:not(.sec-band) { padding-block-start: 0; }
.sec-band + .sec { padding-block-start: var(--sec); }
.sec-flush { padding-block-start: 0; }
.sec-tight { padding-block: 0 var(--sec); }

/* A BAND is a section painted in its own accent's wash, edge to edge, with a
   hairline dot texture. It is what gives a long page a horizontal rhythm
   instead of one continuous sheet. */
.sec-band {
  background-color: var(--accent-wash);
  /* a touch see-through, so the building behind the page stays in view */
  background-color: color-mix(in srgb, var(--accent-wash) 62%, transparent);
  background-image: var(--dots);
  background-size: 22px 22px;
  border-block: 1px solid rgba(var(--accent-rgb), .3);
}

.sec-head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; flex-wrap: wrap;
  margin-bottom: clamp(1.5rem, 1rem + 1.6vw, 2.4rem);
}
.sec-title { font-size: var(--step-3); }
/* the accent arrives as a soft bar under the heading, which grows in when the
   head is revealed — so the heading itself keeps full ink contrast */
.sec-title::after {
  content: ""; display: block; width: 64px; height: 5px; border-radius: 99px;
  margin-block-start: 14px;
  background: linear-gradient(90deg, var(--accent), rgba(var(--accent-rgb), .15));
  transform-origin: left center;
  transition: scale .9s var(--spring) .15s;
}
body[dir="rtl"] .sec-title::after { background: linear-gradient(270deg, var(--accent), rgba(var(--accent-rgb), .15)); transform-origin: right center; }
.sec-lede { color: var(--ink-2); margin-top: 12px; max-width: 60ch; font-size: var(--step-1); line-height: 1.8; }
.legend { display: inline-flex; align-items: center; gap: 7px; color: var(--mute); font-size: var(--step--1); font-weight: 600; }
.legend svg { width: 15px; height: 15px; color: var(--peach-strong); fill: var(--peach); }

.page-head { position: relative; isolation: isolate; padding-block: clamp(2.2rem, 1.4rem + 3.5vw, 4.4rem) clamp(1.6rem, 1rem + 2vw, 2.8rem); }
/* It bleeds UP behind the transparent header, never sideways: a negative
   inline inset is scrollable overflow in RTL, and the Persian page then
   opens shifted by exactly that much. */
.page-head::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  inset-block: calc(-1 * var(--header-h) - 10px) 0; inset-inline: 0;
  background:
    radial-gradient(28% 60% at 80% 20%, rgba(var(--accent-rgb), .3), transparent 70%),
    radial-gradient(24% 50% at 20% 0%,  rgba(var(--peach-rgb), .22), transparent 70%);
  -webkit-mask-image: linear-gradient(to bottom, #000 40%, transparent);
          mask-image: linear-gradient(to bottom, #000 40%, transparent);
}
/* A PHOTO WASH is a portrait laid faintly behind the page. It is painted in
   the section's accent rather than in its own colours: the photo is the top
   background layer, the pastel under it, and `luminosity` keeps only the
   photo's light and shade — so a peach section gets a peach photograph and a
   sky one a sky photograph, in either theme, from any file. It sits over the
   site-wide ambient field and building and under the content, and its edges
   are feathered so it never shows a border. The source is `--src`, set
   inline from the template.

   The base class only paints; the two placements below position it. */
.photo-wash {
  position: absolute; z-index: -1; pointer-events: none;
  background: var(--src) var(--pos, 50% 50%) / var(--size, cover) no-repeat,
              linear-gradient(var(--accent), var(--accent)) var(--pos, 50% 50%) / var(--size, cover) no-repeat;
  background-blend-mode: luminosity, normal;
  opacity: var(--photo);
  filter: var(--photo-fx);
}

/* The standing portrait (/services/): the whole figure, pinned to the
   viewport at the inline end, so it stays in view the length of the page
   while the content scrolls over it. Its box takes the photo's own shape, so
   `cover` crops nothing. Two feathers, across and down, are intersected so
   every edge dissolves — a single radial would round off the figure. It is
   `fixed` from inside the head's stacking context, which keeps it under
   every later section and over the ambient layer. */
.photo-stand {
  position: fixed; inset-block: auto 0; inset-inline-end: clamp(0px, 4vw, 64px);
  height: calc(100vh - var(--header-h) + 10px); height: calc(100svh - var(--header-h) + 10px); max-width: 100vw;
  aspect-ratio: 840 / 1125;
  --pos: 50% 0%;
  opacity: var(--photo-stand);
  --feather-x: linear-gradient(to right, transparent, #000 22%, #000 78%, transparent);
  --feather-y: linear-gradient(to bottom, transparent, #000 7%, #000 80%, transparent);
  -webkit-mask-image: var(--feather-x), var(--feather-y);
  -webkit-mask-composite: source-in;
          mask-image: var(--feather-x), var(--feather-y);
          mask-composite: intersect;
}
/* The flashlight: a second copy, masked to a soft circle round the pointer
   as well as the two feathers. The photo takes no pointer events and sits
   under the content, so app.js (initPointer) writes --mx/--my in the photo's
   own pixels and sets .is-lit while the pointer is over it. */
.photo-stand.photo-lit {
  opacity: 0; transition: opacity .6s var(--ease);
  --beam: radial-gradient(220px circle at var(--mx, 50%) var(--my, 30%), #000 15%, rgba(0, 0, 0, .5) 55%, transparent 100%);
  -webkit-mask-image: var(--beam), var(--feather-x), var(--feather-y);
          mask-image: var(--beam), var(--feather-x), var(--feather-y);
}
.photo-stand.photo-lit.is-lit { opacity: calc(var(--photo-stand) * 2.4); }
/* on a phone the figure stands behind the text, so it steps further back */
@media (max-width: 760px) { .photo-stand { inset-inline-end: 0; opacity: calc(var(--photo-stand) * .6); } }

.page-title { font-size: var(--step-4); letter-spacing: -.03em; line-height: 1.12; }
.page-title .count {
  display: inline-grid; place-items: center; vertical-align: super;
  min-width: 34px; height: 34px; padding-inline: 8px; margin-inline-start: 6px;
  font-size: 15px; font-weight: 800; letter-spacing: 0; line-height: 1;
  border-radius: 12px; background: var(--accent); color: var(--on-accent); box-shadow: var(--glow);
}

.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin-bottom: 18px; font-size: var(--step--1); font-weight: 600; list-style: none; }
.crumbs a { color: var(--mute); padding: 3px 8px; border-radius: 8px; transition: background-color .2s, color .2s; }
.crumbs a:hover { color: var(--accent-deep); background: var(--accent-tint); }
.crumbs svg { width: 14px; height: 14px; color: var(--mute); rotate: 90deg; opacity: .7; }
body[dir="ltr"] .crumbs svg { rotate: -90deg; }
.crumbs [aria-current] { color: var(--ink-2); padding-inline: 8px; }

.empty { color: var(--mute); padding-block: 32px; text-align: center; }

/* ══════════════════════════════════════════════════════════════════════════
   6 · HERO
   ══════════════════════════════════════════════════════════════════════════ */
.hero { position: relative; isolation: isolate; padding-block: clamp(1.8rem, 1rem + 4vw, 4.6rem) 0; }

/* The aurora: four soft pastel fields, one per hue, drifting very slowly.
   They are radial gradients rather than blurred boxes, so the drift is a
   transform the compositor moves and not a blur it repaints. */
.hero-aurora {
  position: absolute; z-index: -1; pointer-events: none; overflow: hidden;
  inset-block: calc(-1 * var(--header-h) - 10px) -10%; inset-inline: 0;
  -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
}
.hero-aurora::after {
  content: ""; position: absolute; inset: 0;
  background-image: var(--dots); background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(70% 60% at 50% 30%, #000, transparent 75%);
          mask-image: radial-gradient(70% 60% at 50% 30%, #000, transparent 75%);
}
.hero-aurora i { position: absolute; width: 55vmax; height: 55vmax; border-radius: 50%; opacity: var(--aurora); }
.hero-aurora i:nth-child(1) { top: -28vmax; inset-inline-end: -12vmax; background: radial-gradient(closest-side, rgba(var(--mint-rgb), .55), transparent); }
.hero-aurora i:nth-child(2) { top: -20vmax; inset-inline-start: -18vmax; background: radial-gradient(closest-side, rgba(var(--peach-rgb), .45), transparent); }
.hero-aurora i:nth-child(3) { top: 12vmax; inset-inline-start: 22%; width: 42vmax; height: 42vmax; background: radial-gradient(closest-side, rgba(var(--lilac-rgb), .36), transparent); }
.hero-aurora i:nth-child(4) { top: 4vmax; inset-inline-end: 18%; width: 36vmax; height: 36vmax; background: radial-gradient(closest-side, rgba(var(--sky-rgb), .42), transparent); }

.hero-grid {
  display: grid; gap: clamp(2.4rem, 1rem + 5vw, 4.5rem);
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  align-items: center;
}
@media (max-width: 900px) { .hero-grid { grid-template-columns: minmax(0, 1fr); } .hero-visual { order: -1; } }

.hero-name {
  font-size: var(--step-4); letter-spacing: -.035em; line-height: 1.08;
  margin-block: 18px 0;
}
body[dir="ltr"] .hero-name { font-family: var(--display); font-weight: 650; letter-spacing: -.04em; }
/* a straight rule under the name: a hairline track drawn in from the start
   edge, then a short mint bar that sweeps its length and settles at the start */
.scribble { position: relative; display: inline-block; padding-bottom: .22em; }
.scribble::before, .scribble::after {
  content: ""; position: absolute; bottom: 0; height: 3px;
}
.scribble::after { inset-inline: 0; background: var(--ink); opacity: .14; }
.scribble::before {
  z-index: 1; inset-inline-start: 0; width: 22%;
  background: var(--mint-strong);
}
.hero-role { font-size: var(--step-2); font-weight: 700; color: var(--mint-deep); margin-top: 18px; letter-spacing: -.015em; line-height: 1.5; max-width: 32ch; }
.hero-intro { color: var(--ink-2); margin-top: 18px; max-width: 58ch; font-size: var(--step-1); line-height: 1.9; }
body[dir="ltr"] .hero-intro { line-height: 1.72; }
.hero-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 30px; }
.hero-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 22px; margin-top: 28px; color: var(--ink-2); font-size: var(--step--1); list-style: none; }
.hero-meta li { display: inline-flex; align-items: center; gap: 8px; }
.hero-meta li > svg { width: 17px; height: 17px; color: var(--peach-strong); }
.hero-meta a { color: var(--ink-2); }
.hero-meta a:hover { color: var(--accent-deep); }
.hero-meta .mini-btn { width: 28px; height: 28px; border-radius: 8px; }

/* The portrait: a squircle on a slowly turning four-hue halo, with the
   primary skills floating round it. */
.hero-visual { display: grid; place-items: center; padding: clamp(1rem, 3vw, 2.4rem); }
.portrait {
  position: relative; width: min(100%, 340px); aspect-ratio: 1;
  transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform .6s var(--ease);
}
.portrait.is-tilting { transition-duration: .12s; }
.portrait-ring {
  position: absolute; inset: -7%; border-radius: 42%;
  background: conic-gradient(from 0deg, var(--mint), var(--sky), var(--lilac), var(--peach), var(--mint));
  filter: blur(22px); opacity: .75;
  animation: halo 16s linear infinite;
}
@keyframes halo { to { rotate: 360deg; } }
.portrait-field {
  position: relative; width: 100%; height: 100%; overflow: hidden;
  border-radius: 38% 38% 38% 38% / 36% 36% 40% 40%;
  background: linear-gradient(155deg, var(--mint-soft), var(--lilac-soft));
  border: 6px solid var(--surface);
  box-shadow: var(--shadow-3);
  display: grid; place-items: center;
}
.portrait-field img { width: 100%; height: 100%; object-fit: cover; transition: scale .8s var(--ease); }
.portrait:hover .portrait-field img { scale: 1.04; }
.portrait-initials { font-family: var(--display); font-size: 84px; font-weight: 600; color: var(--mint-deep); opacity: .6; direction: ltr; }

.float-chip {
  position: absolute; z-index: 2;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 13px 7px 10px; border-radius: 14px;
  background: var(--glass); color: var(--ink);
  -webkit-backdrop-filter: blur(10px) saturate(1.5); backdrop-filter: blur(10px) saturate(1.5);
  border: 1px solid rgba(var(--accent-rgb), .7);
  box-shadow: var(--shadow-2);
  font-size: 12.5px; font-weight: 600; white-space: nowrap; cursor: default;
  animation: bob 6s ease-in-out infinite;
  transition: scale .3s var(--spring), box-shadow .3s;
}
.float-chip:hover { scale: 1.08; box-shadow: var(--shadow-2), var(--glow); }
.float-chip .dot { width: 22px; height: 22px; border-radius: 7px; display: grid; place-items: center; background: var(--accent); color: var(--on-accent); }
.float-chip .dot svg { width: 13px; height: 13px; }
.float-chip:nth-of-type(1) { top: 4%;    inset-inline-start: -14%; }
.float-chip:nth-of-type(2) { top: 30%;   inset-inline-end: -16%; animation-delay: -1.5s; }
.float-chip:nth-of-type(3) { bottom: 24%; inset-inline-start: -18%; animation-delay: -3s; }
.float-chip:nth-of-type(4) { top: -6%;   inset-inline-end: 4%;  animation-delay: -4.5s; }
.float-chip:nth-of-type(5) { bottom: 12%; inset-inline-end: -12%; animation-delay: -2.2s; }
@keyframes bob { 0%, 100% { translate: 0 0; } 50% { translate: 0 -9px; } }
@media (max-width: 520px) {
  .float-chip:nth-of-type(1) { inset-inline-start: -6%; }
  .float-chip:nth-of-type(2) { inset-inline-end: -6%; }
  .float-chip:nth-of-type(3) { inset-inline-start: -8%; }
  .float-chip:nth-of-type(5) { inset-inline-end: -6%; }
}

.portrait-dock {
  position: absolute; z-index: 3; bottom: -20px; inset-inline: 0; margin-inline: auto; width: max-content;
  display: flex; gap: 4px; padding: 5px; border-radius: 16px;
  background: var(--glass); border: 1px solid var(--line); box-shadow: var(--shadow-2);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
}
.dock-btn {
  width: 38px; height: 38px; border-radius: 12px; display: grid; place-items: center;
  color: var(--ink-2); transition: background-color .2s, color .2s, transform .3s var(--spring);
}
.dock-btn svg { width: 18px; height: 18px; }
.dock-btn:hover { background: var(--accent-soft); color: var(--accent-deep); transform: translateY(-3px) scale(1.08); }

/* The tech ribbon under the hero. Four copies of the list, moving one copy's
   width, so the seam never shows on a wide screen. Always LTR: these are
   Latin names and the loop needs one direction to be seamless. */
.marquee {
  margin-top: clamp(3rem, 2rem + 4vw, 5rem);
  border-block: 1px solid var(--line);
  background: color-mix(in srgb, var(--surface) 55%, transparent);
  overflow: hidden; direction: ltr;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.marquee-track { display: flex; width: max-content; animation: marquee 38s linear infinite; }
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-list { display: flex; align-items: center; gap: 12px; padding: 14px 6px; list-style: none; }
.marquee-list li {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 6px 14px; border-radius: 999px;
  font-family: var(--mono); font-size: 13px; font-weight: 500; color: var(--ink-2);
  background: var(--surface); border: 1px solid var(--line);
  transition: border-color .2s, color .2s, background-color .2s;
}
.marquee-list li::before { content: ""; width: 7px; height: 7px; border-radius: 3px; rotate: 45deg; background: var(--accent); }
.marquee-list li:hover { border-color: var(--accent); color: var(--accent-deep); background: var(--accent-tint); }
@keyframes marquee { to { transform: translateX(-25%); } }

/* ══════════════════════════════════════════════════════════════════════════
   7 · AT A GLANCE + NOW
   ══════════════════════════════════════════════════════════════════════════ */
.glance { padding-block: clamp(2.2rem, 1.6rem + 2vw, 3.2rem); }
.glance-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr)); list-style: none; }
.glance-tile {
  position: relative; overflow: hidden; display: grid; grid-template-columns: auto 1fr; gap: 2px 14px; align-items: center;
  padding: 16px 18px; border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-1);
  transition: transform .35s var(--spring), border-color .25s, box-shadow .3s;
}
.glance-tile:hover { transform: translateY(-3px); border-color: rgba(var(--accent-rgb), .9); box-shadow: var(--shadow-2); }
.glance-ico {
  grid-row: span 2; width: 46px; height: 46px; border-radius: 15px; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-deep); border: 1px solid rgba(var(--accent-rgb), .55);
  transition: rotate .45s var(--spring), scale .3s var(--spring);
}
.glance-ico svg { width: 22px; height: 22px; }
.glance-tile:hover .glance-ico { rotate: -8deg; scale: 1.06; }
.glance-label { font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--accent-strong); font-weight: 500; line-height: 1.4; direction: ltr; text-align: start; }
body[dir="rtl"] .glance-label { font-family: var(--sans); letter-spacing: 0; font-size: 12px; font-weight: 700; direction: rtl; }
.glance-value { font-weight: 700; font-size: var(--step--1); line-height: 1.55; color: var(--ink); }

.now {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 12px 18px; flex-wrap: wrap;
  padding: 18px var(--pad); border-radius: var(--r-lg);
  background: linear-gradient(100deg, var(--accent-soft), var(--accent-tint) 60%);
  border: 1px solid rgba(var(--accent-rgb), .6);
}
body[dir="rtl"] .now { background: linear-gradient(260deg, var(--accent-soft), var(--accent-tint) 60%); }
.now-badge {
  display: inline-flex; align-items: center; gap: 9px; flex: none;
  padding: 5px 14px 5px 11px; border-radius: 999px;
  background: var(--surface); color: var(--accent-deep); font-weight: 800; font-size: var(--step--1);
  box-shadow: var(--shadow-1);
}
.now p { color: var(--ink); flex: 1 1 280px; font-weight: 500; }

/* ══════════════════════════════════════════════════════════════════════════
   8 · WORK — case rows (home, next project) and cards (the list)
   ══════════════════════════════════════════════════════════════════════════ */
.cases { display: grid; gap: clamp(1.1rem, .8rem + 1vw, 1.6rem); }
.case {
  position: relative; overflow: hidden;
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl);
  /* see-through, like the bands, so the page's background reads through */
  background: color-mix(in srgb, var(--surface) 64%, transparent);
  box-shadow: var(--shadow-1); color: var(--ink);
  transition: transform .45s var(--spring), box-shadow .35s var(--ease), border-color .3s;
}
.cases > .case:nth-child(even) .case-cover { order: 2; }
.case:hover { color: var(--ink); transform: translateY(-5px); border-color: rgba(var(--accent-rgb), .95); box-shadow: var(--shadow-2), var(--glow); }
@media (max-width: 780px) { .case { grid-template-columns: minmax(0, 1fr); } .cases > .case:nth-child(even) .case-cover { order: 0; } }

/* A cover with no image is not empty: it is the project's index over a
   pastel field with three soft shapes and a faint grid. When `cover` lands,
   the image fills this same box and nothing around it moves. */
.case-cover, .pcard-cover {
  position: relative; overflow: hidden; min-height: 220px;
  display: grid; place-items: center;
  background:
    radial-gradient(90% 90% at 85% 10%, rgba(var(--accent-rgb), .55), transparent 60%),
    linear-gradient(160deg, color-mix(in srgb, var(--accent-soft) 70%, transparent), color-mix(in srgb, var(--accent-tint) 55%, transparent));
}
.case-cover::before, .pcard-cover::before {
  content: ""; position: absolute; inset: 0;
  background-image: linear-gradient(rgba(var(--accent-rgb), .28) 1px, transparent 1px), linear-gradient(90deg, rgba(var(--accent-rgb), .28) 1px, transparent 1px);
  background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(75% 75% at 50% 50%, #000, transparent 80%);
          mask-image: radial-gradient(75% 75% at 50% 50%, #000, transparent 80%);
}
.case-cover img, .pcard-cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: scale .8s var(--ease); }
.case:hover .case-cover img, .pcard:hover .pcard-cover img { scale: 1.05; }
.cover-art i { position: absolute; display: block; transition: translate .8s var(--spring), rotate .8s var(--spring); }
.cover-art i:nth-child(1) { width: 38%; aspect-ratio: 1; border-radius: 50%; top: 12%; inset-inline-start: 10%; background: rgba(var(--accent-rgb), .45); }
.cover-art i:nth-child(2) { width: 26%; aspect-ratio: 1; border-radius: 28%; bottom: 10%; inset-inline-end: 12%; rotate: 18deg; background: var(--surface); opacity: .75; }
.cover-art i:nth-child(3) { width: 18%; aspect-ratio: 1; border-radius: 50%; top: 18%; inset-inline-end: 22%; border: 5px solid rgba(var(--accent-rgb), .8); }
.case:hover .cover-art i:nth-child(1), .pcard:hover .cover-art i:nth-child(1) { translate: 8% 10%; }
.case:hover .cover-art i:nth-child(2), .pcard:hover .cover-art i:nth-child(2) { rotate: 60deg; translate: -10% -8%; }
.case:hover .cover-art i:nth-child(3), .pcard:hover .cover-art i:nth-child(3) { translate: -30% 20%; }
.cover-index {
  position: relative; font-family: var(--display); font-size: clamp(64px, 5vw + 40px, 104px); font-weight: 600; line-height: 1;
  color: var(--accent-deep); opacity: .85; direction: ltr; letter-spacing: -.04em;
  text-shadow: 0 2px 0 var(--surface);
  transition: scale .6s var(--spring);
}
.case:hover .cover-index, .pcard:hover .cover-index { scale: 1.08; }
.cover-year {
  position: absolute; inset-block-start: 14px; inset-inline-start: 14px;
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 11.5px; font-weight: 500;
  padding: 4px 10px; border-radius: 999px;
  background: var(--glass); color: var(--accent-deep);
  border: 1px solid rgba(var(--accent-rgb), .6);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}

.case-body { padding: clamp(1.3rem, 1rem + 1.6vw, 2.3rem); display: flex; flex-direction: column; gap: 12px; }
.case-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.case-title { font-size: var(--step-2); letter-spacing: -.02em; transition: color .2s; }
.case:hover .case-title { color: var(--accent-deep); }
.case-sum { color: var(--ink-2); }
.case-outcome {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 12px 14px; border-radius: var(--r);
  background: var(--accent-tint); border: 1px dashed rgba(var(--accent-rgb), .9);
  font-size: var(--step--1); color: var(--ink); line-height: 1.75;
}
.case-outcome svg { width: 20px; height: 20px; flex: none; color: var(--accent-strong); margin-top: 3px; }
.case-outcome b { display: block; font-size: 11.5px; color: var(--accent-strong); font-weight: 800; }
.case-foot { margin-top: auto; padding-top: 6px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; }
.case-go {
  display: inline-flex; align-items: center; gap: 8px; font-weight: 700; font-size: var(--step--1); color: var(--accent-deep);
  padding: 7px 14px; border-radius: 999px; background: var(--accent-soft);
  transition: background-color .25s, gap .3s var(--spring);
}
.case-go svg { width: 16px; height: 16px; }
.case:hover .case-go { background: var(--accent); color: var(--on-accent); gap: 14px; }
.case:hover .stack i { border-color: rgba(var(--accent-rgb), .6); }

.grid-projects { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); }
.pcard {
  position: relative; overflow: hidden; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--surface) 64%, transparent);
  box-shadow: var(--shadow-1); color: var(--ink);
  transition: transform .45s var(--spring), box-shadow .35s var(--ease), border-color .3s;
}
.pcard:hover { color: var(--ink); transform: translateY(-6px); border-color: rgba(var(--accent-rgb), .95); box-shadow: var(--shadow-2), var(--glow); }
.pcard-cover { min-height: 0; aspect-ratio: 16 / 10; flex: none; }
.pcard-cover .cover-index { font-size: 72px; }
.pcard-go {
  position: absolute; inset-block-end: 14px; inset-inline-end: 14px;
  width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center;
  background: var(--surface); color: var(--accent-deep); box-shadow: var(--shadow-2);
  opacity: 0; scale: .6; transition: opacity .3s, scale .4s var(--spring);
}
.pcard-go svg { width: 18px; height: 18px; }
.pcard:hover .pcard-go, .pcard:focus-visible .pcard-go { opacity: 1; scale: 1; }
.pcard-body { padding: var(--pad); display: flex; flex-direction: column; gap: 10px; flex: 1; }
.pcard-title { font-size: var(--step-1); transition: color .2s; }
.pcard:hover .pcard-title { color: var(--accent-deep); }
.pcard-sum { color: var(--ink-2); font-size: var(--step--1); line-height: 1.85; flex: 1; }
.pcard .stack { margin-top: 6px; }

/* the filter shows a card again with a small spring rather than a jump */
.is-pop { animation: popIn .5s var(--spring); }
@keyframes popIn { from { opacity: 0; scale: .94; } }

/* ══════════════════════════════════════════════════════════════════════════
   9 · SKILLS
   ══════════════════════════════════════════════════════════════════════════ */
.skill-groups { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); }
@media (min-width: 900px) { .skill-groups { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.skill-group {
  position: relative; overflow: hidden;
  padding: var(--pad); border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-1);
  transition: border-color .3s, box-shadow .35s var(--ease), transform .45s var(--spring);
}
.skill-group:hover { transform: translateY(-4px); border-color: rgba(var(--accent-rgb), .95); box-shadow: var(--shadow-2), var(--glow); }
.sg-head { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.sg-ico {
  width: 42px; height: 42px; border-radius: 14px; flex: none; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-deep); border: 1px solid rgba(var(--accent-rgb), .55);
  transition: rotate .5s var(--spring);
}
.sg-ico svg { width: 21px; height: 21px; }
.skill-group:hover .sg-ico { rotate: 8deg; }
.sg-head h3 { font-size: var(--step-1); flex: 1; }
.sg-count {
  font-family: var(--mono); font-size: 11px; font-weight: 500; color: var(--accent-deep);
  padding: 2px 9px; border-radius: 999px; background: var(--accent-tint); border: 1px solid rgba(var(--accent-rgb), .5);
}
.skill-list { display: flex; flex-wrap: wrap; gap: 7px; list-style: none; }
.skill-list li {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 12.5px; line-height: 1; direction: ltr;
  padding: 8px 12px; border-radius: 10px;
  background: var(--surface-2); color: var(--ink-2); border: 1px solid var(--line);
  transition: transform .3s var(--spring), border-color .2s, background-color .2s, color .2s;
}
.skill-list li:hover { transform: translateY(-2px); border-color: var(--accent); color: var(--accent-deep); }
.skill-list li svg { width: 13px; height: 13px; fill: var(--accent); color: var(--accent-deep); }
.skill-list li.is-primary { background: var(--accent-soft); color: var(--accent-deep); font-weight: 500; border-color: rgba(var(--accent-rgb), .7); }
.skill-list li.is-primary:hover svg { animation: twinkle .7s var(--spring); }
@keyframes twinkle { 50% { rotate: 72deg; scale: 1.35; } }

/* ══════════════════════════════════════════════════════════════════════════
   10 · TIMELINE
   ══════════════════════════════════════════════════════════════════════════ */
.timeline { list-style: none; display: grid; gap: 16px; position: relative; }
.timeline::before {
  content: ""; position: absolute; inset-block: 12px 12px; inset-inline-start: 11px; width: 2px; border-radius: 2px;
  background: linear-gradient(to bottom, var(--accent), rgba(var(--accent-rgb), .15));
}
.tl-item { position: relative; padding-inline-start: 42px; }
.tl-dot {
  position: absolute; inset-inline-start: 3px; inset-block-start: 26px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--surface); border: 3px solid var(--accent);
  box-shadow: 0 0 0 5px var(--accent-wash);
  transition: scale .35s var(--spring), background-color .2s;
}
.tl-item:hover .tl-dot { scale: 1.2; background: var(--accent); }
.tl-item.is-current .tl-dot { background: var(--accent-strong); border-color: var(--accent-strong); }
.tl-card {
  position: relative; overflow: hidden;
  padding: clamp(1.1rem, .9rem + 1vw, 1.6rem) var(--pad); border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-1);
  transition: border-color .3s, box-shadow .35s var(--ease), transform .45s var(--spring);
}
.tl-item:hover .tl-card { border-color: rgba(var(--accent-rgb), .95); box-shadow: var(--shadow-2); transform: translateX(-4px); }
body[dir="ltr"] .tl-item:hover .tl-card { transform: translateX(4px); }
.tl-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: 10px 20px; }
.tl-role { font-size: var(--step-1); }
.tl-org { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 4px; color: var(--accent-strong); font-weight: 700; font-size: var(--step--1); }
.tl-org a { color: var(--accent-strong); text-decoration: underline; text-decoration-color: rgba(var(--accent-rgb), .8); text-underline-offset: 4px; }
.tl-loc { display: inline-flex; align-items: center; gap: 5px; color: var(--mute); font-weight: 500; }
.tl-loc svg { width: 14px; height: 14px; }
.tl-when { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.tl-dates {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  font-size: 12.5px; font-weight: 600; color: var(--ink-2);
  padding: 4px 11px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--line);
}
.tl-dates svg { width: 14px; height: 14px; color: var(--accent-strong); }
.tl-dur {
  font-size: 11.5px; font-weight: 700; color: var(--accent-deep); padding: 1px 10px; border-radius: 999px;
  background: var(--accent-soft); cursor: help;
}
@media (max-width: 640px) { .tl-when { align-items: flex-start; flex-direction: row; flex-wrap: wrap; } }
.tl-desc { color: var(--ink-2); font-size: var(--step--1); margin-top: 14px; padding-top: 14px; border-top: 1px dashed var(--line); line-height: 1.9; }
.tl-desc > * + * { margin-top: 10px; }
.tl-desc ul { padding-inline-start: 0; list-style: none; display: grid; gap: 7px; }
.tl-desc li { position: relative; padding-inline-start: 20px; }
.tl-desc li::before {
  content: ""; position: absolute; inset-inline-start: 2px; top: .75em; width: 7px; height: 7px;
  border-radius: 2px; rotate: 45deg; background: var(--accent);
}
body[dir="ltr"] .tl-desc li::before { top: .62em; }

/* ══════════════════════════════════════════════════════════════════════════
   11 · POSTS
   ══════════════════════════════════════════════════════════════════════════ */
.post-list { display: grid; gap: 12px; list-style: none; }
.post-row {
  position: relative; overflow: hidden;
  display: grid; grid-template-columns: 1fr auto; gap: 8px 20px; align-items: center;
  padding: 20px var(--pad); border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-1);
  color: var(--ink);
  transition: border-color .25s, transform .45s var(--spring), box-shadow .35s;
}
.post-row:hover { color: var(--ink); transform: translateY(-3px); border-color: rgba(var(--accent-rgb), .95); box-shadow: var(--shadow-2), var(--glow); }
.post-title { font-size: var(--step-1); transition: color .2s; }
.post-row:hover .post-title { color: var(--accent-deep); }
.post-ex { color: var(--ink-2); font-size: var(--step--1); margin-top: 6px; }
.post-foot { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; margin-top: 12px; }
.post-meta { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--mute); font-weight: 600; }
.post-meta svg { width: 14px; height: 14px; color: var(--accent-strong); }
.post-go {
  width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-deep);
  transition: background-color .25s, translate .4s var(--spring);
}
.post-go svg { width: 18px; height: 18px; }
.post-row:hover .post-go { background: var(--accent); color: var(--on-accent); translate: -4px 0; }
body[dir="ltr"] .post-row:hover .post-go { translate: 4px 0; }

/* ══════════════════════════════════════════════════════════════════════════
   12 · ARTICLE BODY (Markdown output)
   ══════════════════════════════════════════════════════════════════════════ */
.prose { font-size: var(--step-1); line-height: 2; color: var(--ink-2); }
body[dir="ltr"] .prose { line-height: 1.78; }
.prose > * + * { margin-top: 1.1em; }
.prose h2 { font-size: var(--step-2); color: var(--ink); margin-top: 1.9em; }
.prose h3 {
  display: flex; align-items: center; gap: 12px;
  font-size: var(--step-1); color: var(--ink); margin-top: 1.9em;
}
.prose h3::before { content: ""; width: 10px; height: 10px; border-radius: 3px; rotate: 45deg; flex: none; background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.prose strong { color: var(--ink); font-weight: 750; }
.prose ul, .prose ol { padding-inline-start: 1.3em; display: grid; gap: .55em; }
.prose li::marker { color: var(--accent-strong); }
.prose blockquote {
  margin-inline: 0; border-inline-start: 4px solid var(--accent);
  padding: 14px 20px; border-start-end-radius: var(--r); border-end-end-radius: var(--r);
  background: var(--accent-tint); color: var(--ink);
}
.prose code {
  font-family: var(--mono); font-size: .82em; direction: ltr; unicode-bidi: isolate;
  background: var(--peach-tint); border: 1px solid rgba(var(--peach-rgb), .6);
  padding: 1px 6px; border-radius: 6px; color: var(--peach-deep);
}
.prose pre {
  background: var(--bg-inset); border: 1px solid var(--line);
  border-radius: var(--r); padding: 16px 18px; overflow-x: auto;
  direction: ltr; text-align: left;
}
.prose pre code { background: none; border: 0; padding: 0; color: var(--ink); font-size: .8em; line-height: 1.75; }
.prose img { border-radius: var(--r); border: 1px solid var(--line); }
.prose hr { border: 0; border-top: 1px dashed var(--line); margin-block: 2em; }
.prose a { color: var(--accent-strong); text-decoration: underline; text-underline-offset: 4px; text-decoration-color: rgba(var(--accent-rgb), .9); text-decoration-thickness: 2px; }
.prose a:hover { color: var(--accent-deep); background: var(--accent-tint); }

/* ══════════════════════════════════════════════════════════════════════════
   13 · DETAIL PAGES — project and post
   ══════════════════════════════════════════════════════════════════════════ */
.lede-lg { font-size: var(--step-2); line-height: 1.65; max-width: 62ch; color: var(--ink-2); font-weight: 500; }
.detail-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }

.outcome {
  display: flex; gap: 16px; align-items: flex-start; max-width: 780px;
  margin-top: 26px; padding: 18px 20px; border-radius: var(--r-lg);
  background: linear-gradient(120deg, var(--accent-soft), var(--accent-tint) 70%);
  border: 1px solid rgba(var(--accent-rgb), .7);
  box-shadow: var(--shadow-1);
}
.outcome-ico {
  flex: none; width: 46px; height: 46px; border-radius: 15px; display: grid; place-items: center;
  background: var(--accent); color: var(--on-accent); box-shadow: var(--glow);
}
.outcome-ico svg { width: 22px; height: 22px; }
.outcome-label { display: block; font-size: 12px; font-weight: 800; color: var(--accent-deep); margin-bottom: 2px; }
.outcome p { color: var(--ink); font-weight: 600; }

.detail-grid { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: clamp(2rem, 1rem + 3.5vw, 4.5rem); align-items: start; padding-bottom: var(--sec); }
@media (max-width: 980px) { .detail-grid { grid-template-columns: minmax(0, 1fr); } .detail-aside { order: -1; } }
.detail-cover { margin-bottom: 36px; }
.detail-cover img { width: 100%; border-radius: var(--r-xl); border: 1px solid var(--line); box-shadow: var(--shadow-2); }
.detail-block + .detail-block { margin-top: 44px; }
.block-title { display: flex; align-items: center; gap: 12px; font-size: var(--step-2); margin-bottom: 16px; }
.block-ico { width: 40px; height: 40px; border-radius: 13px; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent-deep); flex: none; }
.block-ico svg { width: 20px; height: 20px; }

.detail-aside { position: sticky; top: calc(var(--header-h) + 16px); }
@media (max-width: 980px) { .detail-aside { position: static; } }
.aside-card {
  padding: var(--pad); border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-2);
  display: grid; gap: 18px;
}
.facts { display: grid; gap: 14px; margin: 0; }
.fact { display: grid; grid-template-columns: auto 1fr; gap: 0 12px; align-items: start; }
.fact-ico {
  grid-row: span 2; width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-deep);
}
.fact-ico svg { width: 18px; height: 18px; }
.fact dt { font-size: 12px; font-weight: 700; color: var(--mute); line-height: 1.5; }
.fact dd { margin: 0; font-weight: 700; font-size: var(--step--1); color: var(--ink); line-height: 1.6; }
.fact dd .stack { margin-top: 6px; }
.aside-actions { display: grid; gap: 8px; padding-top: 18px; border-top: 1px dashed var(--line); }

.post-head-meta { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; margin-top: 18px; }
.article-foot { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 48px; padding-top: 24px; border-top: 1px dashed var(--line); }

/* ══════════════════════════════════════════════════════════════════════════
   14 · ABOUT
   ══════════════════════════════════════════════════════════════════════════ */
.about-grid { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: clamp(2rem, 1rem + 4vw, 5rem); align-items: start; }
@media (max-width: 980px) { .about-grid { grid-template-columns: minmax(0, 1fr); } .about-aside { order: -1; } }
.about-main .prose { max-width: 70ch; }
.about-aside { position: sticky; top: calc(var(--header-h) + 16px); }
@media (max-width: 980px) { .about-aside { position: static; } }

.profile-card {
  position: relative; overflow: hidden; text-align: center;
  padding: 0 var(--pad) var(--pad); border-radius: var(--r-xl);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-2);
  display: grid; justify-items: center; gap: 12px;
}
.profile-card::before {
  content: ""; position: absolute; inset-inline: 0; top: 0; height: 110px; z-index: 0;
  background: linear-gradient(120deg, var(--mint-soft), var(--sky-soft), var(--lilac-soft), var(--peach-soft));
}
.profile-card > * { position: relative; }
.profile-face {
  width: 116px; height: 116px; margin-top: 44px; border-radius: 36px; overflow: hidden;
  border: 5px solid var(--surface); box-shadow: var(--shadow-2);
  background: var(--mint-soft); display: grid; place-items: center;
  transition: border-radius .5s var(--spring), rotate .5s var(--spring);
}
.profile-card:hover .profile-face { border-radius: 50%; rotate: -4deg; }
.profile-face img { width: 100%; height: 100%; object-fit: cover; }
.profile-face span { font-family: var(--display); font-size: 40px; color: var(--mint-deep); direction: ltr; }
.profile-name { font-size: var(--step-1); }
.profile-role { color: var(--ink-2); font-size: var(--step--1); line-height: 1.7; }
.profile-card .facts { width: 100%; text-align: start; padding-block: 16px 4px; border-top: 1px dashed var(--line); }
.profile-links { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.profile-links .dock-btn { border: 1px solid var(--line); background: var(--surface-2); }
.profile-actions { display: grid; gap: 8px; width: 100%; }

/* ══════════════════════════════════════════════════════════════════════════
   15 · RÉSUMÉ — a Lebenslauf layout, screen and paper from one template
   ══════════════════════════════════════════════════════════════════════════ */
.cv-hero {
  position: relative; overflow: hidden; isolation: isolate;
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 18px clamp(1rem, 3vw, 2rem); align-items: center;
  padding: clamp(1.2rem, 1rem + 1.5vw, 2rem); border-radius: var(--r-xl);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-2);
}
.cv-hero::before {
  content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; width: 6px;
  background: linear-gradient(to bottom, var(--mint), var(--sky), var(--lilac), var(--peach));
}
/* In the résumé card the wash is two copies of one photo, both spanning the
   whole card so the pointer's --mx/--my (card pixels, from data-spot) are
   their pixels too. The photo is drawn only in the card's inline-end part.
   The first copy is barely there; the second is a flashlight: masked to a
   soft circle round the pointer, it comes up on hover and the face appears
   where the light falls. Touch and reduced motion keep the faint copy only. */
.cv-hero .photo-wash {
  inset: 0; --w: min(46%, 460px); --size: var(--w) auto; --pos: right 0 top 36%; --to-end: to right;
  opacity: calc(var(--photo) * .5);
  -webkit-mask-image: linear-gradient(var(--to-end), transparent calc(100% - var(--w)), #000 calc(100% - var(--w) * .3));
          mask-image: linear-gradient(var(--to-end), transparent calc(100% - var(--w)), #000 calc(100% - var(--w) * .3));
}
body[dir="rtl"] .cv-hero .photo-wash { --pos: left 0 top 36%; --to-end: to left; }
@media (max-width: 760px) {
  .cv-hero .photo-wash { --w: 82%; --pos: right 0 top 30%; }
  body[dir="rtl"] .cv-hero .photo-wash { --pos: left 0 top 30%; }
}
.cv-hero .photo-lit {
  opacity: 0; transition: opacity .5s var(--ease);
  -webkit-mask-image:
    radial-gradient(170px circle at var(--mx, 80%) var(--my, 45%), #000 20%, rgba(0, 0, 0, .55) 55%, transparent 100%),
    linear-gradient(var(--to-end), transparent calc(100% - var(--w)), #000 calc(100% - var(--w) * .55));
  -webkit-mask-composite: source-in;
          mask-image:
    radial-gradient(170px circle at var(--mx, 80%) var(--my, 45%), #000 20%, rgba(0, 0, 0, .55) 55%, transparent 100%),
    linear-gradient(var(--to-end), transparent calc(100% - var(--w)), #000 calc(100% - var(--w) * .55));
          mask-composite: intersect;
}
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .cv-hero:hover .photo-lit { opacity: calc(var(--photo) * 3); }
}
@media (max-width: 760px) { .cv-hero { grid-template-columns: auto minmax(0, 1fr); } .cv-actions { grid-column: 1 / -1; } }
.cv-face { width: 104px; height: 104px; border-radius: 30px; overflow: hidden; background: var(--sky-soft); display: grid; place-items: center; box-shadow: var(--shadow-1); }
@media (max-width: 520px) { .cv-face { width: 72px; height: 72px; border-radius: 22px; } }
.cv-face img { width: 100%; height: 100%; object-fit: cover; }
.cv-face span { font-family: var(--display); font-size: 36px; color: var(--sky-deep); direction: ltr; }
.cv-id .eyebrow { margin-bottom: 8px; }
.cv-id .page-title { font-size: var(--step-3); }
.cv-id .sec-lede { margin-top: 6px; font-size: var(--step-0); }
.cv-actions { display: flex; flex-wrap: wrap; gap: 8px; }

.cv-grid { display: grid; grid-template-columns: 310px minmax(0, 1fr); gap: clamp(1.5rem, 1rem + 3vw, 3.5rem); align-items: start; padding-block: clamp(1.6rem, 1rem + 2vw, 2.6rem) var(--sec); }
@media (max-width: 900px) { .cv-grid { grid-template-columns: minmax(0, 1fr); } .cv-main { order: -1; } }
.cv-aside { display: grid; gap: 14px; }
.cv-block { padding: 18px; border-radius: var(--r-lg); background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-1); }
.cv-h { display: flex; align-items: center; gap: 9px; font-size: 13px; font-weight: 800; color: var(--accent-deep); margin-bottom: 12px; }
.cv-h::before { content: ""; width: 8px; height: 8px; border-radius: 2px; rotate: 45deg; background: var(--accent); }
.cv-contact { list-style: none; display: grid; gap: 10px; }
.cv-contact li { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 0 10px; align-items: center; }
.cv-contact .ci { width: 32px; height: 32px; border-radius: 10px; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent-deep); }
.cv-contact .ci svg { width: 16px; height: 16px; }
.cv-contact small { display: block; font-size: 11px; color: var(--mute); font-weight: 700; line-height: 1.3; }
.cv-contact a, .cv-contact .v { display: block; font-size: 13px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cv-contact .v { white-space: normal; }
.cv-contact a:hover { color: var(--accent-deep); }
.cv-block p { font-size: var(--step--1); font-weight: 600; color: var(--ink); line-height: 1.8; }
.cv-skills + .cv-skills { margin-top: 14px; padding-top: 14px; border-top: 1px dashed var(--line); }
.cv-skills h3 { font-size: 13px; margin-bottom: 8px; color: var(--ink); }
.skill-list-sm li { font-size: 11.5px; padding: 6px 9px; border-radius: 8px; }

.cv-main { display: grid; gap: clamp(2rem, 1.4rem + 2vw, 3rem); }
.cv-title { display: flex; align-items: center; gap: 12px; font-size: var(--step-2); margin-bottom: 18px; }
.cv-title .block-ico { background: var(--accent-soft); }
.cv-intro { font-size: var(--step-1); color: var(--ink-2); line-height: 1.95; padding: 20px var(--pad); border-radius: var(--r-lg); background: var(--accent-tint); border: 1px solid rgba(var(--accent-rgb), .45); }
body[dir="ltr"] .cv-intro { line-height: 1.75; }
.cv-projects { list-style: none; display: grid; gap: 10px; }
.cv-projects a {
  position: relative; overflow: hidden; display: grid; gap: 6px;
  padding: 16px 18px; border-radius: var(--r); color: var(--ink);
  background: var(--surface); border: 1px solid var(--line);
  transition: border-color .25s, transform .4s var(--spring), box-shadow .3s;
}
.cv-projects a:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow-2); color: var(--ink); }
.cv-p-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.cv-p-head h3 { font-size: var(--step-0); }
.cv-p-head span { font-family: var(--mono); font-size: 12px; color: var(--accent-deep); background: var(--accent-soft); padding: 1px 9px; border-radius: 999px; flex: none; }
.cv-projects p { color: var(--ink-2); font-size: var(--step--1); line-height: 1.8; }

/* ══════════════════════════════════════════════════════════════════════════
   16 · CONTACT
   ══════════════════════════════════════════════════════════════════════════ */
.contact-grid { display: grid; gap: clamp(1.5rem, 1rem + 3vw, 3.5rem); grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr); align-items: start; }
@media (max-width: 900px) { .contact-grid { grid-template-columns: minmax(0, 1fr); } }
.side-h { display: flex; align-items: center; gap: 10px; font-size: var(--step-1); margin-bottom: 16px; }
.side-h .block-ico { width: 34px; height: 34px; border-radius: 11px; }
.side-h .block-ico svg { width: 17px; height: 17px; }

.channels { display: grid; gap: 10px; list-style: none; }
.channel {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 12px 12px 14px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-1);
  transition: border-color .25s, transform .4s var(--spring), box-shadow .3s;
}
.channel:hover { border-color: rgba(var(--accent-rgb), .95); transform: translateY(-2px); box-shadow: var(--shadow-2); }
.channel-ico {
  width: 42px; height: 42px; flex: none; border-radius: 13px; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-deep); border: 1px solid rgba(var(--accent-rgb), .55);
  transition: rotate .45s var(--spring);
}
.channel:hover .channel-ico { rotate: -10deg; }
.channel-ico svg { width: 20px; height: 20px; }
.channel-txt { flex: 1; min-width: 0; }
.channel-txt b { display: block; font-size: var(--step--1); font-weight: 800; line-height: 1.4; }
.channel-txt span { display: block; font-family: var(--mono); font-size: 12px; color: var(--mute); direction: ltr; text-align: start; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body[dir="rtl"] .channel-txt span { text-align: end; }

.card-link {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 14px; margin-top: 14px;
  padding: 14px 16px; border-radius: var(--r);
  background: linear-gradient(120deg, var(--accent-soft), var(--accent-tint)); color: var(--ink);
  border: 1px dashed rgba(var(--accent-rgb), .95);
  transition: transform .4s var(--spring), box-shadow .3s;
}
.card-link:hover { color: var(--ink); transform: translateY(-2px); box-shadow: var(--glow); }
.card-link-qr { width: 48px; height: 48px; flex: none; border-radius: 14px; display: grid; place-items: center; background: var(--surface); color: var(--accent-deep); box-shadow: var(--shadow-1); transition: rotate .5s var(--spring); }
.card-link:hover .card-link-qr { rotate: 12deg; }
.card-link-qr svg { width: 24px; height: 24px; }
.card-link b { display: block; font-weight: 800; }
.card-link small { display: block; color: var(--ink-2); font-size: 12.5px; }
.card-link > svg { width: 18px; height: 18px; margin-inline-start: auto; color: var(--accent-deep); transition: translate .3s var(--spring); }
.card-link:hover > .fwd { translate: -4px 0; }
body[dir="ltr"] .card-link:hover > .fwd { translate: 4px 0; }

.form {
  position: relative; display: grid; gap: 16px; padding: var(--pad); border-radius: var(--r-xl);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-2);
}
/* The honeypot is invisible and inside the form's own box. It used to sit at
   left: -9999px, which in RTL is scrollable overflow: the whole Persian
   contact page opened scrolled 1100px sideways. */
.hp { position: absolute; inset-block-start: 0; inset-inline-start: 0; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); opacity: 0; pointer-events: none; }
.field { display: grid; gap: 7px; align-content: start; }
.field label { font-size: var(--step--1); font-weight: 700; color: var(--ink-2); }
.control { position: relative; }
.control > svg {
  position: absolute; inset-inline-start: 14px; top: 14px; width: 18px; height: 18px;
  color: var(--mute); pointer-events: none; transition: color .2s, scale .3s var(--spring);
}
.field input, .field textarea {
  font: inherit; font-size: var(--step-0); color: var(--ink);
  /* a real border, not a transparent one: a field whose edge you cannot see
     is a field people do not know is a field */
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 14px; padding: 12px 14px; padding-inline-start: 44px; width: 100%;
  transition: border-color .2s, background-color .2s, box-shadow .25s;
}
/* An address or a number is typed LTR inside the Persian page: its own start is
   the left, but the icon is on the right, so the text must stop short of it. */
body[dir="rtl"] .field input[dir="ltr"] { padding-inline-end: 44px; }
.field textarea { resize: vertical; min-height: 160px; line-height: 1.85; padding-inline-start: 14px; }
.field input::placeholder, .field textarea::placeholder { color: var(--mute); }
.field input:hover, .field textarea:hover { border-color: rgba(var(--accent-rgb), .8); }
.field input:focus, .field textarea:focus {
  outline: none; border-color: var(--accent-strong); background: var(--surface);
  box-shadow: 0 0 0 4px rgba(var(--accent-rgb), .35);
}
.control:focus-within > svg { color: var(--accent-strong); scale: 1.12; }
.field-foot { display: flex; justify-content: space-between; gap: 12px; min-height: 18px; }
.field-err { font-size: 12.5px; font-weight: 700; color: var(--peach-deep); }
.field:has(.field-err) input, .field:has(.field-err) textarea { border-color: var(--peach-strong); background: var(--peach-tint); }
.counter { margin-inline-start: auto; font-family: var(--mono); font-size: 11px; color: var(--mute); direction: ltr; transition: color .2s; }
.counter.is-near { color: var(--peach-strong); font-weight: 500; }
.row-2 { display: grid; gap: 16px; grid-template-columns: 1fr 1fr; }
@media (max-width: 560px) { .row-2 { grid-template-columns: minmax(0, 1fr); } }
.field-opt { font-size: 11.5px; font-weight: 500; color: var(--mute); margin-inline-start: 4px; }
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] { border-color: var(--peach-strong); background: var(--peach-tint); }
/* Email + phone: one rule over two fields, so one box, one hint, one error.
   The hint turns to a tick the moment either field has something in it — the
   reader sees the requirement is met without being told twice. */
.reach {
  margin: 0; min-width: 0; display: grid; gap: 12px;
  padding: 14px 16px 16px; border: 1px dashed rgba(var(--accent-rgb), .9);
  border-radius: 18px; background: rgba(var(--accent-rgb), .08);
  transition: border-color .25s, background-color .25s;
}
.reach legend { float: inline-start; width: 100%; padding: 0; font-size: var(--step--1); font-weight: 800; color: var(--ink); }
.reach legend + * { clear: both; }
.reach-hint { display: flex; align-items: center; gap: 7px; margin: -4px 0 0; font-size: 12.5px; color: var(--ink-2); }
.reach-hint svg { flex: none; width: 15px; height: 15px; color: var(--accent-deep); transition: color .2s; }
.reach:has(input:not(:placeholder-shown)) { border-style: solid; }
.reach-ok { display: none; }
.reach:has(input:not(:placeholder-shown)) .reach-ok { display: block; color: var(--mint-deep); }
.reach:has(input:not(:placeholder-shown)) .reach-todo { display: none; }
.reach.is-invalid { border-style: solid; border-color: var(--peach-strong); background: var(--peach-tint); }
.reach.is-invalid input { border-color: var(--peach-strong); }
.reach-err { margin: 0; }
.form-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding-top: 4px; }

/* ══════════════════════════════════════════════════════════════════════════
   17 · THE BUSINESS CARD
   ══════════════════════════════════════════════════════════════════════════ */
.vcard-stage { position: relative; isolation: isolate; }
.vcard-stage .hero-aurora { inset-block-end: 0; }
.vcard-wrap { display: grid; place-items: center; padding-block: clamp(2rem, 1rem + 4vw, 4.5rem); gap: 24px; }
.vcard {
  position: relative; overflow: hidden;
  width: min(100%, 420px); padding: clamp(1.4rem, 1rem + 2vw, 2.1rem);
  border-radius: var(--r-xl); background: var(--surface);
  border: 1px solid var(--line); box-shadow: var(--shadow-3);
  display: grid; gap: 20px;
  transform: perspective(1100px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform .6s var(--ease);
}
.vcard.is-tilting { transition-duration: .1s; }
.vcard::before {
  content: ""; position: absolute; inset-inline: 0; top: 0; height: 128px;
  background: linear-gradient(120deg, var(--mint-soft), var(--sky-soft) 35%, var(--lilac-soft) 65%, var(--peach-soft));
}
/* the sheen: a soft light that follows the pointer across the card */
.vcard-sheen {
  position: absolute; inset: 0; pointer-events: none; z-index: 3; opacity: 0;
  background: radial-gradient(320px circle at var(--gx, 50%) var(--gy, 50%), var(--shine), transparent 55%);
  mix-blend-mode: soft-light; transition: opacity .4s;
}
.vcard.is-tilting .vcard-sheen { opacity: 1; }
.vcard > *:not(.vcard-sheen) { position: relative; }
.vcard-top { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 16px; align-items: end; padding-top: 28px; }
.vcard-face {
  width: 96px; height: 96px; border-radius: 30px; overflow: hidden;
  border: 4px solid var(--surface); box-shadow: var(--shadow-2);
  background: var(--mint-soft); display: grid; place-items: center;
}
.vcard-face img { width: 100%; height: 100%; object-fit: cover; }
.vcard-face span { font-family: var(--display); font-size: 34px; color: var(--mint-deep); direction: ltr; }
.vcard h1 { font-size: var(--step-2); }
.vcard-role { color: var(--mint-deep); font-weight: 700; font-size: var(--step--1); line-height: 1.6; margin-top: 4px; }
.vcard-loc { display: flex; align-items: center; gap: 6px; color: var(--mute); font-size: 12.5px; font-weight: 600; margin-top: 4px; }
.vcard-loc svg { width: 14px; height: 14px; color: var(--peach-strong); flex: none; }
.vcard-qr-wrap { display: grid; justify-items: center; gap: 10px; padding: 18px; border-radius: var(--r-lg); background: var(--surface-2); border: 1px dashed var(--line); }
.vcard-qr {
  width: 172px; height: 172px; padding: 12px; border-radius: var(--r);
  background: var(--qr-plate); color: var(--qr-ink); box-shadow: var(--shadow-1);
  transition: scale .4s var(--spring);
}
.vcard-qr:hover { scale: 1.04; }
.vcard-qr svg { width: 100%; height: 100%; }
.vcard-scan { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 700; color: var(--mute); }
.vcard-scan svg { width: 14px; height: 14px; }
.vcard-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@media (max-width: 400px) { .vcard-actions { grid-template-columns: minmax(0, 1fr); } }
.vcard-actions .btn { white-space: normal; }
.vcard-links { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.vcard-links .dock-btn { border: 1px solid var(--line); background: var(--surface-2); }

/* ══════════════════════════════════════════════════════════════════════════
   17b · SERVICES — the promise cards on /services/ and the home band
   ══════════════════════════════════════════════════════════════════════════ */
.offer-grid { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); list-style: none; }
.offer-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: 10px;
  padding: var(--pad); border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-1);
  transition: border-color .3s, box-shadow .35s var(--ease), transform .45s var(--spring);
}
.offer-card:hover { transform: translateY(-4px); border-color: rgba(var(--accent-rgb), .95); box-shadow: var(--shadow-2), var(--glow); }
.offer-ico {
  width: 46px; height: 46px; border-radius: 15px; flex: none; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-deep); border: 1px solid rgba(var(--accent-rgb), .55);
  transition: rotate .5s var(--spring);
}
.offer-ico svg { width: 22px; height: 22px; }
.offer-card:hover .offer-ico { rotate: -8deg; }
.offer-card h3 { font-size: var(--step-1); margin-top: 4px; }
.offer-card p { color: var(--ink-2); font-size: var(--step--1); line-height: 1.9; }
.offer-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }

/* the link under a post to where it was first published */
.post-original { margin-top: 36px; }
.post-original small { margin-bottom: 2px; }

/* an article's publication facts, its PDF / publisher buttons and its abstract */
.article-facts { display: grid; gap: 8px; margin-top: 20px; font-size: var(--step--1); }
.article-facts > div { display: flex; flex-wrap: wrap; gap: 4px 12px; }
.article-facts dt { color: var(--ink-2); min-width: 7.5em; }
.article-facts dd { color: var(--ink); font-weight: 600; }
.article-facts a { color: var(--accent-strong); }
.article-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 22px; }
.article-abstract {
  margin-bottom: 32px; padding: 18px 20px; border-radius: var(--r);
  background: var(--accent-tint); border: 1px solid rgba(var(--accent-rgb), .55);
  border-inline-start: 4px solid var(--accent);
}
.article-abstract .eyebrow { display: block; margin-bottom: 8px; }
.article-abstract p { line-height: 1.95; }

/* ══════════════════════════════════════════════════════════════════════════
   18 · CTA + FOOTER
   ══════════════════════════════════════════════════════════════════════════ */
.cta {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; align-items: center; justify-content: space-between; gap: 24px 32px; flex-wrap: wrap;
  padding: clamp(1.8rem, 1.2rem + 3vw, 3.4rem); border-radius: var(--r-xl);
  background: linear-gradient(125deg, var(--accent-soft), var(--surface) 55%, var(--lilac-soft));
  border: 1px solid rgba(var(--accent-rgb), .6);
  box-shadow: var(--shadow-2);
}
.cta-art { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.cta-art i { position: absolute; border-radius: 50%; }
.cta-art i:nth-child(1) { width: 220px; height: 220px; inset-inline-end: -60px; top: -80px; background: rgba(var(--peach-rgb), .45); animation: bob 9s ease-in-out infinite; }
.cta-art i:nth-child(2) { width: 140px; height: 140px; inset-inline-end: 22%; bottom: -70px; background: rgba(var(--sky-rgb), .4); animation: bob 7s ease-in-out -2s infinite; }
.cta-art i:nth-child(3) { width: 60px; height: 60px; inset-inline-start: 46%; top: 16%; border: 6px solid rgba(var(--mint-rgb), .7); animation: bob 8s ease-in-out -4s infinite; }
.cta-copy { max-width: 56ch; }
.cta h2 { font-size: var(--step-3); }
.cta p { color: var(--ink-2); margin-top: 10px; font-size: var(--step-1); }
.cta-actions { display: flex; flex-wrap: wrap; gap: 10px; }

.ftr {
  position: relative; margin-top: var(--sec);
  background-color: var(--bg-inset); background-image: var(--dots); background-size: 22px 22px;
  border-top: 1px solid var(--line);
}
.ftr::before {
  content: ""; position: absolute; inset-inline: 0; top: -1px; height: 3px;
  background: linear-gradient(90deg, var(--mint), var(--sky), var(--lilac), var(--peach));
}
.ftr-top { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 2fr); gap: 36px; padding-block: clamp(2.4rem, 2rem + 2vw, 3.6rem) 28px; }
@media (max-width: 860px) { .ftr-top { grid-template-columns: minmax(0, 1fr); } }
.ftr-brand { display: grid; gap: 14px; align-content: start; justify-items: start; }
.ftr-brand p { color: var(--ink-2); font-size: var(--step--1); max-width: 40ch; }
.ftr-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
@media (max-width: 560px) { .ftr-cols { grid-template-columns: 1fr 1fr; } }
.ftr-col h2 { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 800; color: var(--accent-deep); margin-bottom: 12px; }
.ftr-col h2::before { content: ""; width: 8px; height: 8px; border-radius: 2px; rotate: 45deg; background: var(--accent); }
.ftr-col ul { list-style: none; display: grid; gap: 4px; }
.ftr-col a {
  display: inline-flex; align-items: center; gap: 8px; padding: 3px 0;
  color: var(--ink-2); font-size: var(--step--1); font-weight: 500;
  transition: color .2s, translate .3s var(--spring);
}
.ftr-col a svg { width: 15px; height: 15px; color: var(--mute); transition: color .2s; }
.ftr-col a:hover { color: var(--accent-deep); translate: -3px 0; }
body[dir="ltr"] .ftr-col a:hover { translate: 3px 0; }
.ftr-col a:hover svg { color: var(--accent-strong); }
.ftr-bottom {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 24px;
  padding-block: 18px 26px; border-top: 1px dashed var(--line);
}
.ftr-bottom small { color: var(--mute); font-size: 12.5px; }
.ftr-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ftr-meta a, .ftr-meta button {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600; color: var(--ink-2); background: var(--surface); border: 1px solid var(--line); cursor: pointer;
  transition: border-color .2s, color .2s, transform .3s var(--spring);
}
.ftr-meta svg { width: 14px; height: 14px; }
.ftr-meta a:hover, .ftr-meta button:hover { color: var(--accent-deep); border-color: var(--accent); transform: translateY(-2px); }

/* ══════════════════════════════════════════════════════════════════════════
   19 · COMMAND PALETTE, TOAST, TOOLTIP, BACK TO TOP
   ══════════════════════════════════════════════════════════════════════════ */
.cmdk { position: fixed; inset: 0; z-index: 200; display: grid; place-items: start center; padding: 12vh 1rem 1rem; }
.cmdk[hidden] { display: none; }
.cmdk-scrim { position: absolute; inset: 0; background: var(--scrim); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); animation: fade .25s var(--ease); }
.cmdk-panel {
  position: relative; width: min(100%, 600px); overflow: hidden;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-3);
  animation: cmdIn .35s var(--spring);
}
.cmdk-panel::before { content: ""; position: absolute; inset-inline: 0; top: 0; height: 3px; background: linear-gradient(90deg, var(--mint), var(--sky), var(--lilac), var(--peach)); }
.cmdk.is-closing .cmdk-panel { animation: cmdOut .16s var(--ease) forwards; }
.cmdk.is-closing .cmdk-scrim { animation: fade .16s var(--ease) reverse forwards; }
@keyframes cmdIn { from { opacity: 0; translate: 0 -14px; scale: .97; } }
@keyframes cmdOut { to { opacity: 0; translate: 0 -8px; scale: .98; } }
@keyframes fade { from { opacity: 0; } }
.cmdk-search { display: flex; align-items: center; gap: 12px; padding: 6px 18px; border-bottom: 1px solid var(--line); }
.cmdk-search > svg { width: 20px; height: 20px; color: var(--mute); flex: none; }
.cmdk-input { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--ink); font: inherit; font-size: var(--step-1); padding: 14px 0; }
.cmdk-input:focus { outline: none; box-shadow: none; }
.cmdk-list { max-height: min(56vh, 420px); overflow-y: auto; padding: 8px; overscroll-behavior: contain; }
.cmdk-group { padding: 10px 12px 6px; font-size: 11.5px; font-weight: 800; color: var(--mute); }
.cmdk-item {
  display: flex; align-items: center; gap: 12px; padding: 9px 12px;
  border-radius: 12px; color: var(--ink-2); font-size: var(--step--1); font-weight: 600; cursor: pointer;
}
.cmdk-item .ci { width: 32px; height: 32px; border-radius: 10px; display: grid; place-items: center; flex: none; background: var(--surface-2); border: 1px solid var(--line); color: var(--mute); transition: all .2s; }
.cmdk-item .ci svg { width: 16px; height: 16px; }
.cmdk-item .ct { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmdk-item mark { background: var(--peach-soft); color: var(--peach-deep); border-radius: 4px; padding-inline: 1px; }
.cmdk-item .go { width: 16px; height: 16px; opacity: 0; color: var(--accent-deep); transition: opacity .2s, translate .25s var(--spring); }
.cmdk-item.is-on { background: var(--accent-soft); color: var(--accent-deep); }
.cmdk-item.is-on .ci { background: var(--accent); border-color: transparent; color: var(--on-accent); }
.cmdk-item.is-on .go { opacity: 1; translate: -3px 0; }
body[dir="ltr"] .cmdk-item.is-on .go { translate: 3px 0; }
.cmdk-empty { padding: 36px; text-align: center; color: var(--mute); font-size: var(--step--1); }
.cmdk-foot { display: flex; flex-wrap: wrap; gap: 6px 18px; padding: 10px 18px; border-top: 1px solid var(--line); background: var(--surface-2); color: var(--mute); font-size: 12px; }
.cmdk-foot span { display: inline-flex; align-items: center; gap: 5px; }
@media (hover: none) { .cmdk-foot { display: none; } }

.toast {
  position: fixed; inset-block-end: 26px; inset-inline: 0; margin-inline: auto;
  width: max-content; max-width: calc(100% - 2rem); z-index: 300;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px 10px 12px; border-radius: 999px;
  background: var(--tip-bg); color: var(--tip-ink);
  font-size: var(--step--1); font-weight: 700;
  box-shadow: var(--shadow-3);
  animation: toastIn .45s var(--spring);
}
body[dir="rtl"] .toast { padding: 10px 12px 10px 18px; }
.toast-ico { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: var(--mint); color: var(--on-accent); }
.toast-ico svg { width: 14px; height: 14px; }
.toast.is-leaving { animation: toastOut .25s var(--ease) forwards; }
@keyframes toastIn { from { opacity: 0; translate: 0 20px; scale: .9; } }
@keyframes toastOut { to { opacity: 0; translate: 0 12px; } }

/* Placed by app.js in viewport pixels (getBoundingClientRect), so `left` and
   `top` are physical on purpose. --ax is where the arrow sits. */
.tip {
  position: fixed; left: 0; top: 0; z-index: 400;
  max-width: min(280px, calc(100vw - 16px)); padding: 7px 12px; border-radius: 10px;
  background: var(--tip-bg); color: var(--tip-ink);
  font-size: 12.5px; font-weight: 600; line-height: 1.5; text-align: center;
  box-shadow: var(--shadow-2); pointer-events: none;
  opacity: 0; translate: 0 5px; scale: .94;
  transition: opacity .16s ease, translate .3s var(--spring), scale .3s var(--spring);
}
.tip[data-place="bottom"] { translate: 0 -5px; }
.tip.is-on { opacity: 1; translate: 0 0; scale: 1; }
.tip::after {
  content: ""; position: absolute; left: var(--ax, 50%); width: 10px; height: 10px; margin-left: -5px;
  background: inherit; border-radius: 2px; rotate: 45deg; bottom: -4px;
}
.tip[data-place="bottom"]::after { bottom: auto; top: -4px; }

.to-top {
  position: fixed; z-index: 50; inset-block-end: 22px; inset-inline-end: 22px;
  width: 50px; height: 50px; border-radius: 50%; border: 0; padding: 0; cursor: pointer;
  display: grid; place-items: center; color: var(--ink);
  background: var(--glass); box-shadow: var(--shadow-2);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  opacity: 0; scale: .6; pointer-events: none;
  transition: opacity .3s, scale .45s var(--spring), translate .3s var(--spring);
}
.to-top.is-on { opacity: 1; scale: 1; pointer-events: auto; }
.to-top:hover { translate: 0 -3px; color: var(--mint-deep); }
.to-top > svg:not(.to-top-ring) { width: 20px; height: 20px; position: relative; }
.to-top-ring { position: absolute; inset: 0; width: 100%; height: 100%; rotate: -90deg; }
.to-top-ring circle { fill: none; stroke-width: 3; }
.to-top-ring .track { stroke: var(--line); }
.to-top-ring .bar { stroke: var(--mint); stroke-linecap: round; stroke-dasharray: 138.2; stroke-dashoffset: 138.2; }
@media (max-width: 620px) { .to-top { inset-block-end: 14px; inset-inline-end: 14px; width: 44px; height: 44px; } }

/* ══════════════════════════════════════════════════════════════════════════
   20 · SPOTLIGHT, REVEAL, LOAD-IN
   ══════════════════════════════════════════════════════════════════════════ */
/* A soft light that follows the pointer inside a card. `isolation: isolate`
   plus z-index -1 puts it above the card's own background and below its
   content, so it tints the surface without washing over the text. */
[data-spot] { isolation: isolate; }
[data-spot]::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; border-radius: inherit;
  background: radial-gradient(380px circle at var(--mx, 50%) var(--my, 50%), rgba(var(--accent-rgb), .26), transparent 60%);
  opacity: 0; transition: opacity .35s;
}
[data-spot]:hover::after { opacity: 1; }

@keyframes rise { from { opacity: 0; translate: 0 18px; } to { opacity: 1; translate: 0 0; } }

/* Everything is visible at rest; this only softens the arrival. The hidden
   state exists only while .js is on the root and motion is allowed, and the
   arrival is an ANIMATION rather than a transition — so a card's own hover
   transitions are never delayed or overridden by it. */
@media (prefers-reduced-motion: no-preference) {
  /* the backdrop photo develops in, like a print in the tray */
  .photo-wash:not(.photo-lit) { animation: washIn 1.6s var(--ease) both; }
  @keyframes washIn { from { opacity: 0; scale: 1.04; } }
  .js .reveal { opacity: 0; }
  .js .reveal.is-in { animation: rise .8s var(--ease) var(--d, 0ms) both; }
  .js .reveal:not(.is-in) .sec-title::after, .js .sec-head.reveal:not(.is-in) .sec-title::after { scale: .15 1; }

  .hero-copy > *, .hero-visual { animation: rise .9s var(--ease) both; }
  .hero-copy > :nth-child(2) { animation-delay: .06s; }
  .hero-copy > :nth-child(3) { animation-delay: .12s; }
  .hero-copy > :nth-child(4) { animation-delay: .18s; }
  .hero-copy > :nth-child(5) { animation-delay: .24s; }
  .hero-copy > :nth-child(6) { animation-delay: .3s; }
  .hero-visual { animation-delay: .2s; }
  .scribble::after { transform-origin: left; animation: ruleDraw .9s .45s var(--ease) both; }
  body[dir="rtl"] .scribble::after { transform-origin: right; }
  .scribble::before { animation: ruleSweep 1.6s 1.1s var(--ease) both; }
  body[dir="rtl"] .scribble::before { animation-name: ruleSweepRtl; }
  .hero-aurora i { animation: drift 22s ease-in-out infinite alternate; }
  .hero-aurora i:nth-child(2) { animation-duration: 26s; animation-delay: -6s; }
  .hero-aurora i:nth-child(3) { animation-duration: 30s; animation-delay: -12s; }
  .hero-aurora i:nth-child(4) { animation-duration: 24s; animation-delay: -3s; }
  .tl-item.reveal.is-in .tl-dot { animation: popIn .6s var(--spring) calc(var(--d, 0ms) + .2s) both; }

  .ambient-field i:nth-child(1) { animation: amb1 22s ease-in-out infinite alternate; }
  .ambient-field i:nth-child(2) { animation: amb2 28s ease-in-out -9s infinite alternate; }
  .ambient-field i:nth-child(3) { animation: amb3 32s ease-in-out -17s infinite alternate; }
  .ambient-field i:nth-child(4) { animation: amb4 25s ease-in-out -5s infinite alternate; }
  @supports (animation-timeline: scroll()) {
    .ambient-field { animation: ambTurn linear both; animation-timeline: scroll(root); }
  }
}
@keyframes ruleDraw { from { scale: 0 1; } }
/* the bar is 22% of the rule, so 355% of its own width is the far end */
@keyframes ruleSweep {
  0%   { opacity: 0; translate: 0 0; }
  12%  { opacity: 1; }
  55%  { translate: 355% 0; }
  100% { opacity: 1; translate: 0 0; }
}
@keyframes ruleSweepRtl {
  0%   { opacity: 0; translate: 0 0; }
  12%  { opacity: 1; }
  55%  { translate: -355% 0; }
  100% { opacity: 1; translate: 0 0; }
}
@keyframes drift { to { translate: 6vmax 4vmax; scale: 1.12; } }
@keyframes amb1 { 50% { translate: 14vmax 8vmax; scale: 1.15; } 100% { translate: 4vmax 18vmax; scale: .9; } }
@keyframes amb2 { 50% { translate: -12vmax 12vmax; scale: .88; } 100% { translate: -20vmax -4vmax; scale: 1.1; } }
@keyframes amb3 { 50% { translate: 10vmax -14vmax; scale: 1.18; } 100% { translate: -8vmax -6vmax; scale: .95; } }
@keyframes amb4 { 50% { translate: 16vmax -8vmax; scale: .9; } 100% { translate: 6vmax -18vmax; scale: 1.12; } }
@keyframes ambTurn { to { rotate: 70deg; scale: 1.1; } }

/* Phones and tablets: the same page, a lighter engine. Everything below is
   paint a small GPU pays for every frame — the drifting lights and their
   scroll-driven turn (layers bigger than the screen), the canvas mask, the
   blurred halo turning, and frosted glass on chips that bob. The look stays;
   the lights and the halo simply hold still, and the glass becomes a fill. */
@media (hover: none), (max-width: 700px) {
  .ambient-field, .ambient-field i { animation: none !important; will-change: auto; }
  .ambient-net { -webkit-mask-image: none; mask-image: none; }
  .portrait-ring { animation: none; }
  .float-chip, .portrait-dock { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--surface); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .marquee-track { width: auto; flex-wrap: wrap; justify-content: center; }
  .marquee-list[aria-hidden="true"] { display: none; }
  .marquee-list { flex-wrap: wrap; justify-content: center; }
}

/* ══════════════════════════════════════════════════════════════════════════
   21 · ERROR PAGE
   ══════════════════════════════════════════════════════════════════════════ */
.err-page { position: relative; isolation: isolate; }
.err-wrap { display: grid; place-items: center; text-align: center; gap: 16px; padding-block: clamp(4rem, 3rem + 6vw, 8rem); }
.err-code {
  font-family: var(--display); font-size: clamp(5rem, 3rem + 10vw, 10rem); font-weight: 700;
  line-height: .9; direction: ltr; letter-spacing: -.05em;
  background: linear-gradient(120deg, var(--mint-strong), var(--sky-strong), var(--lilac-strong), var(--peach-strong));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: bob 5s ease-in-out infinite;
}
.err-wrap h1 { font-size: var(--step-3); }
.err-wrap p { color: var(--ink-2); max-width: 44ch; }
.err-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 8px; }

/* ══════════════════════════════════════════════════════════════════════════
   22 · PRINT — the résumé is a real document
   ══════════════════════════════════════════════════════════════════════════ */
@media print {
  @page { margin: 14mm 12mm; }
  .hdr, .ftr, .no-print, .cmdk, .toast, .tip, .to-top, .hero-aurora, .ambient, .marquee, .cta, .photo-wash { display: none !important; }
  body { background: #fff; color: #000; font-size: 10pt; line-height: 1.5; }
  .shell, .narrow { width: 100%; }
  .js .reveal { opacity: 1 !important; animation: none !important; }
  *, *::before, *::after { box-shadow: none !important; }
  .page-head::before, .sec-title::after, .timeline::before, .tl-dot, .cv-hero::before, [data-spot]::after { display: none !important; }
  .sec-band { background: none !important; border: 0 !important; }
  .page-head { padding-block: 0 8pt; }
  .cv-hero { border: 0; padding: 0; grid-template-columns: auto 1fr; }
  .cv-grid { grid-template-columns: 58mm 1fr; gap: 8mm; padding-block: 8pt 0; }
  .cv-main { order: 0; gap: 12pt; }
  .cv-block, .tl-card, .cv-projects a, .cv-intro { border: 1px solid #ddd !important; background: #fff !important; padding: 8pt; border-radius: 6pt; }
  .tl-item { padding-inline-start: 0; break-inside: avoid; }
  .tl-desc { margin-top: 6pt; padding-top: 6pt; }
  .timeline { gap: 8pt; }
  .cv-title { font-size: 13pt; margin-bottom: 6pt; }
  .block-ico, .ci, .fact-ico { display: none !important; }
  .cv-contact li { grid-template-columns: minmax(0, 1fr); }
  a { color: #000; text-decoration: none; }
}
