@charset "utf-8";

/* ============================================================================
   DigitON — Plateformes
   Design system inherited from digiton.ma, extended with one agreed rule:
   each project's own brand hue becomes a local accent ("room") on its case
   study only. Structure, type scale, spacing and corner language never move.

   Deviations from the published DigitON tokens, both accessibility fixes and
   both documented in DESIGN.md:
     --digiton-muted #5b7fa5 measures 4.02:1 on --digiton-bg  -> not text-safe.
     --digiton-accent #2f88f2 measures 3.41:1               -> not text-safe.
   ========================================================================== */

/* ---- Fonts ----
   The @font-face rules live in fonts.css, loaded before this file, because the
   faces are inlined as data URIs: a linked woff2 cannot be fetched from a
   file:// document (opaque origin, CORS-mode font fetch). See fonts.css. ---- */

/* ------------------------------- Tokens --------------------------------- */
:root {
  /* Published DigitON palette */
  --bg: #f7fbff;
  --surface: #ffffff;
  --ink: #061a35;
  --accent: #2f88f2;
  --accent-light: #3590fa;
  --navy: #061a35;
  --navy-deep: #020b18;
  --line: #a6cdfa;              /* published border, alpha applied per use */

  /* Accessible text roles derived from the published tokens. Both were
     re-derived after a computed-contrast audit: the published muted grey
     measures 4.02:1 and the published accent 3.41:1, neither of them safe
     for body text on this ground. */
  --ink-muted: #3f6288;         /* 6.09:1 on --bg — secondary prose */
  --ink-faint: #4a6d8f;         /* 5.21:1 on --bg — smallest labels */
  --accent-ink: #1462c4;        /* 5.65:1 on --bg — accent-coloured text */

  /* Room accent — the client's own brand hue. DigitON blue on the landing. */
  --room: var(--accent);
  --room-ink: var(--accent-ink);
  --room-wash: rgba(47, 136, 242, 0.09);
  --room-light: rgba(47, 136, 242, 0.16);

  /* Type */
  --font-display: "Outfit", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;

  /* Shape — one radius for plates, the published button radius for controls */
  --r-plate: 20px;
  --r-btn: 8px;

  /* Depth — offset and blur, always. Never a zero-offset halo. The dark
     button's own shadow is neutral: a blue glow on navy reads as a halo. */
  --lift-1: 0 1px 2px rgba(6, 26, 53, 0.05), 0 4px 12px rgba(6, 26, 53, 0.06);
  --lift-2: 0 2px 4px rgba(6, 26, 53, 0.05), 0 12px 28px rgba(6, 26, 53, 0.09);
  --lift-3: 0 4px 8px rgba(6, 26, 53, 0.07), 0 24px 56px rgba(6, 26, 53, 0.14);
  --lift-dark: 0 1px 2px rgba(2, 11, 24, 0.3), 0 10px 24px rgba(2, 11, 24, 0.32);

  /* Rhythm — 4px base */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --band: clamp(4.5rem, 9vw, 8.5rem);
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --measure: 68ch;

  /* Motion — exponential ease-out, one authored curve */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --t-fast: 180ms;
  --t-med: 420ms;
  --t-slow: 900ms;
}

/* The four rooms. Each hue is the client's own brand colour, read from their
   panel provider or tailwind config. --room drives the light and rules,
   --room-ink is the darkened AA-safe version used for any coloured text. */
