/* ====== tokens ====== */
:root {
  --bg: #F2F4F8;
  --bg-raised: #FFFFFF;
  --ink: #0C1430;
  --ink-soft: #4A5470;
  --cobalt: #2B50E0;
  --cobalt-deep: #1D3AA8;
  --teal: #0B7372;
  --sand: #E4A93C;
  --line: #DCE1EB;
  --line-cool: #D8DEE9;
  --cobalt-hover: #1D3AA8;
  --band: #070D1F;          /* the dark sections (path, recommendations) */
  --stage: #070D1F;         /* the ground the films are lit for: hero, case films */
  --signal: #FFB547;        /* the request itself: the packet in the films, the hero full stop */
  --logo-dark: #141C2E;     /* chip behind white logo artwork */
  --logo-chip: #FFFFFF;     /* chip behind logos drawn for a light ground */
  --frost: rgba(242, 244, 248, .86);
  --frost-strong: rgba(242, 244, 248, .97);
  --surface-2: #E8EDF6;     /* skeleton screens, empty bar tracks */
  --surface-3: #F7F9FC;     /* inner boxes on a raised card */
  --skeleton: #C3CCDC;      /* placeholder lines in the diagrams */
  --muted-fill: #B9C3D6;
  --float-btn: rgba(255, 255, 255, .85);
  --highlight: rgba(43, 80, 224, .16);
  --paper: #F7F8FB;
  --paper-line: #E1E5EE;
  --quote-ink: #1E2638;
  --sand-ink: #8A5A0B;     /* sand as text on a light ground */
  --dot: #7D879A;           /* inactive carousel dots: 3:1 against the card */
  --radius: 12px;
  --shadow-card: 0 1px 2px rgba(20, 28, 46, .05), 0 8px 24px rgba(20, 28, 46, .05);
  --shadow-lift: 0 2px 4px rgba(20, 28, 46, .06), 0 16px 36px rgba(20, 28, 46, .09);
  --shadow-pop: 0 14px 34px rgba(20, 28, 46, .16);
  color-scheme: light;
  --font: "Archivo", system-ui, -apple-system, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, monospace;
}

/* ====== dark theme ======
   Set on <html> by the inline script in <head>: the visitor's choice if they
   made one, otherwise their system setting. */
:root[data-theme="dark"] {
  --bg: #0A1124;
  --bg-raised: #111A33;
  --ink: #E9EDF6;
  --ink-soft: #9AA6C2;
  --cobalt: #5B7BFF;
  --cobalt-deep: #9DB0FF;
  --cobalt-hover: #5A78FF;
  --teal: #3DB5A3;
  --sand: #E9B354;
  --line: #222D4D;
  --line-cool: #222D4D;
  --band: #070D1F;
  --logo-dark: #0A0E17;
  --logo-chip: #F2F4F8;
  --frost: rgba(10, 17, 36, .86);
  --frost-strong: rgba(10, 17, 36, .97);
  --surface-2: #232C40;
  --surface-3: #1D2536;
  --skeleton: #3A465F;
  --muted-fill: #4B5874;
  --float-btn: rgba(23, 30, 46, .88);
  --highlight: rgba(111, 140, 255, .22);
  --paper: #111A33;
  --paper-line: #26315A;
  --quote-ink: #E4E9F2;
  --sand-ink: #E9B354;
  --dot: #66738F;
  --shadow-card: 0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px rgba(0, 0, 0, .22);
  --shadow-lift: 0 2px 4px rgba(0, 0, 0, .3), 0 16px 36px rgba(0, 0, 0, .35);
  --shadow-pop: 0 14px 34px rgba(0, 0, 0, .45);
  color-scheme: dark;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--ink);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3 {
  text-wrap: balance;
  font-variation-settings: "wdth" 125;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.025em;
}

a { color: inherit; }

:focus-visible {
  outline: 3px solid var(--cobalt);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--bg); padding: .6rem 1rem; z-index: 99;
}
.skip:focus { left: 1rem; top: 1rem; }

.accent { color: var(--cobalt); }

/* ====== header ====== */
.top {
  display: flex; justify-content: space-between; align-items: center;
  max-width: 1180px; margin: 0 auto;
  padding: 1.4rem 2rem;
  position: sticky; top: 0; z-index: 50;
  transition: padding .25s ease;
}
/* the bar itself is only as wide as the content, so a full-bleed layer behind it
   carries the frosted ground once the page scrolls */
.top::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: calc(50% - 50vw); right: calc(50% - 50vw);
  background: var(--frost);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  z-index: -1;
  opacity: 0;
  transition: opacity .25s ease;
}
.top.is-stuck { padding-top: .75rem; padding-bottom: .75rem; }
.top.is-stuck::before { opacity: 1; }
/* reading progress, a hairline along the bottom of the bar */
.top-progress {
  position: absolute;
  left: calc(50% - 50vw);
  bottom: -1px;
  width: 100vw; height: 2px;
  background: var(--cobalt);
  transform-origin: 0 50%;
  transform: scaleX(var(--p, 0));
  opacity: 0;
  transition: opacity .25s ease;
}
.top.is-stuck .top-progress { opacity: 1; }
body { overflow-x: clip; }
section[id], footer[id] { scroll-margin-top: 4.5rem; }
.mark {
  font-variation-settings: "wdth" 125;
  font-weight: 900; font-size: 1.5rem; text-decoration: none;
}
.mark-dot { color: var(--cobalt); }
.top nav { display: flex; gap: 1.8rem; align-items: center; position: relative; }
.top nav a {
  text-decoration: none; font-weight: 600; font-size: .95rem;
  color: var(--ink-soft);
  border-bottom: 2px solid transparent;
  padding-bottom: 2px;
  transition: color .15s, border-color .15s;
}
.top nav a:hover { color: var(--ink); border-color: var(--cobalt); }
.top nav a.is-active { color: var(--ink); border-color: var(--cobalt); }
/* over the filmed hero the bar reads light on dark, until it sticks and frosts */
:root { --top-h: 5.1rem; }
body:has(> .hero) .top:not(.is-stuck) {
  --ink: #FFFFFF; --ink-soft: rgba(233, 237, 246, .78); --line: rgba(233, 237, 246, .3);
  --bg-raised: rgba(255, 255, 255, .06); --float-btn: rgba(255, 255, 255, .08); --cobalt-deep: #A9B9FF;
  color: var(--ink);
}

/* ====== hero: the filmed request, full bleed ======
   Always on the dark stage in both themes, since the film is lit for it. The
   tokens are re-pointed inside it so the shared pieces (pill, buttons, the
   "now" line) turn light without their own dark variants. */
.hero {
  --ink: #E9EDF6; --ink-soft: #B3BDD6; --line: rgba(233, 237, 246, .28);
  --bg-raised: rgba(7, 13, 31, .45); --teal: #3DD6C2; --cobalt-deep: #A9B9FF;
  position: relative; isolation: isolate; overflow: hidden;
  margin-top: calc(-1 * var(--top-h));
  min-height: min(100svh, 960px);
  display: flex; align-items: center;
  padding: calc(var(--top-h) + 2rem) max(2rem, calc((100vw - 1180px) / 2 + 2rem)) 3.2rem;
  background: var(--stage);
  color: var(--ink);
}
.hero-film {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 70% 50%;
  animation: filmin 1.6s cubic-bezier(.2,.7,.2,1) both;
}
@keyframes filmin { from { opacity: 0; transform: scale(1.05); } }
/* the copy keeps its own dark ground on the left; the film owns the right */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(90deg, rgba(7, 13, 31, .96) 0%, rgba(7, 13, 31, .86) 34%, rgba(7, 13, 31, .3) 50%, rgba(7, 13, 31, 0) 62%),
    linear-gradient(0deg, var(--stage) 0%, rgba(7, 13, 31, 0) 20%);
}
.hero-copy { max-width: 46rem; display: flex; flex-direction: column; align-items: flex-start; }
.hero-hello { order: 0; }
.hero h1 { order: 1; }
.hero-lede { order: 2; }
.hero-actions { order: 3; }
.hero-avail { order: 4; }
.hero-now { order: 5; }
.hero-hello {
  color: var(--ink-soft); font-size: .95rem; margin-bottom: 1.4rem;
  display: flex; align-items: center; gap: .8rem;
}
.hero-avatar {
  width: 44px; height: 44px; border-radius: 50%;
  object-fit: cover; object-position: 50% 12%;
  border: 2px solid var(--stage);
  box-shadow: 0 0 0 2px var(--signal);
  flex-shrink: 0;
}
.hero h1 {
  font-size: clamp(3.2rem, 6.6vw, 6.4rem);
  line-height: .9;
  letter-spacing: -.035em;
  color: #FFFFFF;
  margin-bottom: 1.4rem;
}
.hero h1 .accent { color: var(--signal); }
.hero-lede {
  max-width: 31rem;
  color: var(--ink-soft);
  font-size: 1.1rem;
  margin-bottom: 1.8rem;
}
.hero-actions { display: flex; gap: .9rem; flex-wrap: wrap; align-items: center; margin-bottom: 1.6rem; }
.hero .btn-ghost { color: #FFFFFF; }
.hero .btn-ghost:hover { border-color: #FFFFFF; }
/* the address is a link, not a third button — two buttons is a choice, three is a menu */
.hero-mail {
  font-size: .92rem;
  color: var(--ink-soft);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 4px;
  padding: .5rem .2rem;
  transition: color .15s, text-decoration-color .15s;
}
.hero-mail:hover { color: #FFFFFF; text-decoration-color: var(--signal); }

.btn {
  display: inline-block;
  padding: .78rem 1.4rem;
  border-radius: 10px;
  text-decoration: none;
  font-weight: 700;
  font-size: .98rem;
  transition: transform .15s, box-shadow .15s, background .15s;
}
.btn-solid {
  background: var(--cobalt); color: #fff;
  box-shadow: 0 1px 0 rgba(20, 28, 46, .18);
}
.btn-solid:hover { background: var(--cobalt-hover); transform: translateY(-1px); }
.btn-ghost {
  border: 1.5px solid var(--line); color: var(--ink);
  background: var(--bg-raised);
}
.btn-ghost:hover { border-color: var(--cobalt); transform: translateY(-1px); }

/* hero entrance — one orchestrated moment */
.hero-copy > * { opacity: 0; transform: translateY(14px); animation: rise .8s cubic-bezier(.2,.7,.2,1) forwards; }
.hero-copy > :nth-child(1) { animation-delay: .25s; }
.hero-copy > :nth-child(2) { animation-delay: .35s; }
.hero-copy > :nth-child(3) { animation-delay: .5s; }
.hero-copy > :nth-child(4) { animation-delay: .62s; }
.hero-copy > :nth-child(5) { animation-delay: .72s; }
@keyframes rise { to { opacity: 1; transform: none; } }

/* platform schematic: a wire warms while a request rides it, a node pulses when reached */
.arch-wire[data-hot="a"] { stroke: rgba(43, 80, 224, .6); }
.arch-wire[data-hot="b"] { stroke: rgba(14, 124, 123, .6); }
.arch-wire[data-hot="c"], .arch-grpc[data-hot="c"] { stroke: rgba(228, 169, 60, .85); opacity: 1; }
.arch-node { transform-box: fill-box; transform-origin: 50% 50%; transition: transform .28s cubic-bezier(.3, 1.6, .5, 1); }
.arch-node.is-hit { transform: scale(1.05); }
.arch-node.is-hit rect { stroke: var(--cobalt); }

/* ====== proof line ====== */
.proof {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--bg-raised);
}
.proof p {
  max-width: 1040px; margin: 0 auto;
  padding: 3.6rem 2rem;
  font-size: clamp(1.35rem, 2.5vw, 2.05rem);
  line-height: 1.38;
  font-weight: 600;
  letter-spacing: -.012em;
  font-variation-settings: "wdth" 108;
}
.proof em {
  font-style: normal;
  font-weight: 800;
  color: var(--cobalt-deep);
  white-space: nowrap;
}

/* ====== at a glance ====== */
.glance {
  max-width: 1180px;
  margin: 0 auto;
  padding: 3.5rem 2rem 1rem;
}
.glance h2 {
  font-size: clamp(1.4rem, 2.2vw, 1.7rem);
  margin-bottom: 1.8rem;
}
.glance-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  border-top: 1px solid var(--line);
}
.glance-grid > div {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr);
  gap: 1.2rem;
  align-items: baseline;
  padding: .85rem 1.4rem .85rem 0;
  border-bottom: 1px solid var(--line);
}
.glance-grid dt {
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--teal);
}
.glance-grid dd {
  font-size: .95rem;
  color: var(--ink-soft);
}

