/* ============================================================
   SILENT PIXEL — Design System
   Crimson Depth + Warm Sand on Obsidian. Dark and light.
   ============================================================ */

/* ---------- 1. TOKENS ---------- */
/* Brand constants — identical in both themes. The palette is deliberately
   narrow: one crimson, one copper, one sand, two neutrals. Everything else
   in the build is a tint, an alpha or a channel of these. */
:root {
  /* Crimson Depth is the anchor, but at #710014 it carries almost no
     luminance, so on obsidian it cannot draw hairlines or small text.
     --crimson-lit is the same hue lifted enough to survive there; the deep
     original owns the light theme, where it is at its best. */
  --crimson:     #710014;
  --crimson-mid: #A3122A;
  --crimson-lit: #C0182E;
  --copper:      #9C5432;   /* the bridge from crimson into sand */
  --sand:        #C9A57B;   /* Warm Sand */
  --sand-pale:   #E2CBA9;
  --pearl:       #F2F1ED;   /* Soft Pearl */
  --oil:         #0B0B0B;   /* oil black — sits below Obsidian Black */
  --ink-k:       #161616;   /* Obsidian Black */

  --crimson-rgb: 113,0,20;
  --copper-rgb:  156,84,50;
  --sand-rgb:    201,165,123;

  /* Vermilion, not red: an error next to Crimson Depth has to read as a
     warning rather than as more branding. Channel form only — the invalid
     state paints a tinted border and fill, never solid. */
  --err-rgb: 228,87,46;

  /* The primary button is theme-independent — a deep crimson pill with pearl
     type. Held constant because the panning brand gradient would otherwise
     sweep Warm Sand under the label, and neither dark nor pearl type stays
     legible across that whole sweep. */
  --grad-btn: linear-gradient(96deg, #5E0C16 0%, var(--crimson-mid) 42%, #8E3A1E 74%, #5E0C16 100%);
  --on-btn:   var(--pearl);

  /* MEDIA SURFACES — photographs and the procedural work plates. Dark in
     BOTH themes on purpose; see the module docstring. */
  --plate-1:       #241F1C;
  --plate-2:       #131110;
  --on-media:      #F7F6F3;
  --media-rgb:     8,7,7;
  --media-ink-rgb: 247,246,243;
  --media-brd:     rgba(247,246,243,.16);
  --media-brd-2:   rgba(247,246,243,.28);

  /* Type */
  --f-display: "Bricolage Grotesque", "Archivo Expanded", ui-sans-serif, sans-serif;
  --f-body:    "Sora", ui-sans-serif, system-ui, sans-serif;
  --f-mono:    "JetBrains Mono", ui-monospace, monospace;

  --t-hero:  clamp(3.1rem, 11.5vw, 12.5rem);
  --t-h1:    clamp(2.5rem, 6.6vw, 6.1rem);
  --t-h2:    clamp(2rem, 4.6vw, 4.05rem);
  --t-h3:    clamp(1.4rem, 2.3vw, 2.1rem);
  --t-h4:    clamp(1.1rem, 1.5vw, 1.4rem);
  --t-body:  clamp(.96rem, 1.06vw, 1.09rem);
  --t-sm:    .855rem;
  --t-xs:    .715rem;

  /* Space */
  --gut:     clamp(1.15rem, 4.2vw, 4.5rem);
  --sec-y:   clamp(5.5rem, 13vh, 11rem);
  --max:     1560px;
  --max-txt: 68ch;

  /* Motion */
  --e-out:  cubic-bezier(.16, 1, .3, 1);
  --e-io:   cubic-bezier(.72, 0, .22, 1);
  --e-soft: cubic-bezier(.32, .72, 0, 1);

  --r-sm: 6px;
  --r-md: 14px;
  --r-lg: 22px;
  --r-xl: 34px;

  --nav-h: 76px;
  --glass-blur: 22px;
}

/* ---------- 1a. DARK THEME (default) ---------- */
:root,
:root[data-theme="dark"] {
  color-scheme: dark;

  /* Obsidian ramp, warmed. The old ramp was blue-black (#040407); these run
     neutral-to-warm so Warm Sand and copper do not read as contaminated.
     Oil Black is the page ground and Obsidian Black the surface one step up,
     which is the order that gives the cards something to lift away from. */
  --void:      var(--oil);
  --obsidian:  var(--ink-k);
  --slate-900: #1A1918;
  --slate-800: #232221;
  --slate-700: #2C2A28;
  --slate-600: #3A3733;
  --slate-500: #817A70;   /* 4.64:1 on --void — AA for the 10-11px mono meta */
  --slate-400: #8A8379;
  --slate-300: #A9A29A;
  --slate-200: #CFC9BF;
  --bone:      #E6E2D8;   /* bone white */
  --white:     #F7F6F3;

  /* Channel tokens: the whole trick. Every alpha colour in the build resolves
     through one of these four, so "light ink on dark ground" stops being
     hardcoded and becomes two numbers that swap. */
  --ink-rgb:    230,226,216;   /* foreground / hairlines / frost */
  --ground-rgb: 11,11,11;      /* page ground, for scrims and edge fades */
  --card-rgb:   26,25,24;      /* card fill, for gradients fading into a card */
  --surf-rgb:   35,34,33;      /* raised surface (rail buttons, popovers) */
  --shadow-rgb: 0,0,0;

  --accent:      var(--crimson-lit);
  --acc-rgb:     192,24,46;
  --accent-soft: rgba(var(--acc-rgb), .13);
  --accent-line: rgba(var(--acc-rgb), .42);

  --iri-1: var(--crimson-lit);
  --iri-2: var(--crimson);
  --iri-3: var(--copper);
  --iri-4: var(--sand);
  --iri-5: var(--sand-pale);

  /* Gradient headline ramp for the DARK theme. It deliberately does NOT
     start on --crimson: at #710014 the clipped glyphs measured 1.53:1 on the
     obsidian plate (2.9:1 for the brightest painted pixel), i.e. below the
     3.0 large-text floor and visibly murky. Every stop here clears 3.05:1,
     and the ramp still opens on crimson before travelling to sand. Light
     mode keeps true Crimson Depth as its first stop — on pearl that is
     8.76:1, so the constraint only ever bites on the dark side. */
  --grad-iri: linear-gradient(96deg, var(--crimson-lit) 0%, #D0203A 22%, #B8452A 48%, var(--sand) 76%, var(--sand-pale) 100%);
  --grad-iri-soft: linear-gradient(96deg, rgba(var(--crimson-rgb),.44), rgba(var(--copper-rgb),.3) 52%, rgba(var(--sand-rgb),.2));
  --grad-chrome: linear-gradient(180deg, #FFFDF8 0%, #DED3C0 36%, #8A7E6E 52%, #F4F1E9 68%, #A99C88 100%);

  --glass-bg:    rgba(var(--ink-rgb), .038);
  --glass-bg-2:  rgba(var(--ink-rgb), .062);
  --glass-brd:   rgba(var(--ink-rgb), .1);
  --glass-brd-2: rgba(var(--ink-rgb), .19);

  /* Semantic alphas — named for the job, not the colour. */
  --line:      rgba(var(--ink-rgb), .085);
  --line-2:    rgba(var(--ink-rgb), .13);
  --fill-1:    rgba(var(--ink-rgb), .035);
  --fill-2:    rgba(var(--ink-rgb), .055);
  --frost:     rgba(var(--ink-rgb), .016);
  --sheen:     rgba(var(--ink-rgb), .34);
  --grid-line: rgba(var(--ink-rgb), .038);

  /* Scrim lift. Text over a shader needs a much heavier wash on pearl than on
     obsidian: in dark mode the shader is dark and the scrim is dark, so light
     type survives anywhere, but in light mode a mid-tone crimson render sits
     under DARK type. Feeding this into calc() inside the alpha keeps one rule
     per scrim and leaves the dark values numerically untouched (lift = 0). */
  --lift:     0;
  --vig-1:    .42;
  --vig-2:    .78;
  --sh-a:     .9;
  --grain-op: .05;
  --scan-op:  .16;
  --ph-b:     .94;

  /* Fed to the WebGL scenes so the shaders follow the theme.
     Oil-black ramp: near-black body through warm dark-gray sheen, so the
     blob/orb/ribbons read as glossy oil rather than crimson. */
  --gl-base: 0.043 0.043 0.043;
  --gl-c1:   0.030 0.030 0.032;
  --gl-c2:   0.085 0.084 0.088;
  --gl-c3:   0.160 0.160 0.163;
  --gl-c4:   0.300 0.300 0.310;
  --gl-light: 0.0;
}

/* ---------- 1b. LIGHT THEME ---------- */
/* Reachable two ways: the OS preference, or an explicit data-theme on <html>.
   The attribute always wins, so a future toggle needs no CSS change. */
:root[data-theme="light"] {
  color-scheme: light;

  --void:      #F2F1ED;   /* Soft Pearl */
  --obsidian:  #EDEBE5;
  --slate-900: #E7E4DC;
  --slate-800: #DCD8CE;
  --slate-700: #CFCABE;
  --slate-600: #BEB7A9;
  --slate-500: #655F55;
  --slate-400: #5E584E;
  --slate-300: #56504A;
  --slate-200: #3A352F;
  --bone:      #201E1B;
  --white:     #0F0E0D;

  --ink-rgb:    32,30,27;
  --ground-rgb: 242,241,237;
  --card-rgb:   231,228,220;
  --surf-rgb:   252,251,248;
  --shadow-rgb: 74,58,40;

  /* Light mode gets the TRUE Crimson Depth. At 9.6:1 on Soft Pearl it can
     finally carry small text and hairlines — the one thing it cannot do on
     obsidian, where it sits at 1.6:1. */
  --accent:      var(--crimson);
  --acc-rgb:     113,0,20;
  --accent-soft: rgba(var(--acc-rgb), .07);
  --accent-line: rgba(var(--acc-rgb), .34);

  --iri-1: var(--crimson);
  --iri-2: var(--crimson-mid);
  --iri-3: #7E3F22;
  --iri-4: #8A6136;
  --iri-5: var(--copper);

  --grad-iri: linear-gradient(96deg, var(--crimson) 0%, var(--crimson-mid) 26%, #8E3A1E 54%, var(--copper) 78%, #8A6136 100%);
  --grad-iri-soft: linear-gradient(96deg, rgba(var(--crimson-rgb),.15), rgba(var(--copper-rgb),.12) 52%, rgba(var(--sand-rgb),.16));
  --grad-chrome: linear-gradient(180deg, #4A4034 0%, #93856F 34%, #2E2823 52%, #7C6E5A 68%, #3A332B 100%);

  --glass-bg:    rgba(var(--ink-rgb), .032);
  --glass-bg-2:  rgba(var(--ink-rgb), .055);
  --glass-brd:   rgba(var(--ink-rgb), .12);
  --glass-brd-2: rgba(var(--ink-rgb), .2);

  --line:      rgba(var(--ink-rgb), .13);
  --line-2:    rgba(var(--ink-rgb), .2);
  --fill-1:    rgba(var(--ink-rgb), .035);
  --fill-2:    rgba(var(--ink-rgb), .06);
  --frost:     rgba(var(--ink-rgb), .022);
  --sheen:     rgba(255,255,255, .8);
  --grid-line: rgba(var(--ink-rgb), .055);

  /* Pearl is already bright, so the vignette barely closes in and the grain
     lifts slightly — film grain reads as dirt on a light ground if it is as
     heavy as it is on obsidian. */
  --lift:     1;
  --vig-1:    .18;
  --vig-2:    .42;
  --sh-a:     .16;
  --grain-op: .038;
  --scan-op:  .05;
  --ph-b:     .98;

  /* Match the dark-theme shader exactly; only the page chrome remains light. */
  --gl-base: 0.043 0.043 0.043;
  --gl-c1:   0.030 0.030 0.032;
  --gl-c2:   0.085 0.084 0.088;
  --gl-c3:   0.160 0.160 0.163;
  --gl-c4:   0.300 0.300 0.310;
  --gl-light: 0.0;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;

    --void:      #F2F1ED;   /* Soft Pearl */
    --obsidian:  #EDEBE5;
    --slate-900: #E7E4DC;
    --slate-800: #DCD8CE;
    --slate-700: #CFCABE;
    --slate-600: #BEB7A9;
    --slate-500: #655F55;
    --slate-400: #5E584E;
    --slate-300: #56504A;
    --slate-200: #3A352F;
    --bone:      #201E1B;
    --white:     #0F0E0D;

    --ink-rgb:    32,30,27;
    --ground-rgb: 242,241,237;
    --card-rgb:   231,228,220;
    --surf-rgb:   252,251,248;
    --shadow-rgb: 74,58,40;

    /* Light mode gets the TRUE Crimson Depth. At 9.6:1 on Soft Pearl it can
       finally carry small text and hairlines — the one thing it cannot do on
       obsidian, where it sits at 1.6:1. */
    --accent:      var(--crimson);
    --acc-rgb:     113,0,20;
    --accent-soft: rgba(var(--acc-rgb), .07);
    --accent-line: rgba(var(--acc-rgb), .34);

    --iri-1: var(--crimson);
    --iri-2: var(--crimson-mid);
    --iri-3: #7E3F22;
    --iri-4: #8A6136;
    --iri-5: var(--copper);

    --grad-iri: linear-gradient(96deg, var(--crimson) 0%, var(--crimson-mid) 26%, #8E3A1E 54%, var(--copper) 78%, #8A6136 100%);
    --grad-iri-soft: linear-gradient(96deg, rgba(var(--crimson-rgb),.15), rgba(var(--copper-rgb),.12) 52%, rgba(var(--sand-rgb),.16));
    --grad-chrome: linear-gradient(180deg, #4A4034 0%, #93856F 34%, #2E2823 52%, #7C6E5A 68%, #3A332B 100%);

    --glass-bg:    rgba(var(--ink-rgb), .032);
    --glass-bg-2:  rgba(var(--ink-rgb), .055);
    --glass-brd:   rgba(var(--ink-rgb), .12);
    --glass-brd-2: rgba(var(--ink-rgb), .2);

    --line:      rgba(var(--ink-rgb), .13);
    --line-2:    rgba(var(--ink-rgb), .2);
    --fill-1:    rgba(var(--ink-rgb), .035);
    --fill-2:    rgba(var(--ink-rgb), .06);
    --frost:     rgba(var(--ink-rgb), .022);
    --sheen:     rgba(255,255,255, .8);
    --grid-line: rgba(var(--ink-rgb), .055);

    /* Pearl is already bright, so the vignette barely closes in and the grain
       lifts slightly — film grain reads as dirt on a light ground if it is as
       heavy as it is on obsidian. */
    --lift:     1;
    --vig-1:    .18;
    --vig-2:    .42;
    --sh-a:     .16;
    --grain-op: .038;
    --scan-op:  .05;
    --ph-b:     .98;

    /* Oil-black ink on pearl — keep in sync with the [data-theme="light"] block. */
    --gl-base: 0.043 0.043 0.043;
    --gl-c1:   0.030 0.030 0.032;
    --gl-c2:   0.085 0.084 0.088;
    --gl-c3:   0.160 0.160 0.163;
    --gl-c4:   0.300 0.300 0.310;
    --gl-light: 0.0;
  }
}


/* ---------- 2. RESET ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scrollbar-width: none;
  /* The nav is position: fixed, so an #anchor jump would otherwise park the
     target heading underneath it — measured at exactly --nav-h of occlusion
     on #pachete and #proces. scroll-padding-top on the SCROLLING element
     fixes every in-page link and every scrollIntoView at once, so no
     per-section scroll-margin is needed. */
  scroll-padding-top: calc(var(--nav-h) + 1.25rem);
  /* Only the ROOT element's overflow propagates to the viewport — overflow-x on
     body alone still leaves a horizontal scrollbar, which the blurred .aurora
     orbs (right: -8vw) and the 42px [data-rv="right"] entry transform both
     trigger. `clip`, not `hidden`: hidden would turn html into a scroll
     container and break every position: sticky descendant (.nav, .sd-panel). */
  overflow-x: clip;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

body {
  background: var(--void);
  color: var(--bone);
  font-family: var(--f-body);
  font-size: var(--t-body);
  font-weight: 300;
  line-height: 1.62;
  letter-spacing: -.008em;
  overflow-x: hidden;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
body.is-locked { overflow: hidden; }

img, svg, video, canvas { display: block; max-width: 100%; height: auto; }
button, input, textarea, select { font: inherit; color: inherit; background: none; border: none; }
button { cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }

::selection { background: var(--accent); color: var(--pearl); }

:focus-visible {
  outline: 2px solid var(--iri-1);
  outline-offset: 3px;
  border-radius: 3px;
}

html::-webkit-scrollbar { display: none; }

/* ---------- 2b. INTERACTION LAYER ----------
   Everything here is about how the site responds to a finger versus a mouse.
   It changes no layout and no colour token; it only removes the default
   mobile-browser behaviours that make a custom UI feel broken. */

/* 1. Kill the grey flash Chrome/Safari paint over any tapped element. Our
      controls already have their own :active feedback, so the platform
      rectangle only ever fights the design. */
a, button, label, summary, [role="button"], input, textarea, select {
  -webkit-tap-highlight-color: transparent;
}

/* 2. Remove the ~300ms click delay legacy mobile browsers add while they
      wait to see whether a tap becomes a double-tap zoom. `manipulation`
      keeps pan and pinch-zoom (never disable those — pinch is the only
      zoom path a low-vision user has) and drops only double-tap zoom. */
a, button, label, summary, [role="button"] {
  touch-action: manipulation;
}

/* 3. (The 16px minimum that stops iOS force-zooming a focused field lives
      on `.field input/textarea/select` in pages.css, where the field's own
      font-size is declared — putting it here as well would just be an
      override fight with the later, more specific rule.) */

/* 4. Touch feedback. A finger has no hover, so the only way a tap reads as
      "received" is an immediate transform. Kept tiny and fast so it feels
      like pressure, not animation. */
@media (hover: none) {
  .btn:active, .chip:active, .rad:active, .acc-btn:active,
  .tsw:active, .lang button:active, .burger:active,
  .work:active, .rcard:active, .tier:active, .catnav a:active {
    transform: scale(.975);
    transition-duration: .06s;
  }
}

/* 5. Sticky hover. On a touch screen :hover latches after a tap and stays
      lit until you tap elsewhere, so cards keep a "lifted" look at random.
      Neutralise the transform-based lifts where there is no real pointer;
      the :active rules above supply the feedback instead. */
@media (hover: none) {
  /* Exactly the four cards that translate on hover — verified against
     pages.css rather than guessed, so this list contains no dead selectors
     (.pillar, .stat and .sd-steps li change colour only and are fine). */
  .work:hover, .rcard:hover, .tier:hover, .ct-card:hover { transform: none; }
  /* Ken-Burns image zooms latch the same way and leave a card cropped. */
  .work:hover .work-plate,
  .rcard:hover .ph img { transform: none; filter: none; }
  /* The plate badge is hover-revealed on desktop; with no pointer it must
     simply be present, or the category label is never readable at all. */
  .work-badge { opacity: 1; transform: none; }
}

/* 6. The .rail scroller already sets overscroll-behavior-x: contain and
      -webkit-overflow-scrolling: touch at its own definition in pages.css,
      so there is deliberately no duplicate here — and no touch-action
      either. `pan-x` looks right for a horizontal carousel but is a trap:
      it tells the browser this element handles ONLY horizontal panning, so
      a vertical swipe that happens to start on a card scrolls nothing and
      the page feels frozen. The default `auto` is correct — it gives the
      rail horizontal panning and still lets vertical scroll bubble to the
      page, which is exactly the phone-app feel this rail is meant to have. */

/* 7. Text selection is a liability on controls: a long-press on a button
      pops the selection UI instead of acting. Content keeps normal
      selection — only the chrome opts out. */
.btn, .chip, .burger, .tsw, .lang button, .nav-links a, .rail-nav,
.logo, .acc-btn, .work-badge, .tag, .tm-badge {
  -webkit-user-select: none;
  user-select: none;
}

/* 8. Larger, more forgiving focus ring for keyboard users, and make sure a
      focused element is never hidden under the fixed nav. */
:focus-visible { outline-width: 2px; }
.nav-links a:focus-visible, .lang button:focus-visible,
.tsw:focus-visible, .burger:focus-visible { outline-offset: 2px; }

/* 9. Minimum ~44px hit areas on touch.
      Measured undersized at 390px: .lang button 36x27, .tsw 38x38,
      .burger 42x42, .foot-links a 123x23, .chip 113x30.

      An earlier attempt grew each target with a transparent, centred
      ::after. Testing it with elementFromPoint at the four extremes killed
      the idea twice over: a negative z-index parks the pad behind the nav's
      own background so it receives nothing, and a positive one makes the
      pad overlap its neighbour — the footer link literally answered for
      "Web & Aplicații" one row down, and a filter chip answered for "Film".
      An invisible region that steals the adjacent control's tap is worse
      than a small target, because the user gets the WRONG page.

      So these grow for real, in the one axis that has room, and the
      container gaps grow with them so no two targets touch. */
      The nav-cluster half of this (.lang button, .tsw, .burger) canNOT live
      here: those components are defined further down this file, so an
      equal-specificity rule at this point loses to them. Their touch sizes
      sit next to their own definitions instead — see section 11. */
@media (hover: none) {
  /* Footer links are 23px in a .62rem stack: pad to 44 and close the gap so
     the enlarged boxes stay disjoint (verified: no STEALS at +/-21px). */
  .foot-links { gap: .1rem; }
  .foot-links a { padding-block: .62rem; }

  /* Filter chips sit in a wrapping row; give them a full-finger height and
     enough row-gap that a vertical miss lands on nothing, not on the chip
     beneath. */
  .filter-bar { row-gap: .7rem; }
  .chip { min-height: 44px; }
}

/* ---------- 3. TYPOGRAPHY ---------- */
h1, h2, h3, h4, h5 {
  font-family: var(--f-display);
  font-weight: 600;
  line-height: .95;
  letter-spacing: -.038em;
  text-wrap: balance;
}
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); }
h4 { font-size: var(--t-h4); letter-spacing: -.022em; line-height: 1.2; }
p { text-wrap: pretty; }

.display {
  font-family: var(--f-display);
  font-weight: 700;
  line-height: .84;
  letter-spacing: -.052em;
}

.mono {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: .19em;
  text-transform: uppercase;
}

.lede {
  font-size: clamp(1.06rem, 1.55vw, 1.42rem);
  line-height: 1.55;
  font-weight: 300;
  color: var(--slate-200);
  letter-spacing: -.018em;
  max-width: var(--max-txt);
}

.muted   { color: var(--slate-300); }
.muted-2 { color: var(--slate-400); }

/* Iridescent text */
.iri {
  background: var(--grad-iri);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: iri-pan 9s linear infinite;
}
@keyframes iri-pan {
  to { background-position: 220% 0; }
}

.chrome {
  background: var(--grad-chrome);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.outline-txt {
  color: transparent;
  -webkit-text-stroke: 1px var(--slate-500);
}

/* ---------- 4. LAYOUT ---------- */
.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gut);
}
.wrap-narrow { max-width: 1080px; }

section { position: relative; }
.sec { padding-block: var(--sec-y); }
.sec-sm { padding-block: clamp(3.5rem, 8vh, 6.5rem); }

.grid { display: grid; gap: clamp(1rem, 2vw, 1.75rem); }
.g2 { grid-template-columns: repeat(2, 1fr); }
.g3 { grid-template-columns: repeat(3, 1fr); }
.g4 { grid-template-columns: repeat(4, 1fr); }
.g12 { grid-template-columns: repeat(12, 1fr); }

.flex { display: flex; }
.between { justify-content: space-between; }
.center { align-items: center; }
.col { flex-direction: column; }
.wrap-f { flex-wrap: wrap; }

@media (max-width: 1040px) {
  .g4 { grid-template-columns: repeat(2, 1fr); }
  .g3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 680px) {
  .g4, .g3, .g2 { grid-template-columns: 1fr; }
}

/* ---------- 5. ATMOSPHERE ---------- */

/* Film grain */
.grain {
  position: fixed;
  inset: -120%;
  z-index: 9998;
  pointer-events: none;
  opacity: var(--grain-op);
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='260' height='260' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain-shift 7.5s steps(9) infinite;
  will-change: transform;
}
@keyframes grain-shift {
  0%   { transform: translate(0, 0); }
  11%  { transform: translate(-2%, -3%); }
  22%  { transform: translate(-4%, 2%); }
  33%  { transform: translate(2%, -4%); }
  44%  { transform: translate(-1%, 3%); }
  55%  { transform: translate(-3%, 1%); }
  66%  { transform: translate(3%, 2%); }
  77%  { transform: translate(1%, -2%); }
  88%  { transform: translate(-2%, -1%); }
  100% { transform: translate(0, 0); }
}

/* Vignette */
.vignette {
  position: fixed;
  inset: 0;
  z-index: 9997;
  pointer-events: none;
  background: radial-gradient(ellipse 120% 88% at 50% 42%, transparent 34%, rgba(var(--ground-rgb),var(--vig-1)) 78%, rgba(var(--ground-rgb),var(--vig-2)) 100%);
}

/* Scanline */
.scan {
  position: fixed;
  inset: 0;
  z-index: 9996;
  pointer-events: none;
  opacity: var(--scan-op);
  background: repeating-linear-gradient(0deg, rgba(var(--ink-rgb),.03) 0 1px, transparent 1px 3px);
}

/* Grid backdrop */
.bg-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: 88px 88px;
  mask-image: radial-gradient(ellipse 90% 70% at 50% 45%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 45%, #000 20%, transparent 78%);
}

/* Aurora blobs */
.aurora {
  position: absolute;
  border-radius: 50%;
  filter: blur(110px);
  pointer-events: none;
  opacity: .38;
  will-change: transform;
}
.aurora-a {
  width: 46vw; height: 46vw;
  background: radial-gradient(circle, var(--iri-3), transparent 66%);
  top: -14vw; left: -10vw;
  animation: drift-a 26s var(--e-io) infinite;
}
.aurora-b {
  width: 40vw; height: 40vw;
  background: radial-gradient(circle, var(--iri-1), transparent 66%);
  bottom: -14vw; right: -8vw;
  animation: drift-b 32s var(--e-io) infinite;
}
.aurora-c {
  width: 32vw; height: 32vw;
  background: radial-gradient(circle, var(--iri-4), transparent 68%);
  top: 42%; left: 52%;
  opacity: .22;
  animation: drift-a 38s var(--e-io) infinite reverse;
}
@keyframes drift-a {
  0%,100% { transform: translate(0,0) scale(1); }
  33%     { transform: translate(9vw, 7vh) scale(1.16); }
  66%     { transform: translate(-6vw, 12vh) scale(.9); }
}
@keyframes drift-b {
  0%,100% { transform: translate(0,0) scale(1); }
  40%     { transform: translate(-11vw, -9vh) scale(1.2); }
  70%     { transform: translate(5vw, -5vh) scale(.94); }
}

/* Hairline divider */
.hair {
  height: 1px;
  border: 0;
  background: linear-gradient(90deg, transparent, var(--slate-600) 12%, var(--slate-600) 88%, transparent);
}
.hair-iri {
  height: 1px;
  border: 0;
  background: var(--grad-iri);
  opacity: .34;
}

/* ---------- 6. GLASS SURFACES ---------- */
.glass {
  position: relative;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  border-radius: var(--r-lg);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
  overflow: hidden;
}
/* top sheen */
.glass::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--sheen) 50%, transparent);
  opacity: .8;
}

/* Iridescent border via mask */
.brd-iri {
  position: relative;
}
.brd-iri::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: var(--grad-iri);
  background-size: 200% 100%;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity .5s var(--e-out);
  pointer-events: none;
  animation: iri-pan 6s linear infinite;
}
.brd-iri:hover::after, .brd-iri.on::after { opacity: .85; }