.room-alot     { --room: #2b5aa8; --room-ink: #23508f; --room-wash: rgba(43, 90, 168, 0.09);  --room-light: rgba(43, 90, 168, 0.18); }
.room-recouvrement { --room: #204797; --room-ink: #1b3f85; --room-wash: rgba(32, 71, 151, 0.09);  --room-light: rgba(32, 71, 151, 0.18); }
.room-interventions { --room: #14a2b8; --room-ink: #0a6f80; --room-wash: rgba(20, 162, 184, 0.10); --room-light: rgba(20, 162, 184, 0.18); }
.room-soins    { --room: #12855a; --room-ink: #0c6845; --room-wash: rgba(18, 133, 90, 0.09);  --room-light: rgba(18, 133, 90, 0.18); }

/* --------------------------------- Reset -------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.7;
  font-feature-settings: "cv05" 1, "ss01" 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: balance;
  margin: 0;
}
p { margin: 0; }
img { display: block; max-width: 100%; }
a { color: inherit; }
ul, ol { margin: 0; padding: 0; list-style: none; }

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

/* Skip link. The header carries the brand, the in-page nav and the CTA on every
   page, so a keyboard user otherwise tabs through 4-6 stops before reaching the
   content. It is the first focusable thing in the document and stays out of the
   way until it is focused. */
.skip {
  position: absolute;
  left: var(--s-4);
  top: var(--s-3);
  z-index: 100;
  padding: 0.7em 1.15em;
  border-radius: var(--r-btn);
  background: var(--ink);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 500;
  text-decoration: none;
  box-shadow: var(--lift-2);
  transform: translateY(calc(-100% - var(--s-5)));
  transition: transform var(--t-fast) var(--ease);
}
.skip:focus { transform: translateY(0); }

/* ------------------- Browser surfaces (themed, never default) ----------- */
::selection { background: var(--room-light); color: var(--ink); }
html { scrollbar-color: #bcd8f6 var(--bg); scrollbar-width: thin; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb {
  background: #bcd8f6;
  border: 3px solid var(--bg);
  border-radius: 8px;
}
::-webkit-scrollbar-thumb:hover { background: #8fbdea; }
input, textarea, button { font: inherit; color: inherit; }
a { text-underline-offset: 0.22em; text-decoration-thickness: from-font; }

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

/* ------------------------------- Layout --------------------------------- */
/* The pale ground: two faint blue glows, the way digiton.ma's own surfaces
   read. No grid overlay: a two-axis line pattern is decoration pretending to
   be a measuring tool, and there is no drawing under it here. */
.ground {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(80% 55% at 78% -6%, rgba(53, 144, 250, 0.13), transparent 70%),
    radial-gradient(60% 45% at 6% 22%, rgba(47, 136, 242, 0.08), transparent 72%),
    var(--bg);
}
.wrap {
  width: 100%;
  max-width: 1240px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--wide { max-width: 1440px; }
.band { padding-block: var(--band); }

/* ------------------------------ Typography ------------------------------- */
.display {
  font-size: clamp(2.75rem, 5.6vw, 5rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  max-width: 20ch;
}
.display--case { max-width: 16ch; }
.h2 {
  font-size: clamp(2rem, 3.6vw, 3rem);
  line-height: 1.06;
  max-width: 18ch;
}
.h3 { font-size: clamp(1.25rem, 1.6vw, 1.5rem); letter-spacing: -0.02em; }

.lead {
  font-size: clamp(1.125rem, 1.5vw, 1.3125rem);
  line-height: 1.6;
  color: var(--ink-muted);
  max-width: 56ch;
  text-wrap: pretty;
}
.prose { max-width: var(--measure); color: #16375c; }
.prose p + p { margin-top: 1.1em; }

/* Small tracked uppercase, led by a dot. Functional: these are the published
   sector tags from digiton.ma, so they carry information. */
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.tags li { display: flex; align-items: center; gap: 0.5em; }
.tags li::before {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.tags--room { color: var(--room-ink); }
.plate__scrim { transition: opacity var(--t-slow) var(--ease), background var(--t-slow) var(--ease); }
/* Over the plate imagery. #cfe2f8 measured 3.92:1 against the brightest pixel of
   the worst plate once the scrim was composited over the capture, so it is lifted
   to #eaf2fe: 4.60:1 there, and better on the darker plates. It stays a tint of
   the ground rather than flat white, so it still reads as a label. */
.tags--onimage { color: #eaf2fe; }
.plate__cta { color: #fff; }

.meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  font-size: 0.8125rem;
  color: var(--ink-muted);
}
.meta b { font-weight: 500; color: var(--ink); }

.rule { height: 1px; background: rgba(166, 205, 250, 0.35); border: 0; margin: 0; }

/* ------------------------------ Controls -------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.85em 1.4em;
  border-radius: var(--r-btn);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
}
.btn--primary {
  background: var(--ink);
  color: #fff;
  box-shadow: var(--lift-dark);
}
.btn--primary:hover { background: #0d2c56; transform: translateY(-1px); box-shadow: 0 3px 6px rgba(2,11,24,.32), 0 18px 36px rgba(2,11,24,.38); }
.btn--primary:active { transform: translateY(0); box-shadow: var(--lift-dark); }
.btn--ghost { border-color: rgba(166, 205, 250, 0.7); color: var(--ink); background: rgba(255, 255, 255, 0.6); }
.btn--ghost:hover { background: var(--surface); border-color: var(--accent); }
/* Icons carry explicit width/height attributes so they size correctly before
   the stylesheet arrives. These rules make the size unconditional: a stray
   missing attribute on an inline SVG otherwise falls back to the replaced
   element default of 300x150 and blows the layout apart. */
.i { flex: none; width: 17px; height: 17px; }

/* ------------------------------- Header --------------------------------- */
.site-head {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(247, 251, 255, 0.82);
  backdrop-filter: saturate(1.6) blur(14px);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 1px solid rgba(166, 205, 250, 0.28);
}
.site-head__in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  min-height: 72px;
}
/* The DigitON mark is a white knockout logo: it only reads on a dark ground.
   So it never sits bare on the pale ground — it always sits on its own navy
   chip. The asset itself is never recoloured or modified. */
.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  background: var(--navy);
  border-radius: 999px;
  padding: 0.5rem 0.95rem 0.5rem 0.6rem;
  box-shadow: var(--lift-1);
  transition: box-shadow var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.brand:hover { background: var(--navy-deep); box-shadow: var(--lift-2); }
.brand img { height: 22px; width: auto; }
.site-nav { display: flex; align-items: center; gap: var(--s-5); }
.site-nav__links { display: flex; align-items: center; gap: var(--s-5); }
.site-nav a {
  text-decoration: none;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink-muted);
  transition: color var(--t-fast) var(--ease);
}
.site-nav a:hover { color: var(--ink); }
/* .site-nav a is more specific than .btn, so the primary CTA inside the nav
   inherited the muted link colour and rendered navy-on-navy. Restated here. */
.site-nav .btn--primary,
.site-nav .btn--ghost { color: inherit; }
.site-nav .btn--primary { color: #fff; }
.site-nav a.is-current {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--room);
  text-decoration-thickness: 2px;
}
.site-nav .btn { font-size: 0.875rem; padding: 0.7em 1.15em; }
/* On a phone the nav cannot sit beside the brand, but the in-page links still
   navigate a 9,000px case study, so hiding them was the wrong trade: the reader
   lost every section of the document. Instead the brand and the CTA keep the top
   row, and the section links become a scrollable strip on their own row —
   reachable, still one tap, never wider than the viewport, and the primary
   action is never the thing that scrolls out of reach. */
/* The desktop row holds brand + four section links + CTA. Below this width that
   stops being a row and starts squeezing the links onto two lines each, so the
   strip layout takes over earlier than a phone-only breakpoint would. */
@media (max-width: 900px) {
  .site-head__in { flex-wrap: wrap; padding-bottom: 0.4rem; }
  /* display:contents dissolves the nav wrapper so its two children become flex
     items of the header row directly: the CTA lands beside the brand, and only
     the section links drop to a second full-width row. Keeping the CTA inside
     the nav pushed it onto the scrolling row, where it wrapped to two lines and
     overlapped the strip. */
  .site-nav { display: contents; }
  .site-nav > .btn { order: 1; margin-left: auto; }
  .site-nav__links {
    order: 3;
    gap: var(--s-4);
    width: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    padding-bottom: 0.35rem;
    /* Fade the right edge so a link scrolled out of view reads as cut off
       rather than as the list simply ending. */
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  }
  .site-nav__links::-webkit-scrollbar { display: none; }
  .site-nav__links a { flex: none; padding-block: 0.45rem; white-space: nowrap; }
}

/* =========================== THE PLATE ================================== */
/* One authored object, used for every project on both surfaces. The whole
   plate is the link target: one click, one destination, one focus ring. */
.plate {
  position: relative;
  display: block;
  border-radius: var(--r-plate);
  overflow: hidden;
  background: var(--navy-deep);
  text-decoration: none;
  isolation: isolate;
  box-shadow: var(--lift-2);
  transition: box-shadow var(--t-slow) var(--ease), transform var(--t-slow) var(--ease);
}
.plate__media { position: relative; aspect-ratio: 5 / 6; overflow: hidden; }
.plate__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.001);
  transition: transform var(--t-slow) var(--ease), filter var(--t-slow) var(--ease);
}
.plate__scrim {
  position: absolute;
  inset: 0;
  /* Two stops: a floor gradient for the type block, and a flat wash over the
     whole lower half. The flat wash is what keeps white text legible over a
     bright screenshot plate, where a gradient alone still lets the image
     through. */
  background:
    linear-gradient(
      to top,
      rgba(2, 11, 24, 0.97) 0%,
      rgba(2, 11, 24, 0.92) 26%,
      rgba(2, 11, 24, 0.72) 46%,
      rgba(2, 11, 24, 0.18) 68%,
      rgba(2, 11, 24, 0) 84%
    ),
    linear-gradient(to top, rgba(2, 11, 24, 0.62) 0%, rgba(2, 11, 24, 0) 46%);
}
.plate__body {
  position: absolute;
  inset: auto 0 0 0;
  padding: clamp(1.4rem, 2.4vw, 2.25rem);
  color: #fff;
}
.plate__title {
  font-size: clamp(1.5rem, 2.1vw, 2.05rem);
  line-height: 1.1;
  letter-spacing: -0.028em;
  margin-top: 0.7rem;
}
.plate__note {
  margin-top: 0.55rem;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: #c3daf3;
  max-width: 42ch;
  text-wrap: pretty;
}
.plate__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  margin-top: 1.15rem;
  padding-top: 1.05rem;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  font-size: 0.875rem;
  font-weight: 500;
}
.plate__cta { display: inline-flex; align-items: center; gap: 0.5em; }
/* The wipe: the one motion in the build, authored once. */
.plate__rule {
  position: absolute;
  left: clamp(1.4rem, 2.4vw, 2.25rem);
  right: clamp(1.4rem, 2.4vw, 2.25rem);
  bottom: 0;
  height: 2px;
  background: var(--plate-accent, #8fc2f8);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--t-slow) var(--ease);
}
.plate .i-arrow { transition: transform var(--t-slow) var(--ease); }

@media (hover: hover) {
  .plate:hover { transform: translateY(-4px); box-shadow: var(--lift-3); }
  .plate:hover .plate__img { transform: scale(1.06); }
  .plate:hover .plate__scrim {
    background:
      linear-gradient(
        to top,
        rgba(2, 11, 24, 0.98) 0%,
        rgba(2, 11, 24, 0.94) 28%,
        rgba(2, 11, 24, 0.76) 48%,
        rgba(2, 11, 24, 0.22) 70%,
        rgba(2, 11, 24, 0) 86%
      ),
      linear-gradient(to top, rgba(2, 11, 24, 0.68) 0%, rgba(2, 11, 24, 0) 48%);
  }
  .plate:hover .plate__rule { transform: scaleX(1); }
  .plate:hover .i-arrow { transform: translateX(8px); }
}
.plate:focus-visible { outline: 3px solid var(--room-ink); outline-offset: 4px; }

/* ------------------------------ Plate run ------------------------------- */
.plates {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.2vw, 2rem);
}
/* Editorial stagger: the even plates drop, so the run reads as a spread
   rather than a symmetric table. */
.plates > :nth-child(even) { margin-top: clamp(0rem, 5vw, 4.5rem); }
@media (max-width: 900px) {
  .plates { grid-template-columns: minmax(0, 1fr); }
  .plates > :nth-child(even) { margin-top: 0; }
}

/* ------------------------------- Footer --------------------------------- */
.site-foot {
  border-top: 1px solid rgba(166, 205, 250, 0.3);
  padding-block: var(--s-8) var(--s-6);
  margin-top: var(--band);
}
.site-foot__grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-6) var(--s-8);
  align-items: flex-start;
  justify-content: space-between;
}
.site-foot p { font-size: 0.9375rem; color: var(--ink-muted); max-width: 38ch; }
.site-foot nav { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); }
.site-foot nav a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  font-size: 0.9375rem;
  color: var(--ink-muted);
  text-decoration: none;
  transition: color var(--t-fast) var(--ease);
}
.site-foot nav a:hover { color: var(--ink); text-decoration: underline; }
.site-foot__base {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  justify-content: space-between;
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid rgba(166, 205, 250, 0.3);
  font-size: 0.8125rem;
  color: var(--ink-faint);
}
/* The published-project link in the colophon is 13px inline text; it still needs
   a 24px target on touch, so the hit area is padded without changing the type. */
.site-foot__base a {
  display: inline-block;
  padding-block: 0.3rem;
  color: var(--ink-muted);
  text-decoration: underline;
  text-decoration-color: rgba(74, 109, 143, 0.4);
  text-underline-offset: 0.22em;
  transition: color var(--t-fast) var(--ease);
}
.site-foot__base a:hover { color: var(--ink); text-decoration-color: currentColor; }

/* ======================= LANDING: intro band ============================ */
/* Sized so plate one starts inside the first viewport: the artefact leads,
   the interface recedes. */
/* Two columns at desktop: the statement and its support sit side by side so
   the band stays short enough that plate one already shows on arrival. */
.intro__grid { display: grid; gap: var(--s-5) clamp(2rem, 4vw, 4rem); }
@media (min-width: 1000px) {
  .intro__grid { grid-template-columns: 7fr 5fr; align-items: start; }
  .intro__side { padding-top: 0.4rem; }
}
.intro { padding-top: clamp(2rem, 3.6vw, 3.25rem); padding-bottom: clamp(1.75rem, 3vw, 2.75rem); }
.intro__lead { margin-top: 0; }
@media (max-width: 999px) { .intro__lead { margin-top: var(--s-5); } }
.intro__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  margin-top: var(--s-5);
  font-size: 0.8125rem;
  letter-spacing: 0.01em;
  color: var(--ink-faint);
}
.intro__actions { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-5); }
.intro__rule { margin-top: clamp(1.5rem, 2.6vw, 2.5rem); }