/* ====== work ====== */
.work { max-width: 1180px; margin: 0 auto; padding: 6rem 2rem 2rem; }
.work h2, .lab h2, .path h2, .says h2, .hire h2 {
  font-size: clamp(2.4rem, 5.6vw, 4.8rem);
  line-height: .95;
  letter-spacing: -.035em;
  margin-bottom: 2.6rem;
}

/* A case is a chapter: its film across the top, the story on one side, the
   evidence (diagrams, carousels, load bars) on the other. The visual column
   is display: contents so the film and each widget are items of this grid. */
.case {
  scroll-margin-top: 5.5rem;
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  column-gap: 3.5rem;
  row-gap: 1.4rem;
  align-items: start;
  padding: 4.5rem 0;
  border-top: 1px solid var(--line);
}
.case-visual { display: contents; }
.case-visual > * { grid-column: 2; min-width: 0; }
.case-text { grid-column: 1; grid-row: 2 / span 2; }
.case:not(:has(.reel-widget)) .case-text { grid-row: 1 / span 2; }
.case-visual > .reel-widget { grid-column: 1 / -1; grid-row: 1; margin-bottom: 1.8rem; }
.case-flip .case-text { grid-column: 2; }
.case-flip .case-visual > * { grid-column: 1; }
.case-flip .case-visual > .reel-widget { grid-column: 1 / -1; }

.case-role {
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--teal);
  margin-bottom: .7rem;
}
.case h3 { font-size: clamp(2rem, 3.6vw, 3rem); line-height: .98; margin-bottom: 1.2rem; }
.case-title-logo { display: flex; flex-direction: column; align-items: flex-start; gap: 1rem; }
.case-title-logo img { width: 44px; height: 44px; object-fit: contain; }
.case-text p { color: var(--ink-soft); margin-bottom: 1rem; max-width: 38rem; }

.case-stack {
  list-style: none;
  display: flex; flex-wrap: wrap; gap: .5rem;
  margin-top: 1.2rem;
}
.case-stack li {
  font-family: var(--mono);
  font-size: .78rem;
  padding: .3rem .7rem;
  border: 1.5px solid var(--line);
  border-radius: 999px;
  color: var(--ink-soft);
  background: var(--bg-raised);
}

/* --- case visuals --- */
.case-visual > div {
  background: var(--bg-raised);
  border: 1.5px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  box-shadow: var(--shadow-card);
}
.widget-title {
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--ink-soft);
  margin-bottom: 1rem;
}
.widget-foot {
  font-size: .82rem;
  color: var(--ink-soft);
  margin-top: 1rem;
}

.chalet-brand {
  background: var(--logo-dark);
  border-radius: 10px;
  padding: .9rem 1.2rem;
  margin-bottom: 1.2rem;
  display: flex; justify-content: center;
}
.chalet-brand img { height: 52px; width: auto; }

/* load bars */
.loadbar {
  display: grid;
  grid-template-columns: 3.4rem 1fr 4.4rem;
  align-items: center;
  gap: .7rem;
  margin-bottom: .9rem;
}
.loadbar-name { font-family: var(--mono); font-size: .78rem; color: var(--ink-soft); }
.loadbar-val { font-weight: 800; font-size: .95rem; text-align: right; }
.loadbar-track {
  height: 14px;
  background: var(--surface-2);
  border-radius: 999px;
  overflow: hidden;
}
.loadbar-fill {
  height: 100%;
  width: 0;
  border-radius: 999px;
  transition: width 1.1s cubic-bezier(.2,.7,.2,1);
}
.fill-before { background: var(--muted-fill); }
.fill-after { background: var(--cobalt); transition-delay: .35s; }
.in-view .loadbar-fill { width: var(--w); }