/* Spotlight that follows cursor */
.spot { position: relative; }
.spot::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%), rgba(var(--acc-rgb),.16), transparent 62%);
  opacity: 0;
  transition: opacity .45s var(--e-out);
  pointer-events: none;
  z-index: 1;
}
.spot:hover::before { opacity: 1; }

/* ---------- 7. BUTTONS ---------- */
.btn {
  --bh: 3.35rem;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .72em;
  height: var(--bh);
  padding-inline: 1.85rem;
  border-radius: 100px;
  font-family: var(--f-body);
  font-size: .93rem;
  font-weight: 500;
  letter-spacing: -.012em;
  white-space: nowrap;
  overflow: hidden;
  isolation: isolate;
  transition: transform .5s var(--e-out), color .35s, box-shadow .5s var(--e-out), border-color .4s;
  will-change: transform;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0) scale(.985); }

/* Primary — iridescent fill */
.btn-1 {
  color: var(--on-btn);
  font-weight: 600;
  background: var(--grad-btn);
  background-size: 220% 100%;
  animation: iri-pan 8s linear infinite;
  box-shadow: 0 6px 26px -8px rgba(var(--crimson-rgb),.55), inset 0 1px 0 rgba(255,255,255,.28);
}
.btn-1:hover {
  box-shadow: 0 14px 44px -10px rgba(var(--crimson-rgb),.7), inset 0 1px 0 rgba(255,255,255,.36);
}