/* The plate run starts tight under the intro, so plate one's top edge is
   already in the first viewport at desktop height. */
#projets { padding-top: clamp(1.5rem, 2.6vw, 2.5rem); }

/* ------------------------- LANDING: quiet band ------------------------- */
/* A dense passage of four plates earns a quiet one. */
.method { display: grid; gap: var(--s-6); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .method { grid-template-columns: 5fr 7fr; gap: clamp(2rem, 5vw, 5rem); } }
.method__list { display: grid; gap: var(--s-4); margin-top: var(--s-6); }
.method__list li {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.35rem;
  padding-top: var(--s-4);
  border-top: 1px solid rgba(166, 205, 250, 0.35);
  font-size: 0.9375rem;
  color: var(--ink-muted);
}
/* Two columns only once there is room for a label column; below that the
   label stacks rather than squeezing the prose into a narrow strip. */
@media (min-width: 760px) {
  .method__list li {
    grid-template-columns: 14rem minmax(0, 1fr);
    gap: var(--s-6);
    align-items: baseline;
  }
}
.method__list b { color: var(--ink); font-weight: 500; }

/* ============================ CASE STUDY ================================ */
/* The room light: the client's hue bleeding down from the top of the page.
   Authored once per surface, never repeated as a section. */
.room-light {
  position: absolute;
  inset: 0 0 auto 0;
  height: min(760px, 78vh);
  pointer-events: none;
  z-index: -1;
  background:
    radial-gradient(70% 52% at 50% -12%, var(--room-light), transparent 68%),
    radial-gradient(46% 40% at 88% 8%, var(--room-wash), transparent 70%);
}

.crumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55em;
  font-size: 0.8125rem;
  color: var(--ink-faint);
  text-decoration: none;
}
/* Padding so the breadcrumb's tap target clears 24px in both axes; the text
   itself is 13px, which is too small a target on a touch screen. */
.crumb a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  color: var(--ink-muted);
  text-decoration: none;
  transition: color var(--t-fast) var(--ease);
}
.crumb a:hover { color: var(--ink); text-decoration: underline; }
.crumb svg { flex: none; opacity: 0.6; }

.case-head { padding-top: clamp(2.5rem, 5vw, 4.5rem); }
.case-head h1 { margin-top: var(--s-5); }
.case-head__summary { margin-top: var(--s-5); }
.case-head__facts {
  display: grid;
  gap: var(--s-5) var(--s-6);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: var(--s-5);
  border-top: 1px solid rgba(166, 205, 250, 0.35);
}
.fact__k {
  display: block;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.fact__v { display: block; margin-top: 0.35em; font-size: 1rem; font-weight: 500; }

/* Chapter: a label column that holds while the prose column scrolls. */
.chapter { display: grid; gap: var(--s-5) clamp(2rem, 5vw, 5rem); }
@media (min-width: 900px) { .chapter { grid-template-columns: 4fr 8fr; } }
.chapter__label { font-family: var(--font-display); font-size: clamp(1.5rem, 2.4vw, 2.1rem); letter-spacing: -0.03em; line-height: 1.1; }
@media (min-width: 900px) {
  .chapter__sticky { position: sticky; top: calc(72px + var(--s-7)); align-self: start; }
}

/* Figures: real product screenshots, full-bleed in their own white frame. */
.shots { display: grid; gap: clamp(1.5rem, 3vw, 2.75rem); margin-top: clamp(2.5rem, 5vw, 4rem); }
.shot { margin: 0; }
.shot__frame {
  border-radius: var(--r-plate);
  overflow: hidden;
  background: var(--surface);
  border: 1px solid rgba(166, 205, 250, 0.32);
  box-shadow: var(--lift-2);
}
.shot__frame img { width: 100%; height: auto; }
.shot figcaption {
  margin-top: var(--s-4);
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--ink-muted);
  max-width: 56ch;
}
.shot--duo { display: grid; gap: clamp(1rem, 2vw, 1.5rem); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.shot--duo .shot__frame { box-shadow: var(--lift-1); }
@media (max-width: 620px) { .shot--duo { grid-template-columns: minmax(0, 1fr); } }

/* Capability list — what the platform does, in the product's own words. */
.specs { display: grid; gap: 0; margin-top: clamp(2rem, 4vw, 3rem); border-top: 1px solid rgba(166, 205, 250, 0.35); }
.specs li {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.2rem;
  padding-block: var(--s-5);
  border-bottom: 1px solid rgba(166, 205, 250, 0.35);
}
.specs li:first-child { padding-top: var(--s-6); }
.specs li:last-child { padding-bottom: var(--s-6); }
@media (min-width: 760px) { .specs li { grid-template-columns: 3fr 7fr; gap: var(--s-6); align-items: baseline; } }
.specs b { font-weight: 500; }
.specs span { color: var(--ink-muted); font-size: 0.9375rem; }

/* Evidence: published figures and a real signed word. Never invented. */
.figures {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: var(--s-5);
  border-top: 1px solid rgba(166, 205, 250, 0.35);
}
.figure__n {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 4.5vw, 3.75rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1;
  color: var(--room-ink);
  font-variant-numeric: tabular-nums;
}
.figure__k { display: block; margin-top: 0.5em; font-size: 0.9375rem; color: var(--ink-muted); }

.quote { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); align-items: start; }
@media (min-width: 820px) { .quote { grid-template-columns: 5fr 7fr; } }
.quote__frame {
  border-radius: var(--r-plate);
  overflow: hidden;
  border: 1px solid rgba(166, 205, 250, 0.32);
  background: var(--surface);
  box-shadow: var(--lift-2);
}
.quote__frame img { width: 100%; height: auto; }
.quote blockquote { margin: 0; }
.quote blockquote p {
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 1.7vw, 1.5rem);
  line-height: 1.42;
  letter-spacing: -0.02em;
  text-wrap: pretty;
}
.quote figcaption { margin-top: var(--s-5); font-size: 0.875rem; color: var(--ink-muted); }
.quote figcaption b { display: block; font-weight: 500; color: var(--ink); }