/* code widget */
.code-widget pre {
  font-family: var(--mono);
  font-size: .8rem;
  line-height: 1.7;
  overflow-x: auto;
  color: var(--ink);
}
.c-kw { color: var(--cobalt-deep); font-weight: 500; }
.c-str { color: var(--teal); }
.c-fn { color: #A4680B; }

/* score widget */
.case-visual > .widget-dark {
  background: #10263F;
  border-color: #22405F;
}
.widget-dark .widget-title { color: #93A9C4; margin-bottom: 0; }
.score-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 1.1rem;
}
.soc-crest { width: 72px; height: 72px; object-fit: cover; border-radius: 14px; }
/* width: 100% so the frame has a size before its lazy image loads; otherwise the
   centred flex slide shrinks it to 0, no height is reserved, and the page jumps */
.phone-frame {
  width: 100%;
  max-width: 250px; margin: 0 auto;
  border: 6px solid #050B14;
  border-radius: 26px;
  overflow: hidden;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
}
.phone-frame img { display: block; width: 100%; height: auto; }

/* browser-shot frame (Chalet Montagne — desktop pages) */
.shot-frame {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  background: #0B1220;
  box-shadow: 0 8px 22px rgba(21, 34, 56, .14);
}
.shot-frame img { display: block; width: 100%; height: auto; }

/* stacked evidence is spaced by the case grid's row gap */
.case-visual > div + div { margin-top: 0; }

/* honest scope line under a carousel */
.carousel-note {
  font-family: var(--mono);
  font-size: .72rem;
  color: var(--ink-soft);
  text-align: center;
  margin-top: .7rem;
}
.widget-dark .carousel-note { color: #7E93AE; }
/* centred under a centred carousel, like the dark widget's own foot */
.shots-widget .widget-foot { text-align: center; }
.widget-foot-dark { color: #93A9C4; text-align: center; }
/* warehouse widget */
.wh-photo {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
  border: 1px solid var(--line);
}

/* screenshot carousel (SmartCare, SOC Rugby) */
.carousel { position: relative; margin-top: .4rem; min-width: 0; }
.carousel-viewport {
  overflow: hidden;
  min-width: 0;
  touch-action: pan-y;   /* let the page scroll vertically, we handle the swipe */
}
.carousel-track {
  display: flex;
  list-style: none;
  transition: transform .45s cubic-bezier(.2, .7, .2, 1);
}
.carousel-slide {
  flex: 0 0 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.carousel-cap {
  font-family: var(--mono);
  font-size: .74rem;
  color: var(--ink-soft);
  text-align: center;
  margin-top: .8rem;
  min-height: 2.2em;
}
.carousel-btn {
  position: absolute;
  top: 42%;
  transform: translateY(-50%);
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 1.5px solid var(--line);
  background: var(--float-btn);
  color: var(--ink);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.carousel-btn:hover { border-color: var(--cobalt); background: var(--bg-raised); }
.carousel-prev { left: -8px; }
.carousel-next { right: -8px; }
.carousel-dots {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: .5rem;
}
/* 7px dot, but a 22px touch target around it */
.carousel-dots button {
  width: 22px; height: 22px;
  padding: 0;
  border: 0;
  background: none;
  display: grid;
  place-items: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.carousel-dots button::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--dot);
  transition: background .15s, transform .15s;
}
.carousel-dots button[aria-current="true"]::before {
  background: var(--cobalt);
  transform: scale(1.25);
}

/* carousel on a dark widget (SOC Rugby) */
.widget-dark .carousel-cap { color: #93A9C4; }
.widget-dark .carousel-btn {
  border-color: #2C4A6B;
  background: rgba(5, 11, 20, .72);
  color: #F3EBD5;
}
.widget-dark .carousel-btn:hover { border-color: #D9C289; background: #050B14; }
.widget-dark .carousel-dots button::before { background: #5B7DA3; }
.widget-dark .carousel-dots button[aria-current="true"]::before { background: #D9C289; }

/* event proof strip (SOC Rugby) */
.case-proof {
  grid-column: 1 / -1;
  margin-top: 2rem;
  padding-top: 1.6rem;
  border-top: 1px dashed var(--line);
}
.case-proof-label {
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--ink-soft) !important;
  margin-bottom: 1rem;
  max-width: none !important;
}
.case-proof-shots {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .9rem;
}
.case-proof-shots img {
  width: 100%;
  height: 260px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--line);
}

/* ====== lab ====== */
.lab { max-width: 1180px; margin: 0 auto; padding: 6rem 2rem; }
.lab-lede { color: var(--ink-soft); max-width: 34rem; margin: -1.6rem 0 2.4rem; }
.lab-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.2rem;
}
.lab-item {
  border-top: 2px solid var(--ink);
  padding: 1.1rem 0 0;
  transition: border-color .18s;
}
.lab-item:hover h3 { color: var(--teal); }
.lab-item h3 { transition: color .18s; }
.lab-item h3 { font-size: 1.25rem; margin-bottom: .7rem; }
.lab-item p { color: var(--ink-soft); font-size: .95rem; }
.lab-tags {
  font-family: var(--mono);
  font-size: .75rem !important;
  color: var(--teal) !important;
  margin-top: 1rem;
}

/* ====== path ====== */
.path {
  background: var(--band);
  color: #EDF1F8;
}
.path > * { max-width: 1180px; margin-left: auto; margin-right: auto; }
.path { padding: 6rem 2rem 6rem; }
.path h2 { color: #fff; }
.timeline { list-style: none; }
.timeline li {
  display: grid;
  grid-template-columns: 9rem minmax(0, 1fr);
  gap: 2rem;
  padding: 1.6rem 0;
  border-top: 1px solid rgba(237, 241, 248, .16);
  position: relative;
}
.tl-when {
  font-family: var(--mono);
  font-size: .82rem;
  color: var(--sand);
  padding-top: .25rem;
}
.timeline h3 { font-size: 1.2rem; margin-bottom: .5rem; color: #fff; }
.timeline p { color: #A8B4CC; font-size: .95rem; max-width: 40rem; }
.tl-photos {
  display: flex; gap: .8rem; flex-wrap: wrap;
  margin-top: 1.1rem; max-width: 40rem;
}
.tl-photos img {
  flex: 1 1 240px; min-width: 0;
  height: 170px; object-fit: cover;
  border-radius: 10px;
  border: 1px solid rgba(237, 241, 248, .18);
}
.tl-caption {
  font-family: var(--mono);
  font-size: .75rem !important;
  color: #7E8CA8 !important;
  margin-top: .6rem;
}
.timeline .tl-when { color: var(--sand); }

/* ====== contact ====== */
.contact {
  max-width: 1180px; margin: 0 auto;
  padding: 5rem 2rem 4rem;
  text-align: center;
}
.avail-badge {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--mono); font-size: .78rem;
  color: var(--teal);
  border: 1.5px solid var(--teal);
  border-radius: 999px;
  padding: .35rem .9rem;
  margin-bottom: 1.2rem;
  background: var(--bg-raised);
}
.avail-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--teal);
}
.btn-call {
  border: 2px solid var(--cobalt); color: var(--cobalt-deep);
  background: var(--bg-raised);
  font-variant-numeric: tabular-nums;
}
.btn-call:hover { background: var(--cobalt); color: #fff; transform: translateY(-2px); }
.contact-links-secondary { margin-top: .9rem; }
.contact-meta a {
  color: inherit;
  display: inline-block;
  padding: .4rem .2rem;
}
.contact-photo {
  display: block; margin-left: auto; margin-right: auto;
  width: 128px; height: 128px; border-radius: 50%;
  object-fit: cover; object-position: 50% 12%;
  border: 3px solid var(--bg-raised);
  box-shadow: 0 0 0 3px var(--cobalt), 0 14px 34px rgba(21, 34, 56, .18);
  margin-bottom: 1.6rem;
}
.contact h2 { font-size: clamp(2.4rem, 5.6vw, 4.8rem); line-height: .95; letter-spacing: -.035em; margin-bottom: 1.2rem; }
.contact-lede { color: var(--ink-soft); max-width: 30rem; margin: 0 auto 2rem; }
.contact-links { display: flex; gap: .9rem; justify-content: center; flex-wrap: wrap; }
.contact-meta {
  margin-top: 2.5rem;
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--ink-soft);
}

/* ====== nav extras: CV + language ====== */
.nav-cv, .nav-lang {
  border: 1.5px solid var(--line);
  border-radius: 999px;
  padding: .3rem .75rem !important;
  border-bottom-color: var(--line) !important;
}
.nav-cv:hover, .nav-lang:hover { border-color: var(--cobalt) !important; color: var(--cobalt-deep); }
.nav-lang { font-family: var(--mono); font-size: .78rem; }

/* ====== hero availability ====== */
.hero-avail {
  display: inline-flex; align-items: center; gap: .55rem;
  font-size: .86rem; font-weight: 600; line-height: 1.35;
  color: var(--teal);
  border: 1.5px solid var(--teal);
  border-radius: 999px;
  padding: .35rem .9rem;
  margin-bottom: 1.4rem;
  background: var(--bg-raised);
}

/* ====== trust strip ====== */
.clients { max-width: 1180px; margin: 0 auto; padding: 2.6rem 2rem 0; }
.clients-label {
  font-size: .95rem; font-weight: 600;
  color: var(--ink-soft); margin-bottom: 1rem;
}
.clients-row {
  list-style: none;
  display: flex; flex-wrap: wrap; align-items: stretch;
  gap: 1rem;
  padding-bottom: 2.4rem;
  border-bottom: 1px solid var(--line);
}
.clients-row li {
  display: grid; place-items: center;
  min-width: 132px;
  padding: .7rem 1.1rem;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  background: var(--logo-chip);
  transition: border-color .18s, transform .18s;
}
.clients-row li:hover { border-color: var(--cobalt); transform: translateY(-2px); }
/* the chalet mark is white artwork, so it gets the dark chip it was drawn for */
.clients-row li.on-dark { background: var(--logo-dark); border-color: var(--logo-dark); }
.clients-row img {
  height: 34px; width: auto; max-width: 140px;
  object-fit: contain;
}
.clients-row .logo-crest { border-radius: 6px; }

/* ====== case outcome line ====== */
.case-outcome {
  border-left: 3px solid var(--cobalt);
  padding-left: .9rem;
  margin-bottom: 1.2rem !important;
}
.case-outcome b { color: var(--ink); }

/* ====== recommendations ======
   A dark band, so the only section written by other people reads as its own
   moment. The recommendations sit on it as paper records: who wrote it, for
   which project, their exact words, and where to check them. The first is the
   paying client, so it gets the full width. */
.says {
  position: relative;
  background: var(--band);
  color: #EDF1F8;
  padding: 5rem 2rem 5.2rem;
  margin-top: 4rem;
  overflow: hidden;
}
/* one warm light source, top-left, so the band has depth without a gradient wash */
.says::before {
  content: "";
  position: absolute;
  top: -35%; left: -10%;
  width: 60%; height: 130%;
  background: radial-gradient(closest-side, rgba(228, 169, 60, .10), transparent 70%);
  pointer-events: none;
}
.says-head, .says-grid { position: relative; max-width: 1180px; margin-left: auto; margin-right: auto; }
.says-head { margin-bottom: 2.6rem; }
.says h2 { color: #fff; margin-bottom: .9rem; }
.says-lede { color: #A2AEC6; max-width: 42rem; }
.says-verify {
  color: #F3EBD5;
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: rgba(228, 169, 60, .55);
  text-underline-offset: 4px;
  white-space: nowrap;
  transition: text-decoration-color .15s, color .15s;
}
.says-verify::after { content: " \2197"; }
.says-verify:hover { color: #fff; text-decoration-color: var(--sand); }

.says-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.4rem;
  align-items: stretch;
}

.say {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  border-radius: 14px;
  padding: 1.6rem 1.7rem 1.3rem;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 18px 40px rgba(0, 0, 0, .28);
  transition: transform .25s cubic-bezier(.2,.7,.2,1), box-shadow .25s;
}
@media (hover: hover) {
  .say:hover { transform: translateY(-3px); box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 24px 50px rgba(0, 0, 0, .34); }
}

/* who wrote it: the company's mark, the person, and how we worked together */
.say-who {
  display: flex;
  align-items: center;
  gap: .95rem;
  padding-bottom: 1.1rem;
  margin-bottom: 1.2rem;
  border-bottom: 1px dashed var(--paper-line);
}
.say-logo {
  flex-shrink: 0;
  display: grid; place-items: center;
  height: 54px; min-width: 54px;
  padding: 8px;
  background: var(--logo-chip);
  border: 1px solid var(--paper-line);
  border-radius: 12px;
}
.say-logo img { display: block; height: 36px; width: auto; max-width: 104px; object-fit: contain; }
/* the chalet mark is white artwork, drawn for a dark ground */
.say-logo-dark { background: var(--logo-dark); border-color: var(--logo-dark); padding: 8px 12px; }
.say-id { display: flex; flex-direction: column; min-width: 0; }
.say-name {
  font-weight: 800;
  font-size: 1.05rem;
  font-variation-settings: "wdth" 112;
  letter-spacing: -.01em;
  color: var(--ink);
  text-decoration: none;
  align-self: flex-start;
}
a.say-name { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 3px; transition: text-decoration-color .15s, color .15s; }
a.say-name::after { content: " \2197"; font-weight: 400; color: var(--ink-soft); font-size: .85em; }
a.say-name:hover { color: var(--cobalt-deep); text-decoration-color: var(--cobalt); }
.say-role { font-size: .86rem; color: var(--ink-soft); line-height: 1.4; margin-top: .1rem; }
.say-rel {
  font-family: var(--mono);
  font-size: .7rem;
  color: var(--teal);
  margin-top: .35rem;
}

/* their words: a serif for someone else's voice, with the quotation marks of
   the language it was written in */
.say blockquote p {
  font-family: "Iowan Old Style", "Charter", "Palatino Linotype", Georgia, serif;
  font-size: 1.06rem;
  line-height: 1.62;
  color: var(--quote-ink);
  text-wrap: pretty;
}
.say blockquote[lang="en"] p::before { content: "\201C"; }
.say blockquote[lang="en"] p::after { content: "\201D"; }
.say blockquote[lang="fr"] p::before { content: "\00AB\00A0"; }
.say blockquote[lang="fr"] p::after { content: "\00A0\00BB"; }

/* where it comes from, so a reader can check it */
.say-src {
  margin-top: auto;
  padding-top: 1.2rem;
  display: flex; align-items: center; flex-wrap: wrap; gap: .3rem;
  font-family: var(--mono);
  font-size: .7rem;
  color: var(--ink-soft);
}
.say-src::before {
  content: "in";
  display: inline-grid; place-items: center;
  width: 16px; height: 16px;
  margin-right: .3rem;
  border-radius: 3px;
  background: #0A66C2;
  color: #fff;
  font: 700 .62rem/1 var(--font);
}

/* the lead: attribution on the left, the quote given the room on the right */
.say-lead {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  grid-template-rows: auto auto 1fr;
  column-gap: 2.4rem;
  padding: 2.1rem 2.2rem 1.8rem;
}
.say-lead .say-who {
  grid-column: 1; grid-row: 1 / -1;
  flex-direction: column; align-items: flex-start; gap: 1rem;
  margin: 0; padding: 0 2rem 0 0;
  border-bottom: 0;
  border-right: 1px dashed var(--paper-line);
}
.say-lead blockquote, .say-lead .say-tr, .say-lead .say-src { grid-column: 2; }
.say-lead blockquote p { font-size: clamp(1.14rem, 1.6vw, 1.36rem); line-height: 1.55; }
.say-lead .say-src { align-self: end; }

/* the translation is there for readers who need it, folded away for those who do not */
.say-tr { margin-top: 1rem; }
.say-tr summary {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-family: var(--mono);
  font-size: .7rem;
  letter-spacing: .04em;
  color: var(--ink-soft);
  cursor: pointer;
  list-style: none;
  padding: .32rem .7rem;
  border: 1px solid var(--paper-line);
  border-radius: 999px;
  transition: color .15s, border-color .15s, background .15s;
}
.say-tr summary::-webkit-details-marker { display: none; }
.say-tr summary::before { content: "+"; color: currentColor; }
.say-tr[open] summary::before { content: "\2212"; }
.say-tr summary:hover { color: var(--ink); border-color: var(--cobalt); background: var(--bg-raised); }
.say-tr p {
  font-size: .9rem;
  line-height: 1.6;
  color: var(--ink-soft);
  margin-top: .8rem;
  padding-left: 1rem;
  border-left: 2px solid var(--paper-line);
}

/* ====== hire lanes ====== */
.hire { max-width: 1180px; margin: 0 auto; padding: 6rem 2rem 0; }
.hire h2 { margin-bottom: 2.4rem; }
.hire-lede { color: var(--ink-soft); max-width: 34rem; margin-bottom: 2.2rem; }
.hire-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2.6rem;
}
.lane {
  border-top: 2px solid var(--ink);
  padding: 1.2rem 0 0;
  display: flex;
  flex-direction: column;
}
.lane-kicker {
  font-size: .95rem; font-weight: 600;
  color: var(--cobalt-deep);
  margin-bottom: .6rem;
}
.lane h3 { font-size: 1.35rem; margin-bottom: 1.2rem; }
.lane-facts { margin-bottom: 1.6rem; }
.lane-facts > div {
  display: grid;
  grid-template-columns: 9.5rem minmax(0, 1fr);
  gap: 1rem;
  padding: .7rem 0;
  border-top: 1px solid var(--line);
}
.lane-facts dt {
  font-family: var(--mono); font-size: .76rem;
  color: var(--ink-soft);
  padding-top: .1rem;
}
.lane-facts dd { font-size: .95rem; }
.lane-actions {
  display: flex; gap: .7rem; flex-wrap: wrap;
  margin-top: auto;
}
.lane-actions .btn { font-size: .92rem; padding: .7rem 1.2rem; }

.howiwork {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
  margin-top: 1.4rem;
}
.howiwork li {
  border-top: 3px solid var(--teal);
  padding-top: .8rem;
}
.howiwork b { display: block; font-size: .95rem; margin-bottom: .2rem; }
.howiwork span { color: var(--ink-soft); font-size: .85rem; }

/* ====== sticky dock (small screens only) ====== */
.dock { display: none; }

/* ====== scroll reveal (JS adds .in-view) ======
   --i staggers siblings that arrive together (glance rows, lab items, lanes) */
.reveal {
  opacity: 0; transform: translateY(18px);
  transition: opacity .6s, transform .6s cubic-bezier(.2,.7,.2,1);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.reveal.in-view { opacity: 1; transform: none; }

/* stack chips settle in one after another once their case is in view */
.case.reveal .case-stack li {
  opacity: 0; transform: translateY(6px);
  transition: opacity .35s, transform .35s cubic-bezier(.2,.7,.2,1), border-color .15s;
  transition-delay: calc(.35s + var(--i, 0) * 45ms);
}
.case.reveal.in-view .case-stack li { opacity: 1; transform: none; }
.case-stack li:hover { border-color: var(--cobalt); }

/* case cards lift a little under the pointer */
.case-visual > div { transition: transform .25s ease, box-shadow .25s ease; }
@media (hover: hover) {
  .case-visual > div:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-lift);
  }
}

/* proof numbers count up; tabular figures keep the line from jittering */
[data-count] { font-variant-numeric: tabular-nums; }

/* a plain text link under a case, to the live product */
.case-link { margin-bottom: 1rem !important; }
.case-link a {
  font-weight: 700;
  color: var(--cobalt-deep);
  text-decoration: underline;
  text-decoration-color: rgba(43, 80, 224, .35);
  text-underline-offset: 4px;
  transition: text-decoration-color .15s;
}
.case-link a::after { content: " \2197"; }
.case-link a:hover { text-decoration-color: var(--cobalt); }

/* ====== platform case: architecture schematic ====== */
#archdiagram { width: 100%; height: auto; display: block; }
.arch-wire, .arch-grpc {
  fill: none;
  stroke: var(--line);
  stroke-width: 2.2;
  stroke-dasharray: 5 6;
}
.arch-grpc { stroke: var(--teal); opacity: .55; }
.in-view .arch-wire, .in-view .arch-grpc { animation: flow 1.6s linear infinite; }
@keyframes flow { to { stroke-dashoffset: -22; } }
.arch-node rect {
  fill: var(--bg-raised);
  stroke: var(--ink);
  stroke-width: 2;
  transition: stroke .15s;
}
.arch-gw rect { stroke: var(--cobalt); stroke-width: 2.4; }
.arch-svc rect { fill: var(--surface-3); }
.arch-node:hover rect { stroke: var(--cobalt); }
.arch-name {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  fill: var(--ink);
  text-anchor: middle;
}
.arch-sub {
  font-family: var(--mono);
  font-size: 10.5px;
  fill: var(--ink-soft);
  text-anchor: middle;
}
.arch-pkt { fill: var(--cobalt); opacity: 0; transition: opacity .25s; }
.arch-pkt-b { fill: var(--teal); }
.arch-pkt-g { fill: var(--sand); }

/* ====== platform case: monitoring feed ====== */
.mon-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 1rem;
}
.mon-live {
  display: inline-flex; align-items: center; gap: .45rem;
  font-family: var(--mono); font-size: .72rem;
  color: #8FD3C9;
}
.mon-dot { width: 7px; height: 7px; border-radius: 50%; background: #3FB8A6; }
.mon-feed { list-style: none; }
.mon-feed li {
  display: grid;
  grid-template-columns: 3rem 3.6rem minmax(0, 1fr) auto;
  gap: .6rem;
  align-items: baseline;
  font-family: var(--mono);
  font-size: .76rem;
  color: #C9D4E4;
  padding: .5rem 0;
  border-top: 1px solid rgba(237, 241, 248, .08);
}
.mon-feed li:first-child { border-top: 0; }
.mon-t { color: #8297B5; }
.mon-k { color: #93A9C4; }
.mon-ok { color: #6ED3C2; text-align: right; }
.mon-warn {
  color: #1B1405;
  background: var(--sand);
  border-radius: 999px;
  padding: .05rem .5rem;
  font-weight: 500;
  text-align: center;
}
/* rows arrive one by one, like a feed catching up */
.mon-widget.reveal .mon-feed li { opacity: 0; transform: translateY(6px); }
.mon-widget.reveal.in-view .mon-feed li {
  animation: feedin .45s cubic-bezier(.2,.7,.2,1) forwards;
  animation-delay: calc(.4s + var(--i, 0) * .38s);
}
@keyframes feedin { to { opacity: 1; transform: none; } }
.mon-feed li.is-flag { background: linear-gradient(90deg, rgba(228, 169, 60, .10), transparent 70%); }

/* ====== language hint (JS-built, dismissible) ====== */
.lang-hint {
  position: fixed;
  right: 1.2rem; bottom: 1.2rem;
  z-index: 60;
  max-width: 21rem;
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  padding: .85rem 1rem;
  background: var(--bg-raised);
  border: 1.5px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  font-size: .9rem;
  animation: hintin .45s cubic-bezier(.2,.7,.2,1) both .9s;
}
.lang-hint p { flex: 1 1 100%; color: var(--ink-soft); }
.lang-hint .btn { font-size: .85rem; padding: .5rem .9rem; }
.lang-hint button {
  font: inherit; font-size: .85rem;
  background: none; border: 0; cursor: pointer;
  color: var(--ink-soft); text-decoration: underline; text-underline-offset: 3px;
}
@keyframes hintin { from { opacity: 0; transform: translateY(12px); } }

/* ====== motion layer ======
   Everything below is driven by script.js. Without JS (or with reduced motion)
   none of these classes appear and the page shows its final state. */

/* buttons: a press you can feel, and the work button points where it goes */
.btn { transition: transform .2s cubic-bezier(.2,.7,.2,1), box-shadow .15s, background .15s, border-color .15s; }
.btn:active { transform: translateY(0) scale(.97); }
.hero-actions .btn-solid[href="#work"]::after {
  content: "\2193";
  display: inline-block;
  margin-left: .5rem;
  transition: transform .25s cubic-bezier(.2,.7,.2,1);
}
.hero-actions .btn-solid[href="#work"]:hover::after { transform: translateY(3px); }
.btn.magnet { transition: transform .3s cubic-bezier(.2,.7,.2,1), background .15s; }

/* rendered films (assets/motion, built by tools/render-motion.py); script.js plays them in view */
.reel { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; background: var(--stage); }
.case-visual > .reel-widget {
  padding: 0; border: 0; overflow: hidden;
  border-radius: 22px;
  background: var(--stage);
  box-shadow: 0 40px 80px -30px rgba(7, 13, 31, .55);
}
[data-theme="dark"] .case-visual > .reel-widget { box-shadow: 0 0 0 1px var(--line), 0 40px 80px -30px rgba(0, 0, 0, .7); }

/* section headings also rise word by word, after their running number */
.reveal.split { --split-delay: .15s; }

/* headlines rise word by word out of their own line */
.split .w {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: .14em;
  margin-bottom: -.14em;
}
.split .w-i {
  display: inline-block;
  transform: translateY(108%);
  transition: transform 1s cubic-bezier(.2,.8,.2,1);
  transition-delay: calc(var(--split-delay, 0s) + var(--wi, 0) * 80ms);
}
.split.is-in .w-i { transform: none; }
.hero h1.split { animation: none; opacity: 1; transform: none; --split-delay: .1s; }
/* the full stop drops in last, like the request landing */
.hero h1 .accent { display: inline-block; }
.hero h1.split .accent {
  transform: translateY(-120%);
  transition: transform .55s cubic-bezier(.3,1.6,.5,1) .95s;
}
.hero h1.split.is-in .accent { transform: none; }

/* "available" dots breathe, so the badge reads as live */
.avail-dot, .mon-dot { position: relative; flex-shrink: 0; }
.avail-dot::after, .mon-dot::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  background: inherit;
  animation: ping 2.4s cubic-bezier(0,0,.2,1) infinite;
}
@keyframes ping {
  0% { transform: scale(1); opacity: .7; }
  80%, 100% { transform: scale(2.8); opacity: 0; }
}

/* proof numbers get underlined one after another */
.proof em {
  background: linear-gradient(var(--highlight), var(--highlight)) no-repeat 0 90% / 0 .4em;
  transition: background-size .7s cubic-bezier(.2,.7,.2,1);
  transition-delay: calc(.25s + var(--i, 0) * .2s);
}
.proof.in-view em { background-size: 100% .4em; }

/* lab: the rule above each item fills with colour under the pointer */
.lab-item { position: relative; }
.lab-item::before {
  content: "";
  position: absolute; left: 0; right: 0; top: -2px;
  height: 2px;
  background: var(--teal);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform .45s cubic-bezier(.2,.7,.2,1);
}
.lab-item:hover::before { transform: scaleX(1); }

/* load-time race: both bars start together, on one time scale */
.loadbar-val { font-variant-numeric: tabular-nums; }
.loadbar-widget.is-race .loadbar-fill { width: 0; transition-timing-function: linear; transition-delay: .25s; }
.loadbar-widget.is-race.is-running .loadbar-fill { width: var(--w); }
.loadbar-val.is-done { animation: settle .6s cubic-bezier(.3,1.6,.5,1); }
@keyframes settle { 40% { transform: scale(1.12); } }

/* monitoring: the flagged pill keeps asking for a look */
.mon-widget.in-view .mon-warn { animation: warn 2.6s ease-out 3.2s infinite; }
@keyframes warn {
  0% { box-shadow: 0 0 0 0 rgba(228, 169, 60, .55); }
  70%, 100% { box-shadow: 0 0 0 7px rgba(228, 169, 60, 0); }
}

/* carousel: the current dot stretches, and fills while autoplay waits */
.carousel-dots button { position: relative; }
.carousel-dots button::before { transition: width .3s cubic-bezier(.2,.7,.2,1), background .15s; }
.carousel-dots button[aria-current="true"]::before { width: 18px; border-radius: 999px; transform: none; }
.carousel.is-playing .carousel-dots button[aria-current="true"]::before { background: rgba(43, 80, 224, .22); }
.carousel.is-playing .carousel-dots button[aria-current="true"]::after {
  content: "";
  position: absolute;
  left: calc(50% - 9px); top: calc(50% - 3.5px);
  width: 18px; height: 7px;
  border-radius: 999px;
  background: var(--cobalt);
  transform-origin: 0 50%;
  animation: dotfill var(--autoplay, 5s) linear both;
}
.widget-dark .carousel.is-playing .carousel-dots button[aria-current="true"]::before { background: rgba(217, 194, 137, .25); }
.widget-dark .carousel.is-playing .carousel-dots button[aria-current="true"]::after { background: #D9C289; }
@keyframes dotfill { from { transform: scaleX(0); } }
.carousel-slide { transition: opacity .45s; }
.carousel-slide:not(.is-current) { opacity: .35; }

/* screenshots open full size */
.zoomable { cursor: zoom-in; transition: transform .5s cubic-bezier(.2,.7,.2,1); }
.phone-frame .zoomable:hover, .shot-frame .zoomable:hover { transform: scale(1.025); }
.zoomable:focus-visible { outline-offset: -3px; }

html.lb-open, html.menu-open { overflow: hidden; }
.lb {
  border: 0; padding: 0; margin: 0;
  width: 100vw; height: 100vh; height: 100dvh;
  max-width: none; max-height: none;
  background: transparent;
  color: #EDF1F8;
}
.lb::backdrop { background: rgba(9, 13, 22, .86); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.lb-fig {
  height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1rem;
  padding: 4rem 5rem 2rem;
}
.lb[open] .lb-fig { animation: lbin .35s cubic-bezier(.2,.8,.2,1); }
@keyframes lbin { from { opacity: 0; transform: scale(.965); } }
.lb-fig img {
  display: block;
  max-width: 100%;
  max-height: calc(100dvh - 9rem);
  object-fit: contain;
  border-radius: 12px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .5);
}
.lb-fig img.is-swap { animation: lbswap .35s ease; }
@keyframes lbswap { from { opacity: .2; } }
.lb-cap {
  display: flex; gap: .9rem; align-items: baseline; justify-content: center;
  font-family: var(--mono); font-size: .8rem;
  color: #B5C1D4; text-align: center; max-width: 46rem;
}
.lb-count { color: var(--sand); white-space: nowrap; }
.lb-btn {
  position: fixed;
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(237, 241, 248, .22);
  background: rgba(255, 255, 255, .06);
  color: #fff;
  font-size: 1.3rem; line-height: 1;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.lb-btn:hover { background: rgba(255, 255, 255, .14); border-color: rgba(237, 241, 248, .5); }
.lb-close { top: 1rem; right: 1rem; font-size: 1rem; }
.lb-prev { left: 1rem; top: calc(50% - 23px); }
.lb-next { right: 1rem; top: calc(50% - 23px); }
.lb.is-single .lb-prev, .lb.is-single .lb-next { display: none; }

/* one ink line under the nav, sliding between links */
.top nav.has-ink a:not(.nav-cv):not(.nav-lang) { border-bottom-color: transparent !important; }
.nav-ink {
  position: absolute; left: 0; top: 0;
  height: 2px;
  background: var(--cobalt);
  border-radius: 2px;
  opacity: 0;
  pointer-events: none;
  transition: transform .35s cubic-bezier(.2,.7,.2,1), width .35s cubic-bezier(.2,.7,.2,1), opacity .2s;
}

/* phone menu: the button only shows where the section links are hidden */
.menu-btn { display: none; }
.menu-sheet { display: none; }

/* copy-the-address button, glued to the email link */
.mail-pair { display: inline-flex; align-items: center; gap: .15rem; white-space: nowrap; }
.copy-mail {
  position: relative;
  display: inline-grid; place-items: center;
  width: 30px; height: 30px;
  padding: 0;
  color: var(--ink-soft);
  background: none;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}
.copy-mail:hover { color: var(--cobalt-deep); border-color: var(--line); background: var(--bg-raised); }
.copy-mail.is-done { color: var(--teal); }
.copy-mail-note {
  position: absolute;
  left: 50%; bottom: calc(100% + 4px);
  transform: translateX(-50%);
  font: 500 .68rem/1 var(--mono);
  color: var(--bg);
  background: var(--ink);
  border-radius: 6px;
  padding: .3rem .45rem;
  pointer-events: none;
}
.copy-mail-note:empty { display: none; }
.copy-mail.is-done .copy-mail-note { animation: notein .25s cubic-bezier(.2,.7,.2,1); }
@keyframes notein { from { opacity: 0; transform: translate(-50%, 4px); } }

/* timeline: a line fills as the reader moves down, each year lights up when reached */
.timeline.is-live { position: relative; padding-left: 2.2rem; }
.timeline.is-live::before, .timeline.is-live::after {
  content: "";
  position: absolute;
  left: .45rem; top: 0; bottom: 0;
  width: 2px;
  border-radius: 2px;
}
.timeline.is-live::before { background: rgba(237, 241, 248, .1); }
.timeline.is-live::after {
  background: linear-gradient(var(--sand), #35A9A7);
  transform-origin: 50% 0;
  transform: scaleY(var(--tl, 0));
}
.timeline.is-live li::before {
  content: "";
  position: absolute;
  left: calc(-2.2rem + .45rem + 1px - 6px);
  top: 1.95rem;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--band);
  border: 2px solid rgba(237, 241, 248, .28);
  z-index: 1;
  transition: background .3s, border-color .3s, box-shadow .3s;
}
.timeline.is-live li.is-on::before {
  background: var(--sand);
  border-color: var(--sand);
  box-shadow: 0 0 0 5px rgba(228, 169, 60, .16);
}
.timeline.is-live .tl-when { transition: color .3s; }
.timeline.is-live li:not(.is-on) .tl-when { color: #7E8CA8; }

@media (max-width: 620px) {
  .menu-btn {
    display: inline-flex; align-items: center; gap: .5rem;
    font: 600 .9rem/1 var(--font);
    color: var(--ink);
    background: var(--bg-raised);
    border: 1.5px solid var(--line);
    border-radius: 999px;
    padding: .5rem .8rem;
    cursor: pointer;
    order: -1;
  }
  .menu-btn-bars, .menu-btn-bars::before {
    display: block;
    width: 14px; height: 2px;
    background: currentColor;
    border-radius: 2px;
    transition: transform .25s cubic-bezier(.2,.7,.2,1);
  }
  .menu-btn-bars { position: relative; transform: translateY(-3px); }
  .menu-btn-bars::before { content: ""; position: absolute; top: 6px; }
  .menu-btn[aria-expanded="true"] .menu-btn-bars { transform: rotate(45deg); }
  .menu-btn[aria-expanded="true"] .menu-btn-bars::before { transform: translateY(-6px) rotate(-90deg); }

  .menu-sheet {
    display: block;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    top: var(--top-h, 60px);
    z-index: 49;
    padding: 1.4rem 1.1rem 2rem;
    background: var(--frost-strong);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-top: 1px solid var(--line);
    opacity: 0;
    transition: opacity .25s ease;
  }
  .menu-sheet[hidden] { display: none; }
  .menu-sheet.is-open { opacity: 1; }
  .menu-sheet ol { list-style: none; }
  .menu-sheet li {
    border-bottom: 1px solid var(--line);
    opacity: 0; transform: translateY(10px);
    transition: opacity .35s, transform .45s cubic-bezier(.2,.7,.2,1);
    transition-delay: calc(.05s + var(--i, 0) * 45ms);
  }
  .menu-sheet.is-open li { opacity: 1; transform: none; }
  .menu-sheet a {
    display: flex; align-items: baseline; gap: 1rem;
    padding: 1rem 0;
    text-decoration: none;
    font-size: 1.9rem; font-weight: 800; line-height: 1.1;
    font-variation-settings: "wdth" 118;
    letter-spacing: -.015em;
  }
  .menu-num { font: 400 .72rem var(--mono); letter-spacing: .2em; color: var(--teal); }

  .lb-fig { padding: 4.2rem .8rem 5.6rem; }
  .lb-fig img { max-height: calc(100dvh - 12rem); }
  .lb-cap { flex-direction: column; align-items: center; gap: .3rem; font-size: .74rem; }
  .lb-prev, .lb-next { top: auto; bottom: 1.1rem; }
  .lb-prev { left: calc(50% - 56px); }
  .lb-next { right: calc(50% - 56px); }
  .timeline.is-live { padding-left: 1.8rem; }
  .timeline.is-live li::before { left: calc(-1.8rem + .45rem + 1px - 6px); top: 1.85rem; }
}

@media (prefers-reduced-motion: reduce) {
  .avail-dot::after, .mon-dot::after { display: none; }
  .mon-widget.in-view .mon-warn { animation: none; }
  .proof em { transition: none; background-size: 100% .4em; }
  .lab-item::before, .nav-ink, .zoomable, .carousel-slide,
  .menu-sheet, .menu-sheet li, .timeline.is-live li::before { transition: none; }
  .carousel-slide:not(.is-current) { opacity: 1; }
  .lb[open] .lb-fig { animation: none; }
  .btn:active { transform: none; }
}

@media print {
  .copy-mail, .menu-btn, .menu-sheet, .lb, .nav-ink { display: none !important; }
  .timeline.is-live::before, .timeline.is-live::after, .timeline.is-live li::before { display: none; }
}

/* ====== round two: recruiter-facing details ====== */

/* "Now" line under the availability pill: dated, so the page reads as kept up */
.hero-now {
  max-width: 34rem;
  font-size: .9rem;
  line-height: 1.5;
  color: var(--ink-soft);
  margin: 1rem 0 0;
  padding-left: .9rem;
  border-left: 2px solid var(--teal);
}
.hero-now b { color: var(--ink); font-weight: 700; }
.hero-copy > :nth-child(6) { animation-delay: .6s; }

/* lab: a status chip so a missing link reads as "not public yet", not "missing" */
.lab-status {
  display: inline-block;
  font-family: var(--mono);
  font-size: .66rem !important;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--sand-ink) !important;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: .12rem .55rem;
  margin-bottom: .7rem;
}

/* booking link: a calendar mark in front, so it reads differently from email */
.btn-cal::before {
  content: "";
  display: inline-block;
  width: .95em; height: .95em;
  margin-right: .45rem;
  vertical-align: -.1em;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6'%3E%3Crect x='2' y='3' width='12' height='11' rx='2'/%3E%3Cpath d='M2 6.5h12M5.5 1.5v3M10.5 1.5v3'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6'%3E%3Crect x='2' y='3' width='12' height='11' rx='2'/%3E%3Cpath d='M2 6.5h12M5.5 1.5v3M10.5 1.5v3'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* the time in Nabeul, under the contact lede */
.local-time {
  display: block;
  max-width: 30rem;
  margin-left: auto; margin-right: auto;
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--ink-soft);
  margin-top: -1rem; margin-bottom: 1.8rem;
}
.lt-dot { display: inline-block; vertical-align: .05em; margin-right: .55rem; width: 8px; height: 8px; border-radius: 50%; background: var(--muted-fill); }
.local-time.is-working .lt-dot { background: var(--teal); box-shadow: 0 0 0 4px color-mix(in srgb, var(--teal) 20%, transparent); }

/* colophon: who made this, with what, and when it was last touched */
.colophon {
  margin-top: 1.2rem;
  font-size: .78rem;
  color: var(--ink-soft);
  opacity: .8;
}

/* ====== skill finder ====== */
.skill-finder {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  margin: -1.2rem 0 2rem;
}
.skill-finder-label {
  font-size: .95rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin-right: .4rem;
}
.skill-chip {
  display: inline-flex; align-items: center; gap: .45rem;
  font: 600 .86rem/1 var(--font);
  color: var(--ink);
  background: var(--bg-raised);
  border: 1.5px solid var(--line);
  border-radius: 999px;
  padding: .5rem .85rem;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s, transform .2s cubic-bezier(.2,.7,.2,1);
}
.skill-chip:hover { border-color: var(--cobalt); transform: translateY(-1px); }
.skill-chip:active { transform: scale(.97); }
.skill-count {
  font: 500 .68rem/1 var(--mono);
  color: var(--ink-soft);
  background: var(--surface-2);
  border-radius: 999px;
  padding: .2rem .4rem;
}
.skill-chip[aria-pressed="true"] { background: var(--cobalt); border-color: var(--cobalt); color: #fff; }
.skill-chip[aria-pressed="true"] .skill-count { background: rgba(255, 255, 255, .22); color: #fff; }
.skill-finder-status { font-family: var(--mono); font-size: .74rem; color: var(--teal); margin-left: .3rem; }

/* cases outside the filter step back; the matching stack chips light up */
.case > * { transition: opacity .35s ease, filter .35s ease; }
.case.is-dim > * { opacity: .28; filter: grayscale(.7); }
.case.is-dim:hover > * { opacity: .6; }
.case-stack li.is-match { border-color: var(--cobalt); color: var(--cobalt-deep); background: var(--highlight); }

/* ====== outcomes: the rule draws down and the figures count ====== */
.case-outcome .fig { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink); }
.case.reveal .case-outcome {
  border-left-color: transparent;
  background: linear-gradient(var(--cobalt), var(--cobalt)) no-repeat 0 0 / 3px 0;
  background-origin: border-box;
  transition: background-size .8s cubic-bezier(.2,.7,.2,1) .35s;
}
.case.reveal.in-view .case-outcome { background-size: 3px 100%; }

/* ====== reading bar: the request travels down the page with you ====== */
.top-packet {
  position: absolute;
  left: calc(50% - 50vw);
  bottom: -4px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--cobalt);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cobalt) 25%, transparent), 0 0 12px var(--cobalt);
  /* stays inside the viewport at both ends, so it never widens the page */
  transform: translateX(calc(var(--p, 0) * (100vw - 8px)));
  opacity: 0;
  transition: opacity .25s ease;
  pointer-events: none;
}
.top.is-stuck .top-packet { opacity: 1; }
.top-packet.is-landed { animation: land .9s cubic-bezier(.2,.7,.2,1); }
@keyframes land {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--teal) 60%, transparent); background: var(--teal); }
  100% { box-shadow: 0 0 0 14px transparent; background: var(--cobalt); }
}

/* ====== page change portfolio <-> CV: the portrait carries over ====== */
@view-transition { navigation: auto; }
.hero-avatar, .cv-portrait { view-transition-name: portrait; }
html.theme-vt .hero-avatar, html.theme-vt .cv-portrait { view-transition-name: none; }
::view-transition-group(portrait) { animation-duration: .5s; animation-timing-function: cubic-bezier(.2,.7,.2,1); }

@media (max-width: 620px) {
  .skill-finder { margin-top: -1.4rem; gap: .4rem; }
  .skill-finder-label { flex-basis: 100%; margin-bottom: .1rem; }
  .skill-chip { font-size: .8rem; padding: .45rem .7rem; }
  .hero-now { font-size: .86rem; }
}

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  .case > *, .skill-chip, .top-packet { transition: none; }
  .top-packet.is-landed { animation: none; }
  .case.reveal .case-outcome { transition: none; background-size: 3px 100%; }
}

@media print {
  .skill-finder, .local-time, .top-packet, .lab-status { display: none !important; }
  .case.is-dim > * { opacity: 1; filter: none; }
}

/* ====== dark theme: places where a token swap isn't enough ====== */
/* logos drawn for a light ground get a light chip */
[data-theme="dark"] .case-title-logo img {
  background: var(--logo-chip);
  border-radius: 8px;
  padding: 3px;
  box-sizing: content-box;
}
/* the bands sit darker than the page, so a hairline keeps their edges */
[data-theme="dark"] .says, [data-theme="dark"] .path { border-block: 1px solid #1C2436; }
[data-theme="dark"] .proof { background: var(--bg-raised); }
/* white logo artwork on a near-black chip needs an edge on a dark page */
[data-theme="dark"] .clients-row li.on-dark, [data-theme="dark"] .chalet-brand,
[data-theme="dark"] .say-logo-dark { border: 1px solid var(--line); }
/* the dark widgets are already navy: lift them off the navy page */
[data-theme="dark"] .case-visual > .widget-dark { background: #0B1830; border-color: #20324F; }
[data-theme="dark"] .say { box-shadow: 0 0 0 1px var(--paper-line), 0 18px 40px rgba(0, 0, 0, .4); }
[data-theme="dark"] .shot-frame, [data-theme="dark"] .wh-photo,
[data-theme="dark"] .case-proof-shots img { border-color: var(--line); }
[data-theme="dark"] img.hero-avatar, [data-theme="dark"] .contact-photo { border-color: var(--bg); }

/* ====== theme toggle ====== */
.theme-btn {
  display: inline-grid; place-items: center;
  width: 36px; height: 36px;
  padding: 0;
  color: var(--ink-soft);
  background: none;
  border: 1.5px solid var(--line);
  border-radius: 50%;
  cursor: pointer;
  transition: color .15s, border-color .15s, transform .3s cubic-bezier(.3,1.5,.5,1);
}
.theme-btn:hover { color: var(--ink); border-color: var(--cobalt); }
.theme-btn:active { transform: scale(.9); }
.theme-btn svg { display: block; transition: transform .5s cubic-bezier(.2,.7,.2,1); }
.theme-btn .i-sun { display: none; }
[data-theme="dark"] .theme-btn .i-sun { display: block; }
[data-theme="dark"] .theme-btn .i-moon { display: none; }
.theme-btn:hover svg { transform: rotate(-18deg); }

/* when there is no view-transition support, colours cross-fade instead */
html.theme-fade, html.theme-fade *, html.theme-fade *::before, html.theme-fade *::after {
  transition: background-color .35s ease, border-color .35s ease, color .35s ease, fill .35s ease, stroke .35s ease !important;
}
/* with it, the new theme grows out of the toggle as a circle */
::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }

/* ====== responsive ====== */
@media (max-width: 900px) {
  /* the film leads, running under the header, and the headline overlaps its foot.
     Phones get the square cut of the film (hero-m.mp4); the wide poster is
     framed on the same devices until it plays. */
  .hero { flex-direction: column; align-items: stretch; min-height: 0; padding: 0 1.6rem 2.8rem; }
  .hero::after { display: none; }
  .hero-film {
    position: relative; inset: auto; z-index: 0; order: -1;
    width: calc(100% + 3.2rem); height: auto; max-height: 620px;
    margin: 0 -1.6rem -2.4rem;
    aspect-ratio: 1 / 1; object-position: 86% 50%;
    -webkit-mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
            mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
  }
  .hero-copy { position: relative; z-index: 1; max-width: none; }
  .case { grid-template-columns: minmax(0, 1fr); }
  .case-text, .case-flip .case-text { grid-column: 1; grid-row: 2; }
  .case:not(:has(.reel-widget)) .case-text { grid-row: 1; }
  .case-visual > *, .case-flip .case-visual > * { grid-column: 1; }
  .case-visual > .reel-widget { margin-bottom: .4rem; border-radius: 16px; }
  .lab-grid { grid-template-columns: repeat(2, 1fr); }
  .case-proof-shots { grid-template-columns: repeat(2, 1fr); }
  .timeline li { grid-template-columns: minmax(0, 1fr); gap: .3rem; }
  .glance-grid { grid-template-columns: minmax(0, 1fr); }
  .top nav { gap: .5rem; }
  /* bigger tap targets for thumbs */
  .top nav a { font-size: .9rem; padding: .55rem .4rem; }
  .carousel-btn { width: 42px; height: 42px; font-size: 1.35rem; }
  .carousel-prev { left: -12px; }
  .carousel-next { right: -12px; }
  /* 24px minimum touch target; a long dot row wraps to a second line */
  .carousel-dots button { width: 24px; height: 24px; }
}

@media (max-width: 620px) {
  .top { padding: 1rem 1.1rem; }
  .hero { padding-left: 1.1rem; padding-right: 1.1rem; }
  .hero-film { width: calc(100% + 2.2rem); margin-left: -1.1rem; margin-right: -1.1rem; }
  .proof p { padding: 1.8rem 1.1rem; font-size: 1.1rem; }
  .work, .lab, .contact { padding-left: 1.1rem; padding-right: 1.1rem; }
  .path { padding-left: 1.1rem; padding-right: 1.1rem; }
  .case-visual > div { padding: 1.1rem; }
  .case-proof-shots { grid-template-columns: 1fr; }
  .case-proof-shots img { height: 190px; }
  /* full-width CTAs are easier to hit one-handed */
  .hero-actions .btn, .contact-links .btn { flex: 1 1 100%; text-align: center; }
  .tl-photos img { flex-basis: 100%; height: 200px; }
  .glance { padding-left: 1.1rem; padding-right: 1.1rem; }
  .glance-grid > div { grid-template-columns: minmax(0, 1fr); gap: .2rem; padding-right: 0; }
  .lab-grid { grid-template-columns: 1fr; }
  /* thumb-sized mail link */
  .contact-meta a { padding: .6rem .4rem; }
}

/* ====== reduced motion ====== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero-copy > *, .hero-film { animation: none; opacity: 1; transform: none; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .loadbar-fill { transition: none; width: var(--w); }
  .carousel-track { transition: none; }
  .top, .top::before, .top-progress { transition: none; }
  .case.reveal .case-stack li { opacity: 1; transform: none; transition: none; }
  .in-view .arch-wire, .in-view .arch-grpc { animation: none; }
  .arch-pkt { display: none; }
  .mon-widget.reveal .mon-feed li { opacity: 1; transform: none; animation: none !important; }
  .lang-hint { animation: none; }
}

@media (max-width: 620px) {
  .lang-hint { left: .8rem; right: .8rem; bottom: 5.2rem; max-width: none; }
  .mon-feed li { grid-template-columns: 2.6rem 3rem minmax(0, 1fr) auto; gap: .45rem; font-size: .7rem; }
  .top.is-stuck { padding-top: .55rem; padding-bottom: .55rem; }
  /* five section links do not fit a phone; the page is one scroll and the dock
     carries email and CV, so the bar keeps only CV and the language switch */
  .top nav a:not(.nav-cv):not(.nav-lang) { display: none; }
  .top nav { gap: .6rem; }
}

/* ====== new blocks, small screens ====== */
@media (max-width: 900px) {
  .hire-grid { grid-template-columns: minmax(0, 1fr); }
  .says-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .say-lead { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; padding: 1.7rem 1.7rem 1.4rem; }
  .say-lead .say-who {
    grid-row: auto; flex-direction: row; align-items: center;
    padding: 0 0 1.1rem; margin-bottom: 1.2rem;
    border-right: 0; border-bottom: 1px dashed var(--paper-line);
  }
  .say-lead blockquote, .say-lead .say-tr, .say-lead .say-src { grid-column: 1; }
  .howiwork { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .clients-row { gap: 1.6rem; }
  .clients-row img { height: 32px; }
}

@media (max-width: 620px) {
  .clients, .hire, .says { padding-left: 1.1rem; padding-right: 1.1rem; }
  /* five logos: three to a row instead of 2-2-1 */
  .clients-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6rem; }
  .clients-row li { min-width: 0; padding: .6rem .5rem; }
  .clients-row img { height: 28px; max-width: 100%; }
  .says-grid { grid-template-columns: minmax(0, 1fr); }
  .howiwork { grid-template-columns: minmax(0, 1fr); }
  .lane-facts > div { grid-template-columns: minmax(0, 1fr); gap: .15rem; }
  .lane { padding: 1.2rem 0 0; }
  .lane-actions .btn { flex: 1 1 100%; text-align: center; }
  .top nav { gap: .35rem; }

  /* the contact block is a long scroll away, so the two actions ride along */
  .dock {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 40;
    gap: .6rem;
    padding: .6rem .8rem calc(.6rem + env(safe-area-inset-bottom));
    background: var(--frost);
    backdrop-filter: blur(8px);
    border-top: 1px solid var(--line);
  }
  .dock .btn { flex: 1; text-align: center; padding: .75rem 1rem; font-size: .95rem; }
  .dock .btn-ghost { flex: 0 0 5.5rem; background: var(--bg-raised); }
  .contact { padding-bottom: 6rem; }
}

/* ====== printing the portfolio itself ====== */
@media print {
  .top, .dock, .hero-film, .carousel-btn, .carousel-dots, .skip, .lang-hint { display: none; }
  body { background: #fff; font-size: 11pt; }
  .hero, .case { grid-template-columns: 1fr; }
  .case-visual, .case-proof, .clients { display: none; }
  .path, .says { background: #fff; color: var(--ink); }
  .says h2 { color: var(--ink); }
  .says::before { display: none; }
  .say { box-shadow: none; border: 1px solid var(--line); }
  .say-lead { grid-template-columns: 1fr; }
  .say-lead .say-who { grid-row: auto; border-right: 0; }
  .say-lead blockquote, .say-lead .say-src { grid-column: 1; }
  .says-lede { color: var(--ink-soft); }
  .say-tr { display: none; }
  .path h2, .timeline h3 { color: var(--ink); }
  .timeline p { color: var(--ink-soft); }
  .case, .lane, .timeline li, .say { break-inside: avoid; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .8em; color: var(--ink-soft); }
}

/* the open phone menu owns the screen */
html.menu-open .lang-hint { display: none; }

/* the rest of a case story, folded by script.js */
.case-more { margin: .2rem 0 1.4rem; }
.case-more summary {
  display: inline-flex; align-items: center; gap: .6rem;
  min-height: 40px; padding: 0 1.1rem;
  border: 1.5px solid var(--line); border-radius: 999px;
  background: var(--bg-raised); color: var(--ink);
  font-weight: 700; font-size: .92rem;
  cursor: pointer; list-style: none;
  transition: border-color .15s;
}
.case-more summary::-webkit-details-marker { display: none; }
.case-more summary::after { content: "+"; font-weight: 500; font-size: 1.1rem; color: var(--cobalt); }
.case-more[open] summary::after { content: "\2212"; }
.case-more summary:hover { border-color: var(--cobalt); }
.case-more[open] summary { margin-bottom: 1.1rem; }

/* ====== film bands ======
   The sections that carry a background film, and the client strip between two
   of them, sit on the dark stage in both themes. Their tokens are re-pointed so
   the components inside turn light on their own. Each film fades to the stage
   colour at its top and bottom, so neighbouring bands read as one continuous
   reel rather than stacked boxes. */
.proof, .clients, .glance, .says, .lab, .path, .contact {
  --ink: #E9EDF6; --ink-soft: #AEB8D2; --line: rgba(233, 237, 246, .14);
  --bg-raised: rgba(255, 255, 255, .05); --teal: #3DD6C2; --cobalt-deep: #A9B9FF;
  --highlight: rgba(255, 181, 71, .26); --surface-2: rgba(255, 255, 255, .1);
  --sand-ink: #FFC56B; --float-btn: rgba(7, 13, 31, .6);
  position: relative; isolation: isolate; overflow: hidden;
  background: var(--stage); color: var(--ink);
  --wide: max(2rem, calc((100vw - 1180px) / 2 + 2rem));
}
.band-film {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%; object-fit: cover;
}
:is(section, footer):has(> .band-film)::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg,
    var(--stage) 0%, rgba(7, 13, 31, var(--scrim, .5)) 18%,
    rgba(7, 13, 31, var(--scrim, .5)) 82%, var(--stage) 100%);
}
.proof { --scrim: .42; border: 0; }
.glance { --scrim: .7; }
.says { --scrim: .45; }
.lab { --scrim: .55; }
.path { --scrim: .68; }
.contact { --scrim: .4; }

.proof p { position: relative; padding: 7.5rem 2rem 6.5rem; }
.proof em { color: #FFFFFF; }
.clients { max-width: none; margin: 0; padding: 0 var(--wide) 3.5rem; }
.clients-row { border-bottom: 0; padding-bottom: 0; }
.clients-row li.on-dark { border-color: var(--line); }
.glance { max-width: none; margin: 0; padding: 6rem var(--wide) 6.5rem; }
.glance h2 { font-size: clamp(2rem, 3.6vw, 3rem); margin-bottom: 2rem; }
.says { margin-top: 0; padding: 7rem 2rem; }
.lab { max-width: none; margin: 0; padding: 7rem var(--wide); }
.lab-item { border-top-color: var(--ink); }
.path { padding: 7rem 2rem; }
.contact { max-width: none; margin: 0; padding: 8rem var(--wide) 4rem; }
.contact-photo { border-color: var(--stage); }
/* the recommendations are paper cards: in the light theme they keep dark ink
   inside the dark band (in the dark theme the cards are dark too) */
:root:not([data-theme="dark"]) .says .say {
  --ink: #0C1430; --ink-soft: #4A5470; --line: #DCE1EB; --bg-raised: #FFFFFF;
  --teal: #0B7372; --cobalt-deep: #1D3AA8; --sand-ink: #8A5A0B;
}

/* labels speak in the page's own voice; monospace is kept for what really is
   code or machine output (the monitoring feed, stack tags, the live clock) */
.case-role, .widget-title, .carousel-cap, .carousel-note, .case-proof-label, .tl-when,
.tl-caption, .glance-grid dt, .lane-facts dt, .say-rel, .say-src, .avail-badge,
.contact-meta, .loadbar-name, .lab-status, .say-tr summary {
  font-family: var(--font);
  letter-spacing: 0;
}
.case-role { font-size: .9rem; font-weight: 600; }
.widget-title { font-size: .86rem; font-weight: 600; }
.tl-when { font-size: .92rem; font-weight: 700; }
.glance-grid dt, .lane-facts dt { font-size: .86rem; font-weight: 600; }
.say-rel { font-size: .8rem; font-weight: 600; }
.lab-status { text-transform: none; font-weight: 600; }

/* film grain over the whole page: an SVG noise tile shifted a few times a
   second. Live in the page rather than baked into the videos, where noise
   would multiply their size. */
body::after {
  content: ""; position: fixed; inset: -50%; z-index: 90; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: .07;
  mix-blend-mode: overlay;
  animation: grain .9s steps(7) infinite;
}
@keyframes grain {
  0% { transform: translate(0, 0); } 15% { transform: translate(-3%, 2%); } 30% { transform: translate(2%, -4%); }
  45% { transform: translate(-4%, -1%); } 60% { transform: translate(4%, 3%); } 75% { transform: translate(-1%, 4%); }
  90% { transform: translate(3%, -2%); } 100% { transform: translate(0, 0); }
}
@media (prefers-reduced-motion: reduce) { body::after { animation: none; } }
@media print { body::after { display: none; } }

/* ====== landing pages (tools/make-pages.py) ======
   One intent per page: the answer in the hero, then what I build, the proof,
   how it runs and the questions people ask first. */
.hero-page { min-height: min(80svh, 780px); }
/* the case film at its own 16:9 on the right, edges dissolving into the stage,
   so none of its labels get cropped */
@media (min-width: 901px) {
  .hero-page .hero-film {
    inset: auto; left: 38vw; top: calc(50% - 62vw * 9 / 32);
    width: 62vw; height: auto; aspect-ratio: 16 / 9;
    -webkit-mask-image: radial-gradient(75% 75% at 55% 50%, #000 55%, transparent 100%);
            mask-image: radial-gradient(75% 75% at 55% 50%, #000 55%, transparent 100%);
  }
}
.hero-page .hero-copy { max-width: 40rem; }
.hero-page h1 { font-size: clamp(2.4rem, 4.8vw, 4.6rem); line-height: .95; }
.crumbs { order: -1; font-size: .9rem; color: var(--ink-soft); margin-bottom: 1.4rem; }
.crumbs a { color: inherit; text-underline-offset: 3px; }
.crumbs [aria-current] { color: var(--ink); font-weight: 600; }

.page { max-width: 1180px; margin: 0 auto; padding: 1rem 2rem 4rem; }
.page-block { padding: 3.6rem 0; border-top: 1px solid var(--line); }
.page-block:first-child { border-top: 0; }
.page-block h2 { font-size: clamp(1.9rem, 3.6vw, 3rem); line-height: 1; letter-spacing: -.03em; margin-bottom: 1.8rem; }

.page-list { list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem 2.6rem; }
.page-list li { position: relative; padding-left: 1.4rem; color: var(--ink-soft); }
.page-list li::before {
  content: ""; position: absolute; left: 0; top: .6em;
  width: .5rem; height: .5rem; border-radius: 50%; background: var(--signal);
}

.pcards { display: grid; gap: 1.4rem; }
.pcard {
  display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 2.2rem; align-items: center;
  background: var(--bg-raised); border: 1px solid var(--line); border-radius: 18px; overflow: hidden;
}
.pcard img {
  display: block; width: 100%; height: 100%; max-height: 340px; aspect-ratio: 16 / 10;
  object-fit: cover; object-position: 50% 0; background: var(--stage);
}
.pcard-body { padding: 1.8rem 2rem 1.8rem 0; }
.pcard h3 { font-size: 1.5rem; margin-bottom: .7rem; }
.pcard p { color: var(--ink-soft); margin-bottom: .9rem; }
.pcard .pcard-nums { color: var(--ink); font-weight: 700; }
.pcard-link { font-weight: 700; color: var(--cobalt-deep); text-underline-offset: 4px; }

/* these steps really are a sequence, so they are numbered */
.page-steps { list-style: none; counter-reset: step; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2.2rem; }
.page-steps li { counter-increment: step; border-top: 3px solid var(--cobalt); padding-top: 1rem; }
.page-steps li::before {
  content: counter(step); display: block; margin-bottom: .4rem;
  font-weight: 800; font-size: 1.8rem; color: var(--cobalt); font-variation-settings: "wdth" 125;
}
.page-steps h3 { font-size: 1.15rem; margin-bottom: .4rem; }
.page-steps p { color: var(--ink-soft); }

.faq details { border-top: 1px solid var(--line); }
.faq details:last-child { border-bottom: 1px solid var(--line); }
.faq summary {
  position: relative; cursor: pointer; list-style: none;
  padding: 1.15rem 2.6rem 1.15rem 0; font-weight: 700; font-size: 1.06rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; position: absolute; right: .3rem; top: .95rem; font-size: 1.4rem; color: var(--cobalt); }
.faq details[open] summary::after { content: "\2212"; }
.faq details p { color: var(--ink-soft); padding-bottom: 1.3rem; max-width: 46rem; }

/* the services, as links: on the landing pages and in the home page's hire section */
.svc-links { list-style: none; display: flex; flex-wrap: wrap; gap: .7rem; }
.svc-links a {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 1.15rem;
  border: 1.5px solid var(--line); border-radius: 999px; background: var(--bg-raised);
  color: var(--ink); font-weight: 700; text-decoration: none; transition: border-color .15s;
}
.svc-links a:hover { border-color: var(--cobalt); }
.svc-home { margin-top: 2.6rem; }
.svc-home h3 { font-size: 1.15rem; margin-bottom: 1rem; }

@media (max-width: 900px) {
  .hero-page .hero-film {
    -webkit-mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
            mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
  }
  .pcard { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .pcard-body { padding: 1.4rem 1.4rem 1.6rem; }
  .page-list, .page-steps { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 620px) {
  .page { padding: 0 1.1rem 3rem; }
  .page-block { padding: 2.6rem 0; }
  /* the landing headlines are longer than the home one, and French words run long */
  .hero.hero-page h1 { font-size: clamp(2.1rem, 10vw, 2.9rem); hyphens: auto; }
}

/* ====== phone pass ======
   Last in the file on purpose: these win over the component rules above. */
@media (max-width: 620px) {
  :root { --top-h: 4.75rem; }   /* the phone bar: 1rem padding around 44px buttons */
  .btn { white-space: nowrap; }

  /* nothing a recruiter needs to read goes below 13.6px */
  .case-role, .widget-title, .loadbar-name, .carousel-cap, .carousel-note, .case-proof-label,
  .mon-live, .say-rel, .say-src, .lab-status, .lab-tags, .tl-caption, .avail-badge,
  .lt-text, .contact-meta, .colophon, .skill-count, .skill-chip { font-size: .8rem !important; }
  .mon-feed li { font-size: .8rem; grid-template-columns: 2.8rem 3.2rem minmax(0, 1fr) auto; gap: .45rem; }

  /* 44px targets for thumbs */
  .theme-btn { width: 44px; height: 44px; }
  .nav-cv, .nav-lang { min-height: 44px; display: inline-flex !important; align-items: center; }
  .menu-btn { min-height: 44px; }
  .skill-chip { min-height: 44px; }
  .copy-mail { width: 44px; height: 44px; }
  .say-tr summary, .case-more summary { min-height: 44px; }

  /* hero: the two calls side by side; the address lives in the dock and the footer */
  .hero h1 { font-size: clamp(2.9rem, 13.5vw, 3.6rem); }
  .hero-hello { font-size: .9rem; }
  .hero-lede { font-size: 1.02rem; }
  .hero-actions { flex-wrap: nowrap; }
  .hero-actions .btn { flex: 1 1 0; padding-left: .6rem; padding-right: .6rem; }
  .hero-actions .mail-pair { display: none; }
  .hero-now { font-size: .86rem; }

  /* the numbers line */
  .proof p { padding: 4.5rem 1.1rem 4rem; font-size: 1.28rem; }
  .clients, .glance, .lab, .contact { padding-left: 1.1rem; padding-right: 1.1rem; }
  .glance { padding-top: 4rem; padding-bottom: 4.5rem; }
  .says, .lab, .path { padding-top: 4.5rem; padding-bottom: 4.5rem; }
  .contact { padding-top: 5rem; }

  /* at a glance: label over value, tight rows */
  .glance h2 { margin-bottom: 1rem; }
  .glance-grid > div { padding: .6rem 0; }
  .glance-grid dd { font-size: .92rem; }

  /* chapters: films edge to edge, a smaller phone frame, photo strips you swipe */
  .work h2, .lab h2, .path h2, .says h2, .hire h2, .contact h2 { font-size: clamp(2.3rem, 11vw, 3rem); }
  .case { padding: 2.8rem 0; }
  .case-visual > .reel-widget { margin-left: -1.1rem; margin-right: -1.1rem; border-radius: 0; }
  .phone-frame { max-width: 205px; border-width: 5px; border-radius: 22px; }
  .case-proof-shots, .tl-photos {
    display: grid; grid-auto-flow: column; grid-auto-columns: 74%;
    grid-template-columns: none;
    gap: .7rem; overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory; scrollbar-width: none;
    margin-right: -1.1rem; padding-right: 1.1rem;
  }
  .case-proof-shots::-webkit-scrollbar, .tl-photos::-webkit-scrollbar { display: none; }
  .case-proof-shots img, .tl-photos img { height: 250px; width: 100%; scroll-snap-align: start; }

  /* hire: fact label over value, calls two to a row */
  .lane-facts > div { grid-template-columns: minmax(0, 1fr); gap: .15rem; padding: .6rem 0; }
  .lane-actions .btn { flex: 1 1 calc(50% - .35rem); text-align: center; }
  .howiwork { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* contact: the main calls full width, the files and profiles two to a row */
  .contact-links-secondary .btn { flex: 1 1 calc(50% - .45rem); font-size: .86rem; padding-left: .5rem; padding-right: .5rem; }
  .lane-actions .btn { font-size: .86rem; padding-left: .5rem; padding-right: .5rem; }
}

/* ===== one-week mission (Alpilink) ===== */
.mission {
  scroll-margin-top: 5.5rem;
  margin-top: 1rem; padding: 2.4rem 2.6rem;
  border: 1.5px solid var(--line); border-radius: var(--radius);
  background: var(--bg-raised); box-shadow: var(--shadow-card);
}
.mission-head { display: flex; align-items: center; gap: 2rem; margin-bottom: 1.4rem; }
.mission-logo {
  flex: none; display: grid; place-items: center;
  padding: .9rem 1.3rem; border: 1.5px solid var(--line); border-radius: 12px;
  background: #fff; /* brand logo is blue on transparent: keep a light plate in dark mode */
}
.mission-logo img { display: block; width: 150px; height: auto; }
.mission h3 { font-size: clamp(1.5rem, 2.6vw, 2.1rem); line-height: 1.05; }
.mission-lede { color: var(--ink-soft); max-width: 46rem; margin-bottom: 1.6rem; }
.mission-facts {
  list-style: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem; margin-bottom: 1.8rem;
}
.mission-facts li { border-top: 2px solid var(--cobalt); padding-top: .7rem; }
.mission-facts b { display: block; font-size: 1.45rem; line-height: 1.1; color: var(--ink); }
.mission-facts span { font-size: .9rem; color: var(--ink-soft); }
.mission-sub { font-family: var(--mono); font-size: .78rem; color: var(--teal); margin-bottom: .6rem; }
.mission-added ul { list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.4rem; }
.mission-added li { color: var(--ink-soft); font-size: .96rem; }
.mission-added li b { color: var(--ink); }
.mission-sec {
  margin-top: 1.8rem; padding: 1.1rem 1.4rem;
  border-left: 4px solid var(--teal); background: var(--bg); border-radius: 0 10px 10px 0;
}
.mission-sec p:last-child { color: var(--ink-soft); font-size: .96rem; max-width: 52rem; }
.clients-row li a { display: grid; place-items: center; }
@media (max-width: 760px) {
  .mission { padding: 1.5rem 1.2rem; }
  .mission-head { flex-direction: column; align-items: flex-start; gap: 1rem; }
  .mission-facts, .mission-added ul { grid-template-columns: 1fr; }
}

/* ===== mission wheel ===== */
.wheel {
  display: grid; grid-template-columns: minmax(0, 250px) minmax(0, 1fr); gap: 2.2rem; align-items: center;
  margin-bottom: 1.8rem; padding: 1.6rem; border-radius: 12px; background: var(--bg);
}
.wheel:empty { display: none; }
.wheel-stage svg { display: block; width: 100%; height: auto; }
.wheel-disc { transition: transform 4.2s cubic-bezier(.12, .7, .1, 1); }
.wheel-disc text { font-size: 9px; font-weight: 700; text-anchor: middle; }
.wheel-hub { fill: var(--bg-raised); stroke: var(--ink); stroke-width: 2; }
.wheel-pin { fill: var(--ink); }
.wheel-intro { color: var(--ink-soft); font-size: .96rem; max-width: 40rem; margin-bottom: 1rem; }
.wheel-actions { display: flex; flex-wrap: wrap; gap: .7rem; }
.wheel-actions button:disabled { opacity: .55; cursor: default; }
.wheel-out { min-height: 1.6em; margin-top: 1rem; font-weight: 600; }
.wheel-out a { color: var(--cobalt); }
.wheel-sim table { width: 100%; max-width: 30rem; margin-top: .4rem; border-collapse: collapse; font-size: .88rem; font-variant-numeric: tabular-nums; }
.wheel-sim th, .wheel-sim td { padding: .28rem .6rem .28rem 0; text-align: left; white-space: nowrap; border-bottom: 1px solid var(--line); }
.wheel-sim thead th { color: var(--ink-soft); font-weight: 500; }
.wheel-sim th i { display: inline-block; width: .6rem; height: .6rem; margin-right: .45rem; border-radius: 50%; }
.wheel-bar { width: 38%; }
.wheel-bar span { display: block; height: .5rem; max-width: 100%; border-radius: 3px; }
.wheel-sim p { margin-top: .6rem; color: var(--ink-soft); font-size: .88rem; }
@media (max-width: 760px) {
  .wheel { grid-template-columns: 1fr; padding: 1.1rem; gap: 1.2rem; }
  .wheel-stage { max-width: 230px; margin: 0 auto; }
}
@media (prefers-reduced-motion: reduce) { .wheel-disc { transition: none; } }