/* Secondary — glass */
.btn-2 {
  color: var(--bone);
  background: var(--glass-bg-2);
  border: 1px solid var(--glass-brd-2);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.btn-2:hover {
  border-color: var(--accent-line);
  background: rgba(var(--acc-rgb),.1);
  box-shadow: 0 10px 34px -14px rgba(var(--acc-rgb),.34);
}

/* Homepage service CTA: secondary at rest, accent reveal on intent. */
.btn-explore {
  min-width: 17rem;
  font-weight: 600;
}
.btn-explore-fill {
  position: absolute;
  z-index: 0;
  left: 20%;
  top: 50%;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--grad-btn);
  opacity: 0;
  transform: translateY(-50%);
  transition: left .38s var(--e-out), top .38s var(--e-out), width .38s var(--e-out), height .38s var(--e-out), border-radius .38s var(--e-out), opacity .12s ease;
}
.btn-explore-copy {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .72em;
  transition: transform .32s var(--e-out), opacity .22s ease;
}
.btn-explore-active {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: translateX(3rem);
}
.btn-explore:hover,
.btn-explore:focus-visible,
.btn-explore:active {
  color: var(--on-btn);
  border-color: transparent;
  background: var(--glass-bg-2);
  box-shadow: 0 14px 44px -10px rgba(var(--crimson-rgb),.58), inset 0 1px 0 rgba(255,255,255,.26);
}
.btn-explore:hover .btn-explore-fill,
.btn-explore:focus-visible .btn-explore-fill,
.btn-explore:active .btn-explore-fill {
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  border-radius: 100px;
  opacity: 1;
  transform: none;
}
.btn-explore:hover .btn-explore-idle,
.btn-explore:focus-visible .btn-explore-idle,
.btn-explore:active .btn-explore-idle {
  opacity: 0;
  transform: translateX(-3rem);
}
.btn-explore:hover .btn-explore-active,
.btn-explore:focus-visible .btn-explore-active,
.btn-explore:active .btn-explore-active {
  opacity: 1;
  transform: none;
}
@media (max-width: 480px) {
  .btn-explore { min-width: 0; width: 100%; }
}

