/* ============================================================================
   worxbend — personal page stylesheet

   Structure
     1.  Theme tokens        every theme redefines the same variable contract
     2.  Reset & base
     3.  Background stack    canvases + grid + vignette owned by assets/fx/*
     4.  Chrome              header, nav, settings drawer, command palette
     5.  Hero
     6.  Catalog             search, facets, project cards
     7.  Résumé              experience, skills, education
     8.  Contact
     9.  Footer
     10. Motion & responsive

   The `--fx-*` block inside each theme is a contract, not decoration: the
   background engines in assets/fx/ read those values off the root element with
   getComputedStyle and repaint when the `wb:themechange` event fires. Adding a
   theme therefore needs no JavaScript change at all.
   ========================================================================= */

/* ============================================================== 1. tokens */

:root {
  /* --- typography ---------------------------------------------------- */
  --sans: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --mono: "Geist Mono", ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;

  --step--1: clamp(0.76rem, 0.74rem + 0.10vw, 0.82rem);
  --step-0:  clamp(0.94rem, 0.90rem + 0.18vw, 1.02rem);
  --step-1:  clamp(1.14rem, 1.05rem + 0.42vw, 1.38rem);
  --step-2:  clamp(1.42rem, 1.24rem + 0.86vw, 2.00rem);
  --step-3:  clamp(1.78rem, 1.42rem + 1.72vw, 2.96rem);
  --step-4:  clamp(2.20rem, 1.55rem + 3.10vw, 4.40rem);

  /* --- spacing & shape ------------------------------------------------ */
  --gap-1: 6px;
  --gap-2: 12px;
  --gap-3: 20px;
  --gap-4: 32px;
  --gap-5: 52px;
  --gap-6: 84px;
  --radius-sm: 6px;
  --radius: 12px;
  --radius-lg: 18px;
  --shell: 1240px;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  /* --- motion scale --------------------------------------------------- */
  /* app.js sets this to 0 when the visitor asks for reduced motion, which
     collapses every transition and animation without deleting the rules. */
  --motion: 1;

  color-scheme: dark;
}

/* --- Theme: Prime Radiant (default) ----------------------------------- */
/* Deep-space indigo with a cold cyan signal colour. Named for the Foundation
   device that displays psychohistorical equations. */
:root,
[data-theme="radiant"] {
  --bg:            #05060d;
  --bg-deep:       #03030a;
  --surface:       #0b0d1a;
  --surface-2:     #11142450;
  --surface-solid: #101324;
  --fg:            #e8ecfb;
  --fg-muted:      #9ba3c4;
  --fg-dim:        #626a8c;
  --line:          #ffffff14;
  --line-strong:   #ffffff26;

  --accent:        #7c9cff;
  --accent-2:      #57e3d0;
  --accent-3:      #c58bff;
  --accent-ink:    #05060d;
  --accent-soft:   #7c9cff1f;
  --accent-glow:   #7c9cff59;

  --ok:   #58d9a3;
  --warn: #e8c46a;

  --fx-node: 145 170 255;
  --fx-link: 110 128 200;
  --fx-c1:   124 156 255;
  --fx-c2:   87 227 208;
  --fx-c3:   197 139 255;
  --fx-c4:   255 255 255;
  --fx-alpha-node: 0.62;
  --fx-alpha-link: 0.26;
  --fx-composite: lighter;
  --fx-grid: 255 255 255;
  --fx-grid-alpha: 0.045;
  --fx-star-hue: 224;
  --fx-glyph-alpha: 0.30;
}

/* --- Theme: Matrix ----------------------------------------------------- */
/* Black, phosphor green, one amber warning colour. */
[data-theme="matrix"] {
  --bg:            #000403;
  --bg-deep:       #000201;
  --surface:       #04120c;
  --surface-2:     #06190f60;
  --surface-solid: #061a10;
  --fg:            #ccffdd;
  --fg-muted:      #6fbf8e;
  --fg-dim:        #3d7a58;
  --line:          #4dff9f1c;
  --line-strong:   #4dff9f33;

  --accent:        #4dff9f;
  --accent-2:      #9dff5c;
  --accent-3:      #26c97a;
  --accent-ink:    #00160c;
  --accent-soft:   #4dff9f1c;
  --accent-glow:   #4dff9f55;

  --ok:   #4dff9f;
  --warn: #ffc65c;

  --fx-node: 77 255 159;
  --fx-link: 40 160 100;
  --fx-c1:   77 255 159;
  --fx-c2:   157 255 92;
  --fx-c3:   38 201 122;
  --fx-c4:   224 255 236;
  --fx-alpha-node: 0.68;
  --fx-alpha-link: 0.22;
  --fx-composite: lighter;
  --fx-grid: 77 255 159;
  --fx-grid-alpha: 0.05;
  --fx-star-hue: 145;
  --fx-glyph-alpha: 0.72;
}