/* The real close: the next project, then the one honest exit. */
.next { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: center; }
@media (min-width: 980px) { .next { grid-template-columns: 5fr 7fr; } }
.next__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4);
  margin-top: var(--s-6);
}

/* ----------------------------- Reveal ----------------------------------- */
/* One reveal, exponential ease-out, from an already-visible default so a
   failed observer never hides content. */
/* The hidden start state is gated behind .js, which site.js sets in <head>
   before first paint. So: no JS means no hidden state and no flash; JS means
   the state exists from the very first frame. The .revealed failsafe in
   site.js guarantees content can never be stranded invisible. */
.js [data-rise] { opacity: 0; transform: translateY(14px); }
.js .is-lit [data-rise] {
  opacity: 1;
  transform: none;
  transition: opacity var(--t-med) var(--ease), transform var(--t-slow) var(--ease);
  transition-delay: var(--d, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  [data-rise] { opacity: 1; transform: none; }
}

/* ------------------------- Windows high contrast --------------------------
   The scrim is load-bearing: it is the only reason white text survives a bright
   screenshot plate. High Contrast overrides background colours and would strip
   it, leaving white on white. So the plate keeps its own opaque ground and the
   text takes the system colour, which is the one combination that is guaranteed
   to be legible in that mode. */
@media (forced-colors: active) {
  .ground, .room-light { display: none; }
  .site-head { background: Canvas; border-bottom-color: CanvasText; }
  .plate { background: Canvas; border: 1px solid CanvasText; forced-color-adjust: none; }
  .plate__scrim { background: Canvas; }
  .plate__media { display: none; }
  .plate__body { color: CanvasText; position: static; }
  .plate__note, .tags--onimage, .plate__cta { color: CanvasText; }
  .i { color: CanvasText; }
  .plate__foot { border-top-color: CanvasText; }
  .plate__rule { background: Highlight; }
  .shot__frame, .quote__frame { border: 1px solid CanvasText; box-shadow: none; }
  /* CanvasText rather than LinkText, and stated at the same specificity as the
     rules it has to beat: .site-nav .btn--primary is more specific than a bare
     .btn--primary, so a lower-specificity override here left the header CTA
     painting its own white on the forced white Canvas — an invisible button.
     Only two tone pairs are guaranteed to be legible in this mode. */
  .btn, .btn--primary, .btn--ghost,
  .site-nav .btn--primary, .site-nav .btn--ghost, .site-nav a {
    background: Canvas;
    color: CanvasText;
    border: 1px solid CanvasText;
    box-shadow: none;
    forced-color-adjust: none;
    text-decoration-color: CanvasText;
  }
  .site-nav .btn--primary:hover { background: Canvas; color: CanvasText; }
  .site-foot nav a, .crumb a, .site-foot__base a, .site-nav a {
    color: LinkText;
  }
  :focus-visible { outline: 3px solid Highlight; }
}

/* -------------------------- Increased contrast ----------------------------
   The palette already passes AA. When the OS asks for more, the two greys that
   carry secondary prose are pushed darker so the hierarchy survives, and the
   room accents get their ink variant rather than their decorative hue. */
@media (prefers-contrast: more) {
  :root {
    --ink-muted: #2c4a68;
    --ink-faint: #34566f;
    --line: #6ba3e0;
  }
  .rule, .specs, .specs li, .figures, .case-head__facts,
  .method__list li, .site-foot, .site-foot__base { border-color: var(--line); }
}

/* ------------------------------- Print ---------------------------------- */
@media print {
  .ground, .site-head, .room-light { display: none; }
  body { background: #fff; }
  .plate { break-inside: avoid; box-shadow: none; border: 1px solid #ccc; }
}