/* Ghost / link */
.btn-3 {
  height: auto;
  padding: 0;
  border-radius: 0;
  color: var(--slate-200);
  background: none;
}
.btn-3::after {
  content: "";
  position: absolute;
  left: 0; bottom: -4px;
  width: 100%; height: 1px;
  background: var(--grad-iri);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .55s var(--e-out);
}
.btn-3:hover { color: var(--white); transform: none; }
.btn-3:hover::after { transform: scaleX(1); }

.btn-sm { --bh: 2.7rem; padding-inline: 1.3rem; font-size: .855rem; }
.btn-lg { --bh: 3.95rem; padding-inline: 2.4rem; font-size: 1rem; }

/* Arrow that slides */
.btn .arw {
  display: inline-block;
  transition: transform .5s var(--e-out);
}
.btn:hover .arw { transform: translateX(4px); }

/* ---------- 8. CHIPS / TAGS / LABELS ---------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  padding: .42em 1em;
  border-radius: 100px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--slate-200);
  transition: all .4s var(--e-out);
  white-space: nowrap;
}
.chip:hover, .chip.on {
  border-color: var(--accent-line);
  color: var(--white);
  background: var(--accent-soft);
}

.dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--iri-1);
  box-shadow: 0 0 10px var(--iri-1);
  flex: none;
}
.dot-pulse { animation: pulse 2.1s var(--e-io) infinite; }
@keyframes pulse {
  0%,100% { opacity: 1; transform: scale(1); }
  50%     { opacity: .38; transform: scale(.72); }
}

/* Section eyebrow */
.eyebrow {
  display: flex;
  align-items: center;
  gap: .85rem;
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--slate-400);
  margin-bottom: 1.6rem;
}
.eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--slate-600), transparent);
  max-width: 220px;
}
.eyebrow .n {
  color: var(--iri-1);
  font-variant-numeric: tabular-nums;
}