/* --- Theme: Blueprint -------------------------------------------------- */
/* Drafting-table navy with cyan line-work. The engineering register. */
[data-theme="blueprint"] {
  --bg:            #05101c;
  --bg-deep:       #030a13;
  --surface:       #0a1a2c;
  --surface-2:     #0d2136aa;
  --surface-solid: #0c1f33;
  --fg:            #dcefff;
  --fg-muted:      #8fb4d4;
  --fg-dim:        #5b809f;
  --line:          #6fd4ff1f;
  --line-strong:   #6fd4ff38;

  --accent:        #4fc3f7;
  --accent-2:      #ffd479;
  --accent-3:      #7fe3c4;
  --accent-ink:    #041220;
  --accent-soft:   #4fc3f71f;
  --accent-glow:   #4fc3f75c;

  --ok:   #7fe3c4;
  --warn: #ffd479;

  --fx-node: 120 200 245;
  --fx-link: 70 140 190;
  --fx-c1:   79 195 247;
  --fx-c2:   255 212 121;
  --fx-c3:   127 227 196;
  --fx-c4:   240 250 255;
  --fx-alpha-node: 0.58;
  --fx-alpha-link: 0.30;
  --fx-composite: lighter;
  --fx-grid: 111 212 255;
  --fx-grid-alpha: 0.075;
  --fx-star-hue: 200;
  --fx-glyph-alpha: 0.18;
}

/* --- Theme: Solar ------------------------------------------------------ */
/* Chromosphere: near-black ground, amber and rose plasma. */
[data-theme="solar"] {
  --bg:            #0d0603;
  --bg-deep:       #080402;
  --surface:       #1a0d06;
  --surface-2:     #23120880;
  --surface-solid: #1f1008;
  --fg:            #ffeede;
  --fg-muted:      #d4a483;
  --fg-dim:        #96654a;
  --line:          #ff9d4d1c;
  --line-strong:   #ff9d4d33;

  --accent:        #ff9d4d;
  --accent-2:      #ff5f7e;
  --accent-3:      #ffd166;
  --accent-ink:    #180a03;
  --accent-soft:   #ff9d4d1f;
  --accent-glow:   #ff9d4d5c;

  --ok:   #ffd166;
  --warn: #ff5f7e;

  --fx-node: 255 172 110;
  --fx-link: 190 110 70;
  --fx-c1:   255 157 77;
  --fx-c2:   255 95 126;
  --fx-c3:   255 209 102;
  --fx-c4:   255 244 230;
  --fx-alpha-node: 0.64;
  --fx-alpha-link: 0.24;
  --fx-composite: lighter;
  --fx-grid: 255 157 77;
  --fx-grid-alpha: 0.05;
  --fx-star-hue: 26;
  --fx-glyph-alpha: 0.24;
}

/* --- Theme: Nebula ----------------------------------------------------- */
[data-theme="nebula"] {
  --bg:            #0a041a;
  --bg-deep:       #060210;
  --surface:       #150a2c;
  --surface-2:     #1d0f3c80;
  --surface-solid: #190c33;
  --fg:            #f2e6ff;
  --fg-muted:      #b498d8;
  --fg-dim:        #7c62a0;
  --line:          #c98bff1c;
  --line-strong:   #c98bff33;

  --accent:        #d68bff;
  --accent-2:      #56d8ff;
  --accent-3:      #ff87c3;
  --accent-ink:    #12052a;
  --accent-soft:   #d68bff1f;
  --accent-glow:   #d68bff5c;

  --ok:   #56d8ff;
  --warn: #ff87c3;

  --fx-node: 214 139 255;
  --fx-link: 140 95 190;
  --fx-c1:   214 139 255;
  --fx-c2:   86 216 255;
  --fx-c3:   255 135 195;
  --fx-c4:   255 248 255;
  --fx-alpha-node: 0.66;
  --fx-alpha-link: 0.26;
  --fx-composite: lighter;
  --fx-grid: 214 139 255;
  --fx-grid-alpha: 0.05;
  --fx-star-hue: 285;
  --fx-glyph-alpha: 0.26;
}

/* --- Theme: Observatory (light) ---------------------------------------- */
/* The one light theme. Ink on paper, with a plotted-chart blue. */
[data-theme="observatory"] {
  color-scheme: light;

  --bg:            #f4f5f8;
  --bg-deep:       #e9ebf1;
  --surface:       #ffffff;
  --surface-2:     #ffffffcc;
  --surface-solid: #ffffff;
  --fg:            #131627;
  --fg-muted:      #4d5470;
  --fg-dim:        #7a8199;
  --line:          #13162718;
  --line-strong:   #1316272e;

  --accent:        #3b5bdb;
  --accent-2:      #0b8a72;
  --accent-3:      #8b3fd6;
  --accent-ink:    #ffffff;
  --accent-soft:   #3b5bdb14;
  --accent-glow:   #3b5bdb33;

  --ok:   #0b8a72;
  --warn: #b5710a;

  --fx-node: 59 91 219;
  --fx-link: 120 138 205;
  --fx-c1:   59 91 219;
  --fx-c2:   11 138 114;
  --fx-c3:   139 63 214;
  --fx-c4:   20 24 48;
  --fx-alpha-node: 0.42;
  --fx-alpha-link: 0.20;
  --fx-composite: source-over;
  --fx-grid: 19 22 39;
  --fx-grid-alpha: 0.05;
  --fx-star-hue: 224;
  --fx-glyph-alpha: 0.14;
}

/* ============================================================ 2. reset */

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

* { margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  /* Sticky header height plus breathing room, so anchors do not land under it. */
  scroll-padding-top: 92px;
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: var(--step-0);
  line-height: 1.62;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background-color .45s var(--ease-out), color .45s var(--ease-out);
}

img, svg, canvas { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

::selection { background: var(--accent-soft); color: var(--fg); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border-radius: 99px;
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--fg-dim); background-clip: content-box; }

.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-link {
  position: absolute; left: 12px; top: -60px; z-index: 999;
  padding: 10px 16px; border-radius: var(--radius-sm);
  background: var(--accent); color: var(--accent-ink);
  font-family: var(--mono); font-size: var(--step--1);
  transition: top .2s var(--ease-out);
}
.skip-link:focus { top: 12px; }

/* ================================================== 3. background stack */

.fx-stack {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  contain: strict;
}

/* Every FX layer is a full-bleed canvas the engines own. They are stacked in
   depth order: stars sit furthest back, the particle mesh in front of them,
   the glyph rain closest to the page. */
.fx-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 1.1s var(--ease-out);
}
.fx-layer.is-live { opacity: 1; }

#fx-stars   { z-index: 1; }
#fx-network { z-index: 2; }
#fx-glyphs  { z-index: 3; mix-blend-mode: screen; }

[data-theme="observatory"] #fx-glyphs { mix-blend-mode: multiply; }

/* Engineering grid — pure CSS, always on, costs nothing to animate because it
   never animates. Masked to a soft ellipse so it fades out at the edges. */
.fx-grid {
  position: absolute;
  inset: -2px;
  z-index: 0;
  background-image:
    linear-gradient(to right,  rgb(var(--fx-grid) / var(--fx-grid-alpha)) 1px, transparent 1px),
    linear-gradient(to bottom, rgb(var(--fx-grid) / var(--fx-grid-alpha)) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: radial-gradient(ellipse 90% 70% at 50% 30%, #000 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 30%, #000 0%, transparent 78%);
}

/* Radial vignette that keeps text legible over whatever the canvases draw. */
.fx-vignette {
  position: absolute;
  inset: 0;
  z-index: 4;
  background:
    radial-gradient(ellipse 120% 80% at 50% 0%, transparent 40%, var(--bg-deep) 100%),
    radial-gradient(circle 620px at var(--mx, 50%) var(--my, 30%), rgb(var(--fx-c1) / .07), transparent 62%);
}

.fx-noise {
  position: absolute;
  inset: 0;
  z-index: 5;
  opacity: .028;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* ===================================================== 4. chrome & shell */

.app { position: relative; z-index: 2; }

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: clamp(18px, 4vw, 40px);
}

.masthead {
  position: sticky;
  top: 0;
  z-index: 60;
  border-bottom: 1px solid var(--line);
  background: color-mix(in oklab, var(--bg) 72%, transparent);
  backdrop-filter: blur(18px) saturate(170%);
  -webkit-backdrop-filter: blur(18px) saturate(170%);
}

.masthead-inner {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  height: 62px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.brand-mark {
  width: 22px; height: 22px;
  flex: none;
  color: var(--accent);
  filter: drop-shadow(0 0 8px var(--accent-glow));
  animation: mark-spin 26s linear infinite;
  animation-duration: calc(26s / max(var(--motion), 0.001));
}
@keyframes mark-spin { to { transform: rotate(360deg); } }
.brand-name b { font-weight: 600; }
.brand-name span { color: var(--fg-dim); }

.primary-nav {
  display: flex;
  gap: 2px;
  margin-inline-start: auto;
  font-family: var(--mono);
  font-size: var(--step--1);
}
.primary-nav a {
  position: relative;
  padding: 7px 12px;
  border-radius: var(--radius-sm);
  color: var(--fg-muted);
  transition: color .18s, background-color .18s;
}
.primary-nav a:hover { color: var(--fg); background: var(--surface-2); }
.primary-nav a[aria-current="true"] { color: var(--accent); }
.primary-nav a[aria-current="true"]::after {
  content: "";
  position: absolute;
  left: 12px; right: 12px; bottom: 2px;
  height: 1px;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent-glow);
}

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 34px; height: 34px;
  flex: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-muted);
  cursor: pointer;
  transition: color .18s, border-color .18s, background-color .18s;
}
.icon-btn:hover { color: var(--fg); border-color: var(--fg-dim); background: var(--surface-2); }
.icon-btn svg { width: 16px; height: 16px; }

.cmd-trigger {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: 34px;
  padding: 0 8px 0 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: var(--step--1);
  cursor: pointer;
  transition: color .18s, border-color .18s;
}
.cmd-trigger:hover { color: var(--fg-muted); border-color: var(--fg-dim); }
.cmd-trigger svg { width: 14px; height: 14px; }