/* ---------- 9. SCROLL REVEAL ---------- */
[data-rv] {
  opacity: 0;
  transform: translateY(34px);
  transition:
    opacity 1.05s var(--e-out),
    transform 1.05s var(--e-out),
    filter 1.05s var(--e-out);
  filter: blur(7px);
  will-change: opacity, transform;
}
[data-rv].in {
  opacity: 1;
  transform: none;
  filter: blur(0);
}
[data-rv="left"]  { transform: translateX(-42px); }
[data-rv="right"] { transform: translateX(42px); }
[data-rv="scale"] { transform: scale(.93); }
[data-rv="clip"] {
  opacity: 1;
  filter: none;
  transform: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 1.25s var(--e-io);
}
[data-rv="clip"].in { clip-path: inset(0 0 0 0); }

/* Line-by-line mask reveal */
.rv-line { overflow: hidden; display: block; }
.rv-line > span {
  display: block;
  transform: translateY(105%);
  transition: transform 1.15s var(--e-out);
}
.in .rv-line > span, .rv-line.in > span { transform: none; }

/* ---------- 11. NAV ---------- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 900;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  transition: background .55s var(--e-out), backdrop-filter .55s, border-color .55s, height .45s var(--e-out);
  border-bottom: 1px solid transparent;
}
.nav.stuck {
  height: 64px;
  background: rgba(var(--ground-rgb),.82);
  backdrop-filter: blur(20px) saturate(1.5);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  border-bottom-color: var(--line);
}
.nav-in {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gut);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

/* Logo */
.logo {
  display: flex;
  align-items: center;
  gap: .68rem;
  font-family: var(--f-display);
  font-size: 1.06rem;
  font-weight: 700;
  letter-spacing: -.035em;
  flex: none;
}
.logo-mk {
  width: 27px; height: 27px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 2.2px;
  flex: none;
}
.logo-mk i {
  background: var(--slate-400);
  border-radius: 1px;
  transition: background .5s var(--e-out), transform .5s var(--e-out);
}
.logo:hover .logo-mk i { background: var(--iri-1); }
.logo:hover .logo-mk i:nth-child(2n) { background: var(--iri-3); transform: scale(.62); }
.logo:hover .logo-mk i:nth-child(3n) { background: var(--iri-4); }
.logo-mk i:nth-child(1) { transition-delay: 0ms; }
.logo-mk i:nth-child(2) { transition-delay: 30ms; }
.logo-mk i:nth-child(3) { transition-delay: 60ms; }
.logo-mk i:nth-child(4) { transition-delay: 40ms; }
.logo-mk i:nth-child(5) { transition-delay: 70ms; }
.logo-mk i:nth-child(6) { transition-delay: 100ms; }
.logo-mk i:nth-child(7) { transition-delay: 80ms; }
.logo-mk i:nth-child(8) { transition-delay: 110ms; }
.logo-mk i:nth-child(9) { transition-delay: 140ms; }
.logo b { font-weight: 700; }
.logo span { font-weight: 300; color: var(--slate-300); }