kbd {
  display: inline-block;
  padding: 2px 6px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: var(--surface-2);
  color: var(--fg-muted);
  font-family: var(--mono);
  font-size: 10px;
  line-height: 1.5;
}

/* --- section scaffolding ---------------------------------------------- */

.section { padding-block: clamp(56px, 8vw, var(--gap-6)); position: relative; }
.section + .section { border-top: 1px solid var(--line); }

.section-head { margin-bottom: var(--gap-4); }

.eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  color: var(--accent);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.eyebrow::before {
  content: "";
  width: 22px; height: 1px;
  background: currentColor;
  box-shadow: 0 0 8px var(--accent-glow);
}

.section-title {
  font-size: var(--step-3);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.1;
  text-wrap: balance;
}
.section-lede {
  max-width: 68ch;
  margin-top: 14px;
  color: var(--fg-muted);
  text-wrap: pretty;
}

/* ================================================================ 5. hero */

.hero {
  position: relative;
  padding-block: clamp(64px, 12vh, 132px) clamp(48px, 8vh, 96px);
}

/* Two columns once there is room: copy on the left, plasma orb on the right.
   Below that width the orb column is removed entirely — it is decoration, and
   a phone should not be asked to run a second WebGL context on top of the
   background layers. */
.hero-copy { min-width: 0; }
.hero-orb { display: none; }

@media (min-width: 1080px) {
  .hero-inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(280px, 400px);
    gap: clamp(32px, 4vw, 64px);
    align-items: center;
  }
  .hero-orb {
    display: block;
    position: relative;
    aspect-ratio: 1 / 1;
    /* Stay invisible until the WebGL context is live, so there is no flash of
       empty box while three.js is still downloading. */
    opacity: 0;
    transition: opacity .9s var(--ease-out) .15s;
  }
  .hero-orb.is-live { opacity: 1; }
  .hero-orb canvas {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
  }
}

/* --- particle headline -------------------------------------------------

   When hero-text.js takes over, the real <h1> text is painted transparent
   rather than removed: it still holds the layout the particles were sampled
   from, and screen readers, find-in-page and text selection all keep working.
   The canvas is stretched past the h1's box so particles shoved by the cursor
   have somewhere to go instead of being clipped at the edge. */

.hero-title.has-particles { position: relative; color: transparent; }
.hero-title.has-particles .accent { background: none; color: transparent; }
.hero-title.has-particles::selection,
.hero-title.has-particles ::selection { color: var(--fg); }

.hero-particles {
  position: absolute;
  top: -90px;
  left: -90px;
  pointer-events: none;
  z-index: 1;
}