/* Nav links */
.nav-links {
  display: flex;
  align-items: center;
  gap: clamp(.4rem, 1.6vw, 1.5rem);
}
@media (min-width: 1001px) {
  .nav-in { position: relative; }
  .nav-links {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
  }
}
.nav-links a {
  position: relative;
  padding: .5rem .2rem;
  font-size: .885rem;
  font-weight: 400;
  color: var(--slate-300);
  letter-spacing: -.008em;
  transition: color .4s var(--e-out);
}
.nav-links a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 2px;
  width: 100%; height: 1px;
  background: var(--grad-iri);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .5s var(--e-out);
}
.nav-links a:hover, .nav-links a[aria-current="page"] { color: var(--white); }
.nav-links a:hover::after, .nav-links a[aria-current="page"]::after { transform: scaleX(1); }

.nav-right { display: flex; align-items: center; gap: .85rem; flex: none; }

/* Lang toggle */
.lang {
  display: flex;
  align-items: center;
  padding: 3px;
  border-radius: 100px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-brd);
  gap: 2px;
}
.lang button {
  padding: .3rem .68rem;
  border-radius: 100px;
  font-family: var(--f-mono);
  font-size: .66rem;
  letter-spacing: .12em;
  color: var(--slate-400);
  transition: all .4s var(--e-out);
}
.lang button.on {
  color: var(--void);
  background: var(--bone);
  font-weight: 600;
}
.lang button:not(.on):hover { color: var(--bone); }

/* Theme toggle.
   The icon is drawn entirely from the button's own two pseudo-elements — no
   child markup, no SVG, no icon font. ::before is the disc, ::after is the
   crescent bite that slides across it: offset out of frame it reads as a sun,
   slid over the disc it eclipses one side into a moon. One element, both
   states, and the morph is a single transform. */
.tsw {
  position: relative;
  width: 38px; height: 38px;
  flex: none;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,.14);
  background: var(--white);
  display: grid;
  place-items: center;
  transition: border-color .4s var(--e-out), background .4s var(--e-out), transform .5s var(--e-out);
}
.tsw:hover { border-color: var(--accent-line); }
.tsw:active { transform: scale(.93); }
.tsw { display: none !important; }

/* Fixed moon icon; only its contrast changes with the active theme. */
.theme-icon { width: 20px; height: 20px; object-fit: contain; transition: filter .4s var(--e-out); }
:root[data-theme="light"] .tsw { background: var(--ink-k); border-color: rgba(255,255,255,.16); }
:root[data-theme="light"] .theme-icon { filter: invert(1); }

/* Hide the transition during a deliberate flip: ~40 elements with long colour
   transitions would otherwise cross-fade at different rates, which reads as a
   smear instead of a switch. JS adds this for exactly two frames. */
.theme-swap, .theme-swap *, .theme-swap *::before, .theme-swap *::after {
  transition: none !important;
}

/* Burger */
.burger {
  display: none;
  box-sizing: border-box;
  width: 44px;
  height: 44px;
  min-width: 44px;
  aspect-ratio: 1;
  padding: 0;
  flex: 0 0 44px;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--glass-brd);
  background: var(--glass-bg);
}
.burger-icon {
  width: 22px;
  height: 22px;
  display: block;
  object-fit: contain;
  filter: invert(1);
  transition: transform .45s var(--e-out), opacity .25s ease;
}
:root[data-theme="light"] .burger-icon { filter: none; }
.burger.on .burger-icon { transform: rotate(90deg) scale(.9); opacity: .72; }

/* Touch sizing for the nav cluster — the other half of interaction rule 9.
   It has to be HERE, after .lang button / .tsw / .burger are defined,
   because an equal-specificity rule earlier in the file simply loses the
   cascade (it did: the buttons stayed 36x27 and 38x38 in testing).
   The bar is a fixed --nav-h with height-centred contents, so growing these
   vertically costs no layout, and the widths were re-verified to still fit
   a 320px viewport with the burger fully on-screen. */
@media (hover: none) {
  .lang button { padding-block: .62rem; }
  .tsw, .burger { width: 44px; height: 44px; }
}

@media (max-width: 1000px) {
  .nav-links { display: none; }
  .burger { display: grid; }
  /* Tighten the control cluster once the burger joins it. */
  .nav-right { gap: .55rem; }
}

/* Nav overflow rescue.
   Measured at 390px: logo 117 + lang 83 + tsw 38 + CTA 118 + burger 42 plus
   gutters came to 475px of content in a 390px bar, so the burger was laid
   out at x=439 — entirely outside the viewport and silently cut off by the
   root's overflow-x: clip. The mobile menu was therefore unreachable and
   the CTA was sliced in half. The burger is the only control that CANNOT be
   sacrificed (it is the sole route to the nav links), so the redundant one
   goes: the header CTA is already covered by the drawer's Contact entry and
   by a primary CTA in every page's hero and closing block. */
@media (max-width: 820px) {
  .nav-right > .btn { display: none; }
}
/* At 360px and below even logo + lang + theme + burger overruns the bar
   (measured 334px of content at 320px), and the burger must survive. The
   wordmark keeps its 9-dot glyph — which is the actual brand mark and stays
   a link to home — and drops only the redundant "SilentPixel" lettering
   that the drawer and every page heading already state. */
@media (max-width: 360px) {
  .logo > span:last-child { display: none; }
  .nav-right { gap: .4rem; }
  .lang button { padding-inline: .5rem; }
}