.hero-status {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 26px;
  padding: 5px 13px 5px 9px;
  border: 1px solid var(--line-strong);
  border-radius: 99px;
  background: var(--surface-2);
  color: var(--fg-muted);
  font-family: var(--mono);
  font-size: var(--step--1);
}
.pulse-dot {
  width: 7px; height: 7px;
  flex: none;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 0 color-mix(in oklab, var(--ok) 70%, transparent);
  animation: pulse-ring 2.6s var(--ease-out) infinite;
  animation-duration: calc(2.6s / max(var(--motion), 0.001));
}
@keyframes pulse-ring {
  0%   { box-shadow: 0 0 0 0 color-mix(in oklab, var(--ok) 65%, transparent); }
  70%  { box-shadow: 0 0 0 9px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

.hero-title {
  font-size: var(--step-4);
  font-weight: 600;
  letter-spacing: -0.045em;
  line-height: 0.98;
  text-wrap: balance;
}
.hero-title .accent {
  background: linear-gradient(105deg, var(--accent) 0%, var(--accent-2) 48%, var(--accent-3) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero-role {
  margin-top: 18px;
  color: var(--fg-muted);
  font-family: var(--mono);
  font-size: var(--step-1);
  letter-spacing: -0.01em;
}
/* The rotating specialism: one line, fixed height, no layout shift. */
.hero-role .rotator {
  display: inline-block;
  min-width: 1ch;
  color: var(--accent-2);
}
.hero-role .caret {
  display: inline-block;
  width: 9px;
  margin-left: 2px;
  border-bottom: 2px solid var(--accent-2);
  animation: caret-blink 1.15s steps(1) infinite;
  animation-duration: calc(1.15s / max(var(--motion), 0.001));
  vertical-align: 2px;
}
@keyframes caret-blink { 50% { opacity: 0; } }

.hero-lede {
  max-width: 62ch;
  margin-top: 26px;
  color: var(--fg-muted);
  font-size: var(--step-1);
  text-wrap: pretty;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-2);
  margin-top: var(--gap-4);
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 19px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg);
  font-family: var(--mono);
  font-size: var(--step--1);
  cursor: pointer;
  transition: transform .18s var(--ease-out), border-color .18s, background-color .18s, color .18s;
}
.btn:hover { transform: translateY(calc(-2px * var(--motion))); border-color: var(--fg-dim); background: var(--surface-2); }
.btn:active { transform: translateY(0); }
.btn svg { width: 15px; height: 15px; }

.btn-primary {
  border-color: transparent;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  box-shadow: 0 0 0 1px var(--accent), 0 8px 28px -12px var(--accent-glow);
}
.btn-primary:hover { background: var(--accent); color: var(--accent-ink); filter: brightness(1.08); }

/* --- metric strip ------------------------------------------------------ */

.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1px;
  margin-top: clamp(44px, 7vw, 76px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--line);
  overflow: hidden;
}
.metric {
  padding: 22px 20px;
  background: color-mix(in oklab, var(--surface) 62%, transparent);
}
.metric-val {
  font-family: var(--mono);
  font-size: var(--step-2);
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}
.metric-lbl {
  margin-top: 4px;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: var(--step--1);
}

/* ============================================================= 6. catalog */

.catalog-controls {
  position: sticky;
  top: 62px;
  z-index: 40;
  margin-bottom: var(--gap-4);
  padding-block: 14px;
  background: color-mix(in oklab, var(--bg) 88%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.search-row {
  display: flex;
  gap: var(--gap-2);
  align-items: center;
}

.search-field {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
}
.search-field svg.search-icon {
  position: absolute;
  left: 14px; top: 50%;
  width: 16px; height: 16px;
  transform: translateY(-50%);
  color: var(--fg-dim);
  pointer-events: none;
}
.search-input {
  width: 100%;
  padding: 12px 92px 12px 42px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--fg);
  font-family: var(--mono);
  font-size: var(--step-0);
  transition: border-color .18s, box-shadow .18s;
}
.search-input::placeholder { color: var(--fg-dim); }
.search-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.search-meta {
  position: absolute;
  right: 12px; top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: var(--step--1);
  pointer-events: none;
}
.search-clear {
  pointer-events: auto;
  display: none;
  padding: 2px 7px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: transparent;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
  cursor: pointer;
}
.search-clear:hover { color: var(--fg); border-color: var(--fg-dim); }
.is-searching .search-clear { display: inline-block; }

.facets {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 14px;
}
.facet {
  padding: 6px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 99px;
  background: transparent;
  color: var(--fg-muted);
  font-family: var(--mono);
  font-size: var(--step--1);
  cursor: pointer;
  white-space: nowrap;
  transition: color .16s, border-color .16s, background-color .16s;
}
.facet:hover { color: var(--fg); border-color: var(--fg-dim); }
.facet[aria-pressed="true"] {
  border-color: transparent;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}
.facet .count { opacity: .55; margin-left: 6px; font-size: 10px; }
.facet[aria-pressed="true"] .count { opacity: .75; }

.facet-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
}
.facet-group + .facet-group { margin-top: 8px; }
.facet-legend {
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  margin-right: 4px;
  min-width: 62px;
}

/* --- grid & cards ------------------------------------------------------ */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  gap: var(--gap-3);
}

.group-head {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-top: var(--gap-3);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}
.group-head:first-child { margin-top: 0; }
.group-head h3 {
  font-size: var(--step-1);
  font-weight: 500;
  letter-spacing: -0.02em;
}
.group-head .count {
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: var(--step--1);
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 20px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: color-mix(in oklab, var(--surface) 55%, transparent);
  overflow: hidden;
  isolation: isolate;
  transition:
    transform .28s var(--ease-out),
    border-color .28s,
    background-color .28s;
}
/* Cursor-tracked sheen. --cx/--cy are written by app.js on pointermove. */
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  background: radial-gradient(340px circle at var(--cx, 50%) var(--cy, 50%), var(--accent-soft), transparent 68%);
  transition: opacity .3s var(--ease-out);
}
.card:hover {
  transform: translateY(calc(-3px * var(--motion)));
  border-color: var(--line-strong);
  background: color-mix(in oklab, var(--surface) 80%, transparent);
}
.card:hover::before { opacity: 1; }
.card:focus-within { border-color: var(--accent); }

.card-top {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 10px;
}
.card-title {
  font-size: var(--step-1);
  font-weight: 560;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.card-title a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}
.card-title a:hover { color: var(--accent); }

.tier-badge {
  margin-inline-start: auto;
  flex: none;
  padding: 3px 8px;
  border-radius: 99px;
  border: 1px solid var(--line-strong);
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.tier-badge[data-tier="flagship"] {
  border-color: transparent;
  background: var(--accent-soft);
  color: var(--accent);
}

.card-owner {
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 11px;
}
.card-tagline {
  margin-top: 2px;
  color: var(--fg-muted);
  font-size: var(--step--1);
  line-height: 1.55;
}
.card-summary {
  margin-top: 12px;
  color: var(--fg-muted);
  font-size: var(--step--1);
  line-height: 1.62;
}

.card-highlights {
  margin-top: 12px;
  padding-left: 0;
  list-style: none;
  display: grid;
  gap: 5px;
}
.card-highlights li {
  position: relative;
  padding-left: 16px;
  color: var(--fg-muted);
  font-size: var(--step--1);
  line-height: 1.5;
}
.card-highlights li::before {
  content: "";
  position: absolute;
  left: 2px; top: 0.62em;
  width: 5px; height: 5px;
  border-radius: 1px;
  background: var(--accent);
  opacity: .7;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 14px;
}
.chip {
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
  white-space: nowrap;
}
.chip mark { background: var(--accent-soft); color: var(--accent); border-radius: 2px; }

.card-foot {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: auto;
  padding-top: 16px;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 11px;
}
.card-foot > * { display: inline-flex; align-items: center; gap: 5px; }
.card-foot svg { width: 12px; height: 12px; }
.lang-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--lang-color, var(--fg-dim));
  flex: none;
}
.card-links {
  position: relative;
  z-index: 2;
  margin-inline-start: auto;
  display: inline-flex;
  gap: 8px;
}
.card-links a { color: var(--fg-dim); transition: color .16s; }
.card-links a:hover { color: var(--accent); }

/* Search-term highlighting inside titles and summaries. */
mark.hit {
  background: color-mix(in oklab, var(--accent) 24%, transparent);
  color: var(--fg);
  border-radius: 2px;
  padding: 0 1px;
}

.empty-state {
  grid-column: 1 / -1;
  padding: 56px 20px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  text-align: center;
  color: var(--fg-muted);
}
.empty-state code {
  font-family: var(--mono);
  color: var(--accent);
}

/* ============================================================ 7. résumé */

.timeline { display: grid; gap: var(--gap-3); }

.job {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: var(--gap-4);
  padding: 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: color-mix(in oklab, var(--surface) 42%, transparent);
  transition: border-color .28s, background-color .28s;
}
.job:hover { border-color: var(--line-strong); background: color-mix(in oklab, var(--surface) 66%, transparent); }

.job-when {
  font-family: var(--mono);
  font-size: var(--step--1);
}
.job-when .range { color: var(--fg); }
.job-when .dur { display: block; margin-top: 4px; color: var(--fg-dim); }
.job-when .loc { display: block; margin-top: 10px; color: var(--fg-dim); }

.job-role {
  font-size: var(--step-1);
  font-weight: 560;
  letter-spacing: -0.02em;
}
.job-org {
  margin-top: 3px;
  color: var(--accent);
  font-family: var(--mono);
  font-size: var(--step--1);
}
.job-blurb {
  margin-top: 10px;
  color: var(--fg-dim);
  font-size: var(--step--1);
}

.job-points {
  margin-top: 18px;
  display: grid;
  gap: 11px;
  list-style: none;
}
.job-points li {
  position: relative;
  padding-left: 34px;
  color: var(--fg-muted);
  font-size: var(--step--1);
  line-height: 1.65;
}
.job-points li::before {
  content: attr(data-mark);
  position: absolute;
  left: 0; top: 0;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .06em;
}
.job-points strong {
  color: var(--fg);
  font-weight: 600;
  background: linear-gradient(transparent 62%, var(--accent-soft) 62%);
}

/* --- skills ------------------------------------------------------------ */

.skill-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: var(--gap-3);
}
.skill-card {
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: color-mix(in oklab, var(--surface) 42%, transparent);
}
.skill-head {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.skill-glyph {
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--mono);
  font-size: 15px;
}
.skill-head h3 { font-size: var(--step-0); font-weight: 560; letter-spacing: -0.01em; }

.skill-row { margin-bottom: 14px; }
.skill-row:last-child { margin-bottom: 0; }
.skill-label {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
  font-family: var(--mono);
  font-size: var(--step--1);
}
.skill-label .name { color: var(--fg-muted); }
.skill-label .yrs { color: var(--fg-dim); font-size: 10px; }
.skill-track {
  height: 3px;
  border-radius: 99px;
  background: var(--line);
  overflow: hidden;
}
.skill-fill {
  height: 100%;
  width: 0;
  border-radius: 99px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  box-shadow: 0 0 10px var(--accent-glow);
  transition: width 1.1s var(--ease-out);
  transition-duration: calc(1.1s * var(--motion) + 0.001s);
}
.reveal.in .skill-fill { width: var(--pct); }

/* --- education / profiles --------------------------------------------- */

.stack-list { display: grid; gap: var(--gap-2); }

.line-item {
  display: flex;
  align-items: baseline;
  gap: var(--gap-3);
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: color-mix(in oklab, var(--surface) 42%, transparent);
  transition: border-color .24s, background-color .24s;
}
.line-item:hover { border-color: var(--line-strong); background: color-mix(in oklab, var(--surface) 66%, transparent); }
.line-item .when {
  flex: none;
  width: 92px;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: var(--step--1);
}
.line-item .what { font-weight: 560; }
.line-item .where { margin-top: 2px; color: var(--fg-muted); font-size: var(--step--1); }

/* --- contact ----------------------------------------------------------- */

.contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 1px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--line);
  overflow: hidden;
}
.contact-cell {
  display: block;
  padding: 22px;
  background: color-mix(in oklab, var(--surface) 55%, transparent);
  transition: background-color .22s;
}
.contact-cell:hover { background: color-mix(in oklab, var(--surface) 90%, transparent); }
.contact-cell .k {
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.contact-cell .v {
  margin-top: 7px;
  font-family: var(--mono);
  font-size: var(--step-0);
  word-break: break-word;
}
.contact-cell:hover .v { color: var(--accent); }

/* ================================================== 4b. settings drawer */

.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: color-mix(in oklab, var(--bg-deep) 68%, transparent);
  backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  transition: opacity .28s var(--ease-out), visibility .28s;
}
.drawer-scrim.is-open { opacity: 1; visibility: visible; }

.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  z-index: 91;
  width: min(400px, 100vw);
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--line-strong);
  background: var(--surface-solid);
  transform: translateX(100%);
  transition: transform .34s var(--ease-out);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.drawer.is-open { transform: none; }

.drawer-head {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 18px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--surface-solid);
}
.drawer-head h2 {
  font-size: var(--step-0);
  font-weight: 560;
  letter-spacing: -0.01em;
  margin-inline-end: auto;
}
.drawer-body { padding: 20px; display: grid; gap: var(--gap-4); }

.field-set { display: grid; gap: 12px; }
.field-legend {
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.field-help {
  color: var(--fg-dim);
  font-size: var(--step--1);
  line-height: 1.55;
}

.theme-swatches {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 9px;
}
.swatch {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-muted);
  font-family: var(--mono);
  font-size: var(--step--1);
  cursor: pointer;
  text-align: left;
  transition: border-color .18s, color .18s, background-color .18s;
}
.swatch:hover { color: var(--fg); border-color: var(--fg-dim); }
.swatch[aria-pressed="true"] { border-color: var(--accent); color: var(--fg); background: var(--accent-soft); }
.swatch-dots { display: inline-flex; gap: 3px; flex: none; }
.swatch-dots i {
  width: 9px; height: 9px;
  border-radius: 50%;
  display: block;
}

.seg {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
}
.seg button {
  padding: 7px 10px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--fg-muted);
  font-family: var(--mono);
  font-size: var(--step--1);
  cursor: pointer;
  transition: background-color .16s, color .16s;
}
.seg button:hover { color: var(--fg); }
.seg button[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); font-weight: 600; }

.toggle-row {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
}
.toggle-row .label { flex: 1 1 auto; font-size: var(--step--1); }
.toggle-row .label small { display: block; color: var(--fg-dim); font-size: 11px; line-height: 1.5; }

.switch {
  position: relative;
  flex: none;
  width: 40px; height: 22px;
  border: 1px solid var(--line-strong);
  border-radius: 99px;
  background: var(--surface-2);
  cursor: pointer;
  transition: background-color .2s, border-color .2s;
}
.switch::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--fg-dim);
  transition: transform .22s var(--ease-out), background-color .2s;
}
.switch[aria-checked="true"] { background: var(--accent); border-color: transparent; }
.switch[aria-checked="true"]::after { transform: translateX(18px); background: var(--accent-ink); }

.stat-readout {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--line);
  overflow: hidden;
}
.stat-readout div {
  padding: 12px;
  background: var(--surface-solid);
}
.stat-readout .n {
  font-family: var(--mono);
  font-size: var(--step-1);
  font-variant-numeric: tabular-nums;
}
.stat-readout .l {
  margin-top: 2px;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
}

.btn-row { display: flex; gap: 8px; flex-wrap: wrap; }
.btn-sm {
  padding: 8px 13px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-muted);
  font-family: var(--mono);
  font-size: var(--step--1);
  cursor: pointer;
  transition: color .16s, border-color .16s;
}
.btn-sm:hover { color: var(--fg); border-color: var(--fg-dim); }
.btn-sm.danger:hover { color: var(--warn); border-color: var(--warn); }

/* ================================================= 4c. command palette */

.palette-scrim {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: start center;
  padding-top: min(15vh, 140px);
  background: color-mix(in oklab, var(--bg-deep) 72%, transparent);
  backdrop-filter: blur(5px);
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s var(--ease-out), visibility .2s;
}
.palette-scrim.is-open { opacity: 1; visibility: visible; }

.palette {
  width: min(620px, calc(100vw - 32px));
  max-height: min(62vh, 560px);
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-solid);
  box-shadow: 0 32px 90px -30px #000c;
  transform: translateY(-10px) scale(.985);
  opacity: 0;
  transition: transform .22s var(--ease-out), opacity .22s var(--ease-out);
  overflow: hidden;
}
.palette-scrim.is-open .palette { transform: none; opacity: 1; }

.palette-input {
  width: 100%;
  padding: 16px 18px;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  color: var(--fg);
  font-family: var(--mono);
  font-size: var(--step-0);
}
.palette-input:focus { outline: none; }
.palette-input::placeholder { color: var(--fg-dim); }