/* Mobile drawer */
.drawer {
  position: fixed;
  inset: 0;
  z-index: 890;
  background: rgba(var(--ground-rgb),.97);
  backdrop-filter: blur(26px);
  -webkit-backdrop-filter: blur(26px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--nav-h) var(--gut) 3rem;
  clip-path: circle(0% at 92% 5%);
  transition: clip-path 1s var(--e-io);
  pointer-events: none;
}
.drawer.on { clip-path: circle(150% at 92% 5%); pointer-events: auto; }
.drawer a {
  font-family: var(--f-display);
  font-size: clamp(2rem, 8vw, 3.4rem);
  font-weight: 600;
  letter-spacing: -.045em;
  line-height: 1.1;
  padding: .34rem 0;
  color: var(--slate-300);
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .7s var(--e-out), transform .7s var(--e-out), color .3s;
}
.drawer.on a { opacity: 1; transform: none; }
.drawer.on a:nth-child(1) { transition-delay: .18s; }
.drawer.on a:nth-child(2) { transition-delay: .25s; }
.drawer.on a:nth-child(3) { transition-delay: .32s; }
.drawer.on a:nth-child(4) { transition-delay: .39s; }
.drawer.on a:nth-child(5) { transition-delay: .46s; }
.drawer a:hover { color: var(--white); }
.drawer a .idx {
  font-family: var(--f-mono);
  font-size: .7rem;
  color: var(--iri-1);
  vertical-align: super;
  margin-right: .6rem;
  letter-spacing: .1em;
}

/* ---------- 12. FOOTER ---------- */
.foot {
  position: relative;
  padding-top: clamp(4rem, 9vh, 7rem);
  padding-bottom: 2.2rem;
  border-top: 1px solid var(--line);
  overflow: hidden;
}
.foot-grid {
  display: grid;
  grid-template-columns: 1.5fr repeat(3, 1fr);
  gap: clamp(2rem, 4vw, 3.5rem);
  padding-bottom: clamp(3rem, 6vh, 5rem);
}
@media (max-width: 900px) { .foot-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .foot-grid { grid-template-columns: 1fr; } }

.foot h5 {
  font-family: var(--f-mono);
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--slate-400);
  margin-bottom: 1.2rem;
}
.foot-links { display: flex; flex-direction: column; gap: .62rem; }
.foot-links a {
  font-size: .9rem;
  color: var(--slate-300);
  transition: color .35s, transform .45s var(--e-out);
  display: inline-block;
  width: fit-content;
}
.foot-links a:hover { color: var(--white); transform: translateX(4px); }
.foot-links .social-link { display: flex; align-items: center; gap: .55rem; }
.foot-links .social-link img { display: block !important; width: 16px !important; height: 16px !important; max-width: 16px !important; flex: 0 0 16px; object-fit: contain; filter: invert(1); opacity: .72; }
.foot-links .social-link img[src$="instagram.svg"] { transform: scale(1.12); }

/* Shared composition utilities: keep page markup free of inline presentation. */
.u-flex-wrap { display: flex; flex-wrap: wrap; }
.u-flex-center { display: flex; align-items: center; justify-content: center; }
.u-center { text-align: center; }
.u-center-inline { margin-inline: auto; }
.u-grid-center { display: grid; place-items: center; text-align: center; }
.u-min-h-card { min-height: 288px; }
.u-max-38 { max-width: 38ch; }
.u-max-50 { max-width: 50ch; }
.u-max-52 { max-width: 52ch; }
.u-max-54 { max-width: 54ch; }
.u-max-56 { max-width: 56ch; }
.u-max-34 { max-width: 34ch; }
.u-copy { font-size: .9rem; color: var(--slate-300); max-width: 34ch; margin-bottom: 1.5rem; }
.u-mt-0 { margin-top: 0; }
.u-mt-sm { margin-top: .4rem; }
.u-mt-md { margin-top: .6rem; }
.u-mt-lg { margin-top: 1.2rem; }
.u-mt-xl { margin-top: 2rem; }
.u-mt-2xl { margin-top: 2.2rem; }
.u-mt-3xl { margin-top: 3rem; }
.u-mt-34 { margin-top: 3.4rem; }
.u-mb-sm { margin-bottom: 1.1rem; }
.u-mb-md { margin-bottom: 1.3rem; }
.u-mb-lg { margin-bottom: 1.6rem; }
.u-gap-sm { gap: .5rem; }
.u-gap-md { gap: .7rem; }
.u-inline-grid { display: grid; grid-template-columns: 1fr 1.2fr; gap: clamp(2rem, 4vw, 4.5rem); align-items: start; }
.u-section-heading { max-width: 56ch; margin-inline: auto; margin-bottom: clamp(2.5rem, 6vh, 4.5rem); }
.u-section-heading-tight { max-width: 52ch; margin-inline: auto; margin-bottom: clamp(2.5rem, 6vh, 4rem); }
.u-lede-center { margin-inline: auto; }
.u-logo { margin-bottom: 1.3rem; }
.u-flex-gap { gap: .5rem; flex-wrap: wrap; }

.foot-bot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding-top: 1.8rem;
  border-top: 1px solid var(--line);
}
.foot-bot p { font-family: var(--f-mono); font-size: var(--t-xs); letter-spacing: .12em; color: var(--slate-500); text-transform: uppercase; }

/* ---------- 13. UTILITIES ---------- */
.sr {
  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: fixed;
  top: -100px; left: 50%;
  transform: translateX(-50%);
  z-index: 9999;
  padding: .8rem 1.4rem;
  background: var(--bone);
  color: var(--void);
  border-radius: 0 0 var(--r-md) var(--r-md);
  font-size: .875rem;
  font-weight: 600;
  transition: top .35s var(--e-out);
}
.skip:focus { top: 0; }

.rel { position: relative; }
.z1 { position: relative; z-index: 1; }
.z2 { position: relative; z-index: 2; }
.ovh { overflow: hidden; }
.nowrap { white-space: nowrap; }
.tc { text-align: center; }
.mx-auto { margin-inline: auto; }
.full { width: 100%; }

/* Hide inactive language */
[data-i18n-hide] { display: none !important; }