.palette-list {
  list-style: none;
  overflow-y: auto;
  padding: 6px;
}
.palette-list li { border-radius: var(--radius-sm); }
.palette-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-muted);
  cursor: pointer;
  text-align: left;
  font-size: var(--step--1);
}
.palette-item .pi-kind {
  flex: none;
  width: 62px;
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.palette-item .pi-main { flex: 1 1 auto; min-width: 0; }
.palette-item .pi-title { color: var(--fg); font-weight: 500; }
.palette-item .pi-sub {
  color: var(--fg-dim);
  font-size: 11px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.palette-item[aria-selected="true"] { background: var(--accent-soft); }
.palette-item[aria-selected="true"] .pi-kind { color: var(--accent); }

.palette-foot {
  display: flex;
  gap: 16px;
  padding: 9px 14px;
  border-top: 1px solid var(--line);
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: 10px;
}
.palette-foot span { display: inline-flex; align-items: center; gap: 5px; }

/* =============================================================== 9. footer */

.site-foot {
  border-top: 1px solid var(--line);
  padding-block: var(--gap-4);
  color: var(--fg-dim);
  font-family: var(--mono);
  font-size: var(--step--1);
}
.foot-inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-3);
  align-items: center;
  justify-content: space-between;
}
.foot-links { display: flex; flex-wrap: wrap; gap: 16px; }
.foot-links a:hover { color: var(--accent); }

/* --- scroll progress --------------------------------------------------- */
.scroll-rail {
  position: fixed;
  left: 0; right: 0; top: 0;
  z-index: 70;
  height: 2px;
  background: transparent;
  pointer-events: none;
}
.scroll-rail i {
  display: block;
  height: 100%;
  width: var(--progress, 0%);
  background: linear-gradient(90deg, var(--accent), var(--accent-2), var(--accent-3));
  box-shadow: 0 0 12px var(--accent-glow);
}

/* --- toast ------------------------------------------------------------- */
.toast {
  position: fixed;
  left: 50%; bottom: 26px;
  z-index: 120;
  transform: translate(-50%, 18px);
  padding: 11px 18px;
  border: 1px solid var(--line-strong);
  border-radius: 99px;
  background: var(--surface-solid);
  color: var(--fg);
  font-family: var(--mono);
  font-size: var(--step--1);
  opacity: 0;
  visibility: hidden;
  transition: opacity .24s, transform .24s var(--ease-out), visibility .24s;
}
.toast.is-open { opacity: 1; visibility: visible; transform: translate(-50%, 0); }

/* ================================================ 10. motion & responsive */

/* Entrance animations are a progressive enhancement, never a prerequisite for
   reading the page. Content is visible by default; app.js sets
   [data-reveal="on"] on <html> only once it has a working IntersectionObserver
   AND has armed a failsafe timer that un-hides anything still hidden. If the
   observer never fires — old browser, odd embedding, a scripting error — the
   page degrades to plain visible content instead of eighty blank cards. */
.reveal {
  transition:
    opacity .7s var(--ease-out),
    transform .7s var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal="on"] .reveal {
  opacity: 0;
  transform: translateY(calc(18px * var(--motion)));
}
[data-reveal="on"] .reveal.in { opacity: 1; transform: none; }

/* Cards animate in on first paint only; re-renders after a search must not
   re-trigger the stagger, so app.js adds .in immediately for those. */
.card.reveal { transition-duration: .5s; }

@media (max-width: 860px) {
  .primary-nav { display: none; }
  .job { grid-template-columns: 1fr; gap: var(--gap-2); }
  .job-when { display: flex; flex-wrap: wrap; gap: 12px; }
  .job-when .dur, .job-when .loc { margin-top: 0; }
  .catalog-controls { top: 62px; }
  .theme-swatches { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  .hero-actions .btn { flex: 1 1 100%; justify-content: center; }
  .line-item { flex-direction: column; gap: 6px; }
  .line-item .when { width: auto; }
  .facet-legend { min-width: 100%; }
}

/* The visitor's OS preference is the starting point; app.js can override it
   in either direction and stores the result. --motion is what actually gates
   the animations, so both paths funnel through one variable. */
@media (prefers-reduced-motion: reduce) {
  :root { --motion: 0; }
  html { scroll-behavior: auto; }
}

[data-motion="off"] {
  --motion: 0;
}
[data-motion="off"] *,
[data-motion="off"] *::before,
[data-motion="off"] *::after {
  animation-duration: .001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .001ms !important;
  scroll-behavior: auto !important;
}
[data-motion="off"] .reveal,
[data-motion="off"][data-reveal="on"] .reveal { opacity: 1; transform: none; }

/* When the FX tier is "off" the canvases are never created; hide the stack so
   the grid and vignette do not sit on an empty layer. */
[data-fx="off"] .fx-layer { display: none; }

@media print {
  .fx-stack, .masthead, .catalog-controls, .drawer, .drawer-scrim,
  .palette-scrim, .scroll-rail, .toast { display: none !important; }
  body { background: #fff; color: #000; }
  .card, .job, .skill-card, .line-item { break-inside: avoid; border-color: #ccc; }
}
