/* ==========================================================================
   Maison Alchemy — self-hosted fonts (BACKLOG 1.8, 2026-09-06)
   No third-party font request (perf + GDPR for an EU audience); everything
   serves from /fonts (relative to /css/, hence the ../fonts/ paths).

   Display is Cocomat Pro — the client's own brand typeface, from the family
   they sent (docs/creative/Maison_Alchemy_Website/cocomat-pro/). Weights
   400/500/700; CSS font-matching resolves the site's many `600`s up to Bold.
   (It replaced Space Grotesk on 2026-09-06, operator decision; the 3D cube's
   baked-in Space Grotesk glyphs are the one place the old face survives —
   regenerating the GLB with Cocomat is an open follow-up.)
   Body stays Inter (variable latin woff2, the file Google itself ships).
   ========================================================================== */
@font-face {
  font-family: 'Cocomat Pro';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/cocomat-pro-regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Cocomat Pro';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/cocomat-pro-medium.woff2') format('woff2');
}
@font-face {
  font-family: 'Cocomat Pro';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/cocomat-pro-bold.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/inter-var-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   Maison Alchemy — design tokens
   ========================================================================== */
:root {
  --ink:         #171412;
  --ink-soft:    #3A342E;
  --paper:       #FAF7F2;
  --paper-alt:   #F1EAE0;
  /* Luxe pass 2026-09-07: cards are no longer opaque white slabs — a
     translucent lift lets the sheet's grain run through every card on the
     site (research: luxury surfaces are the same paper, delimited by
     hairlines, not covered by plastic). Components that must stay solid
     (the floating ptable panel) opt out locally. */
  --card: rgba(255, 255, 255, .55);
  --line:        #DFD6C6;
  --muted:       #6B6459;
  /* The client deck's bordeaux/oxblood + cream/parchment, already converged
     (CLIENT_CONTENT_BRIEF.md §11). --maroon IS the deck bordeaux, --maroon-dark
     its oxblood; --paper/--paper-alt are the cream/parchment. Hexes unchanged.
     (2026-09-06: a full oxblood-ground experiment was built and REVERTED the
     same day -- the operator reviewed it and called the cream ground back.) */
  --maroon:      #7A2418;
  --maroon-dark: #59180F;
  --maroon-tint: #F4E7E2;
  --cream:       #FAF7F2; /* aliases kept: harmless, some tools referenced them */
  --ink-deep:    #171412;
  --line-cream:  #DFD6C6;

  /* Craft colours -- one hue per real Craft (CONCEPT.md §5's retargeted element
     set), kept in the same muted/matte ink-on-paper register as the brand maroon.
     Scoped to their own cell/plate only -- never page-level UI colour. */
  --craft-identity:         #A2461F;  /* Br -- Brand Strategy & Identity */
  --craft-identity-tint:    #F3E0D2;
  --craft-formulation:      #55622E;  /* For -- Product Dev, Formulation & Manufacturing */
  --craft-formulation-tint: #E7EBD9;
  --craft-marketing:        #93641D;  /* Mk -- Marketing, Growth & Social Media */
  --craft-marketing-tint:   #F2E6D2;  /* the deck's cream/parchment note */
  --craft-audit:            #7A2418;  /* Str -- Business Strategy Consulting & Audits */
  --craft-audit-tint:       #F4E7E2;
  --craft-workshops:        #603152;  /* Wo -- Workshops & Facilitation */
  --craft-workshops-tint:   #ECE0E7;
  --craft-expansion:        #32475B;  /* Exp -- Global Market Expansion */
  --craft-expansion-tint:   #DDE4E9;

  --font-display: "Cocomat Pro", "Arial Rounded MT Bold", "Arial Black", sans-serif;
  --font-body:    "Inter", -apple-system, BlinkMacSystemFont, sans-serif;

  /* Operator round 2026-09-06e: ONE container width for every section — the
     widest in use (the Four Stages / Seven disciplines width). Mixed widths
     made section left edges disagree down the Home page. */
  --container: 1360px;
  --radius: 2px;

  /* --------------------------------------------------------------------
     SPACING LADDER -- Fibonacci (client call 2026-09-11)
     Client note: « il y a des espaces qui n'ont pas forcement de sens [...]
     ces espaces doivent suivre un ratio lie a la suite de Fibonacci ».

     Why the sequence rather than a flat 4/8pt grid: consecutive Fibonacci
     terms converge on the golden ratio (1.618), so each step is ~1.6x the
     last. A linear grid (8/16/24/32) makes 24 and 32 nearly
     indistinguishable, so a designer reaching for "a bit more room" picks an
     arbitrary neighbour and the page ends up with dozens of gap values that
     encode no hierarchy -- exactly the state this file was in (measured
     2026-09-11: 48 distinct padding/margin values). A ratio scale makes
     every step VISIBLY a different rank, so the gap itself tells the reader
     whether two blocks belong together. That legibility, not any mystical
     property of the sequence, is why ratio scales are the house standard for
     typographic systems -- the same reason type scales are ratio-based.

     Rule: every STRUCTURAL gap comes from this ladder. Micro-spacing inside
     a component (icon gaps, chip padding) may stay off-ladder -- it carries
     no hierarchy and normalising it buys nothing.
     -------------------------------------------------------------------- */
  --sp-1:   3px;  /* hairline separation */
  --sp-2:   5px;  /* label to its value */
  --sp-3:   8px;  /* items in a tight list */
  --sp-4:  13px;  /* kicker to title */
  --sp-5:  21px;  /* paragraph to paragraph */
  --sp-6:  34px;  /* element to element inside a block */
  --sp-7:  55px;  /* block to block; a section's own breathing room */
  --sp-8:  89px;  /* page opening; a section carrying extra weight */
  --sp-9: 144px;  /* a full change of movement */
  --ease: cubic-bezier(.19,1,.22,1);
  /* Luxe pass: decorative hovers move SLOWLY (research: slow + quiet reads
     expensive; snappy reads app-like). Functional feedback keeps --ease. */
  --slow: .45s cubic-bezier(.19,1,.22,1);
}

/* ==========================================================================
   Reset
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; overflow-x: clip; }
body {
  margin: 0;
  /* Client call 2026-09-09: the footer sits at the very bottom even when a
     page runs shorter than the viewport (the Journal before entries load).
     The trio: flex-column body, main grows (rule after this block),
     header/footer keep their height. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* Safety net for the craft cube's full-bleed pin (row 16): 100vw can exceed
     the visible viewport by the scrollbar's own width, so this guarantees no
     horizontal page scrollbar ever appears regardless of that subpixel delta.
     `clip` (not `hidden`) is required here: per spec, pairing a non-`visible`
     value on one axis with an implicit/`visible` value on the other forces
     the `visible` axis to compute as `auto`, which turns body into its own
     scroll container and breaks position: sticky for .craft-cube__pin.
     `overflow-x: clip` doesn't trigger that promotion, so overflow-y stays
     the page's natural `visible` and sticky keeps working. */
  overflow-x: clip;
  /* background lives in ONE place: the papyrus-sheet `body` rule near the end
     of this file (background-color + fibre layers). A `background: var(--paper)`
     shorthand here was dead weight — every longhand it set was overridden
     there — and a trap for the next reader (BACKLOG 1.3). */
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
}
main { flex: 1 0 auto; }
.site-header, .site-footer { flex-shrink: 0; }
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, p, dl, dd, blockquote, figure { margin: 0; }
h1, h2, h3 { text-wrap: balance; }
button { font: inherit; cursor: pointer; }
input, textarea { font: inherit; }

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: 24px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 12px 18px;
  z-index: 200;
}
.skip-link:focus { left: 16px; top: 16px; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; scroll-snap-type: none; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; transition-delay: 0ms !important; }
  /* Row 20: no cursor radius, no stagger — every logo static at full color. */
  .logo-strip__logo { --p: 1 !important; }
}

/* Visible keyboard focus (WCAG) — ring in brand maroon, only for keyboard users */
:focus-visible {
  outline: 2px solid var(--maroon);
  outline-offset: 2px;
  border-radius: 1px;
}

/* Fixed header offset so anchor targets aren't hidden behind it */
:target,
section[id],
main[id] {
  scroll-margin-top: 92px;
}

/* Scroll-reveal (JS toggles .is-visible via IntersectionObserver).
   Row 44a — LA FRAPPE: arrivals land short and heavy like a character
   struck into the paper (12px, .55s), siblings in cascade via the --md
   delay main.js computes per group. main.js strips .reveal/.is-visible at
   transitionend, so an element's own authored transitions (hover lifts,
   color soaks) take back over untouched once it has arrived. */
.reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .55s var(--ease) var(--md, 0ms), transform .55s var(--ease) var(--md, 0ms);
}
.reveal.is-visible { opacity: 1; transform: none; }
/* Row 44c — LA PRESSE: a seal does not fade in, it is pressed on. */
.reveal--press { transform: scale(1.05); transform-origin: 50% 60%; }
.reveal--press.is-visible { transform: none; }

/* ==========================================================================
   Type scale
   ========================================================================== */
.section-kicker {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--maroon);
  margin-bottom: var(--sp-4);
  text-wrap: balance;
}
/* Luxe round row 35: the printed-luxury ornament — a small four-pointed star
   leads every kicker, in the warm gold of the reference ink. */
.section-kicker::before {
  content: '\2726';
  margin-right: 9px;
  color: #B67E46;
}
.section-kicker--light { color: #E8B7A8; }

.section-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(28px, 3.6vw, 42px);
  line-height: 1.12;
  letter-spacing: -.022em;
  margin-bottom: var(--sp-5);
  text-wrap: balance;
}

.section-lead {
  /* Client 2026-09-07 (#8/#14): the lead reads to the title's own measure,
     not a short orphan column beneath it.
     Client call 2026-09-09 (T2): wider still — the copy under a title was
     wrapping too early and reading cramped. */
  max-width: 78ch;
  color: var(--muted);
  font-size: 17px;
  text-wrap: pretty;
}
.section-lead--light { color: #D9CFC6; }
.section-lead--programs {
  max-width: none;
  margin-top: 40px;
}

.section-head { margin-bottom: var(--sp-7); }

/* Services hero: large, near-invisible engraving-style SVG watermark behind
   the headline (see comment in services.html for the concept). Purely
   decorative reinforcement — kept out of the text flow and off the a11y tree
   so it never competes with headline contrast/legibility. */
.hero-services .section-head { position: relative; }
.hero-services__glyph {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 145%;
  height: 145%;
  min-width: 120%;
  min-height: 120%;
  transform: translate(-50%, -50%);
  color: var(--maroon);
  opacity: .06;
  z-index: 0;
  pointer-events: none;
}
.hero-services .section-head > :not(.hero-services__glyph) { position: relative; z-index: 1; }
@media (max-width: 640px) {
  .hero-services__glyph { opacity: .05; }
}

/* ==========================================================================
   Brand mark (reproduces the periodic-table logo card in HTML/CSS)
   ========================================================================== */
.brand { display: inline-flex; align-items: center; gap: 12px; }

.brand-mark {
  position: relative;
  width: 40px;
  height: 40px;
  border: 2px solid var(--ink);
  background: var(--paper);
  flex-shrink: 0;
}
.brand-mark__num {
  position: absolute;
  top: 2px; left: 4px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 9px;
  color: var(--maroon);
}
.brand-mark__sym {
  position: absolute;
  bottom: 1px; right: 5px;
  /* Georgia, not the display grotesk: its serif'd "l" stays legible as
     lowercase-L next to a cap A — Space Grotesk's "l" is a bare stroke,
     visually identical to a capital letter I, which reads wrong. */
  font-family: Georgia, serif;
  font-weight: 700;
  font-size: 19px;
  color: var(--maroon);
}
.brand-mark--footer { border-color: var(--paper); background: transparent; }
.brand-mark--footer .brand-mark__sym,
.brand-mark--footer .brand-mark__num { color: var(--paper); }

.brand-word {
  display: flex;
  flex-direction: column;
  line-height: 1.05;
  font-family: var(--font-display);
}
.brand-word__top {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.brand-word__bottom {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.brand--footer .brand-word__top { color: #B8AFA3; }
.brand--footer .brand-word__bottom { color: var(--paper); }

/* Header wordmark: on pages whose top section is dark/maroon (body.dark-hero,
   e.g. contact.html's .contact { background: var(--maroon-dark) }), the
   fixed/transparent header sits directly over that dark surface until
   .is-scrolled swaps in the cream/blur background, making the default
   dark-ink wordmark illegible. Cream variant matches the footer's light
   values; reverts to normal ink once scrolled. Scoped to body.dark-hero so
   pages with a light/cream hero (index, services, academy, about, journal)
   keep the standard dark-on-cream wordmark at scroll-top. */
body.dark-hero .brand--header .brand-mark { border-color: var(--paper); background: transparent; }
body.dark-hero .brand--header .brand-mark__sym,
body.dark-hero .brand--header .brand-mark__num { color: var(--paper); }
body.dark-hero .brand--header .brand-word__top { color: #B8AFA3; }
body.dark-hero .brand--header .brand-word__bottom { color: var(--paper); }

/* Header nav on dark hero pages: white text on transparent background until
   scrolled. Focus outline changes to light cream for visibility on dark. */
body.dark-hero .main-nav a { color: var(--paper); }
body.dark-hero .main-nav a:hover { color: #F4E7E2; }
body.dark-hero .main-nav__cta {
  border-color: var(--paper);
  color: var(--paper) !important;
}
body.dark-hero .main-nav__cta:not(.btn-react):hover { background: var(--paper); color: var(--maroon-dark) !important; }
body.dark-hero .nav-toggle span { background: var(--paper); }
/* Row 36: the brand word must read cream over the oxblood hero (the
   is-scrolled reverts below already restore the dark-on-cream state). */
body.dark-hero .brand-word__top { color: #C9AD97; }
body.dark-hero .brand-word__bottom { color: #F5EAE0; }
body.dark-hero .site-header.is-scrolled .brand-word__top { color: var(--muted); }
body.dark-hero .site-header.is-scrolled .brand-word__bottom { color: var(--ink); }
body.dark-hero :focus-visible { outline-color: var(--paper); }

/* Revert nav colors to dark when header is scrolled */
body.dark-hero .site-header.is-scrolled .main-nav a { color: var(--ink-soft); }
body.dark-hero .site-header.is-scrolled .main-nav a:hover { color: var(--maroon); }
body.dark-hero .site-header.is-scrolled .main-nav__cta {
  border-color: var(--ink);
  color: var(--ink) !important;
}
body.dark-hero .site-header.is-scrolled .main-nav__cta:not(.btn-react):hover { background: var(--ink); color: var(--paper) !important; }
body.dark-hero .site-header.is-scrolled .nav-toggle span { background: var(--ink); }
body.dark-hero .site-header.is-scrolled :focus-visible { outline-color: var(--maroon); }

.site-header.is-scrolled .brand--header .brand-mark { border-color: var(--ink); background: var(--paper); }
.site-header.is-scrolled .brand--header .brand-mark__sym,
.site-header.is-scrolled .brand--header .brand-mark__num { color: var(--maroon); }
.site-header.is-scrolled .brand--header .brand-word__top { color: var(--muted); }
.site-header.is-scrolled .brand--header .brand-word__bottom { color: var(--ink); }

/* ==========================================================================
   Header
   ========================================================================== */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  border-bottom: 1px solid transparent;
  transition: background .3s var(--ease), border-color .3s var(--ease);
}
.site-header.is-scrolled {
  background: rgba(250, 247, 242, .92);
  /* Safari shipped backdrop-filter unprefixed only in 18; iOS/macOS Safari
     15-17 are still a real share of this client's Gulf audience and need
     the -webkit- alias or they lose the blur entirely. Cosmetic either way
     (the background is already 92% opaque) but free to support. */
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-bottom-color: var(--line);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 76px;
}

.main-nav { display: flex; align-items: center; gap: 32px; }
.main-nav a {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-soft);
  transition: color var(--slow); /* row 41: nav hovers breathe, not snap */
}
.main-nav a:hover { color: var(--maroon); }
.main-nav__cta {
  border: 1.5px solid var(--ink);
  padding: 9px 18px;
  color: var(--ink) !important;
  font-family: var(--font-display);
  letter-spacing: .02em;
}
.main-nav__cta:not(.btn-react):hover { background: var(--ink); color: var(--paper) !important; }

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  background: none;
  border: none;
  padding: 0;
}
.nav-toggle span {
  display: block;
  height: 2px;
  background: var(--ink);
  transition: transform .25s var(--ease), opacity .25s var(--ease);
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 15px 28px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: .01em;
  border: 1.5px solid transparent;
  transition: background var(--slow), color var(--slow), border-color var(--slow), letter-spacing var(--slow);
  /* Restrained press feedback — matte scale-down, no glow/gradient */
  position: relative;
  overflow: hidden;
}
.btn--primary { background: var(--maroon); color: var(--paper); border-color: var(--maroon); }
/* Luxe pass: the lift is gone — flat field, slow deepen only. */
.btn--primary:hover { background: var(--maroon-dark); border-color: var(--maroon-dark); }
.btn--ghost { color: var(--ink); border-color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--paper); }
.btn--block { width: 100%; }
.btn:active { transform: scale(.97) translateY(0); }
.btn--primary:active { background: var(--maroon-dark); border-color: var(--maroon-dark); }
.btn::after {
  content: '';
  position: absolute;
  inset: 0;
  background: currentColor;
  opacity: 0;
  transition: opacity .5s var(--ease);
  pointer-events: none;
}
.btn:active::after { opacity: .08; transition: none; }

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  position: relative;
  overflow: hidden;
  /* Client 2026-09-07 (#1/#3): less air above the eyebrow, and the proof
     figures now close the first screen — so the band tightens. */
  /* The fixed header is 76px, so the opening needs --sp-9 above to clear it
     and still read as a deliberate silence. */
  padding: var(--sp-9) 0 var(--sp-7);
  border-bottom: 1px solid var(--line);
}
/* Operator round 2026-09-06c: the hero uses the FULL container width (it sat
   centred in a 760px box); the lead keeps its own readable measure below. */
.hero__inner { position: relative; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 28px;
}
/* R5: swap the full/short eyebrow text by breakpoint instead of duplicating
   markup for a visual-only fix — same node, same semantics either way. */
.eyebrow__short { display: none; }
@media (max-width: 640px) {
  .eyebrow__full { display: none; }
  .eyebrow__short { display: inline; }
}
.eyebrow__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px; height: 22px;
  border: 1.5px solid var(--maroon);
  color: var(--maroon);
  font-size: 11px;
}

.hero__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(36px, 5.6vw, 64px);
  line-height: 1.05;
  letter-spacing: -.032em;
  margin-bottom: 22px;
  text-wrap: balance;
}

/* Typographic accent inside the hero H1 (PAIRINGS.md row 19 device, reused
   here per round-3 feedback): a few letters of two ordinary headline words
   are colored with the existing craft accent tokens. No cell boxes, no
   borders, no tile motif, no per-letter background -- the words still read
   as plain words, just with the site's periodic-table identity legible in
   the first screen without scrolling. Letters carry no semantics and never
   split the word for a screen reader. */
.accent-letter--br { color: var(--craft-identity); }
.accent-letter--fo { color: var(--craft-formulation); }
.accent-letter--mk { color: var(--craft-marketing); }

.hero__baseline {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--maroon);
  padding-bottom: 16px;
  margin-bottom: 20px;
  border-bottom: 2px solid var(--ink);
  display: inline-block;
}

.hero__lead {
  font-size: 18px;
  color: var(--ink-soft);
  /* Client call 2026-09-09 (A9): the lead runs to the title's own width —
     it stops where "...the Formula," stops — instead of a squeezed column. */
  max-width: 820px;
  margin-bottom: 40px;
  text-wrap: pretty;
}

/* Hero critique R4 (2026-09-09): the astrolabe, engraved into the ground —
   same treatment as the Contact/AlchAdemy engravings (a mask, painted at a
   ground-adjacent tone, low opacity). Lives in the empty column to the
   right of the 820px-wide text column; hidden below ~1100px where that
   column no longer exists without colliding with the copy. */
.hero__astrolabe {
  display: none;
  position: absolute;
  top: 120px;
  right: 3%;
  width: 320px;
  height: 376px;
  background: #E4D2C2;
  opacity: .04;
  -webkit-mask: url("../img/engravings/astrolabe-v1.webp") no-repeat center / contain;
  mask: url("../img/engravings/astrolabe-v1.webp") no-repeat center / contain;
  pointer-events: none;
}
@media (min-width: 1100px) {
  .hero__astrolabe { display: block; }
}

/* R5: the compact mobile-only proof line — hidden on desktop, where the
   real stat strip is already in view above the fold. */
.hero__proof-mobile {
  display: none;
  font-size: 13px;
  color: #C9AD97;
  margin: -4px 0 0;
}
.hero__proof-mobile strong { color: #DDB877; font-weight: 700; }
@media (max-width: 720px) {
  .hero__proof-mobile { display: block; }
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 18px;
}

/* ==========================================================================
   Row 36 (operator 2026-09-07): the Home hero speaks from the deck's own
   oxblood — the reference sheet's ground — with gold in the lettering, then
   the page returns to parchment below. Cream variants of the sheet textures
   (ghost symbols + letterpress dust + crossed fibres) paint locally on the
   band; body.dark-hero (an existing pattern) turns the header cream until
   scroll. Only index.html carries .hero, so this styles one band.
   ========================================================================== */
.hero {
  background-color: #4E1913;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1100' height='1100' fill='none' stroke='%23FAF7F2' stroke-opacity='0.009' stroke-width='6'%3E%3Cg transform='rotate(8 250 290)'%3E%3Cpath d='M250 180 350 400H150Z'/%3E%3Cpath d='M195 330h110'/%3E%3C/g%3E%3Ccircle cx='790' cy='190' r='95'/%3E%3Ccircle cx='790' cy='190' r='6'/%3E%3Cg transform='rotate(168 920 660)'%3E%3Cpath d='M920 560 1020 760H820Z'/%3E%3C/g%3E%3Cg transform='translate(400 700) scale(1.15)'%3E%3Cpath d='M60 18a34 34 0 0 0 68 0'/%3E%3Ccircle cx='94' cy='84' r='34'/%3E%3Cpath d='M94 118v54M70 146h48'/%3E%3C/g%3E%3Cpath d='M180 990V800M180 990 120 830M180 990 60 880M180 990 240 830M180 990 300 880'/%3E%3Cg transform='rotate(-6 640 430)'%3E%3Crect x='560' y='350' width='160' height='160'/%3E%3Cpath d='M576 374h20'/%3E%3C/g%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='980'%20height='980'%20fill='none'%20stroke='%23C99B3F'%20stroke-opacity='0.16'%20stroke-width='1.2'%20stroke-linecap='round'%3E%3Cpath%20d='M212%2084V318'%20stroke-dasharray='5.5%205.5'/%3E%3Cpath%20d='M694%20596%20806%20708'%20stroke-dasharray='5%205.5'/%3E%3Cpath%20d='M446%20882H584'%20stroke-dasharray='5.5%205.5'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='7'%20height='7'%3E%3Cg%20fill='none'%20stroke-width='1.3'%20stroke-linecap='butt'%3E%3Cpath%20d='M-2%209%209%20-2M-5.5%205.5%205.5%20-5.5M1.5%2012.5%2012.5%201.5'%20stroke='%23FAF7F2'%20stroke-opacity='0.026'/%3E%3Cpath%20d='M-1.2%209.8%209.8%20-1.2M-4.7%206.3%206.3%20-4.7M2.3%2013.3%2013.3%202.3'%20stroke='%23000000'%20stroke-opacity='0.012'/%3E%3C/g%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='700'%20height='700'%3E%3Cfilter%20id='c'%20x='0'%20y='0'%20width='100%'%20height='100%'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.008'%20numOctaves='3'%20seed='5'%20stitchTiles='stitch'/%3E%3CfeColorMatrix%20type='matrix'%20values='0%200%200%200%200.98%200%200%200%200%200.95%200%200%200%200%200.88%200%200%200%200.032%200'/%3E%3C/filter%3E%3Crect%20width='700'%20height='700'%20filter='url(%23c)'/%3E%3C/svg%3E");
  background-size: 1100px 1100px, 980px 980px, 7px 7px, 700px 700px;
  border-bottom: 4px double #B67E46;
}
.hero .eyebrow { color: #C9AD97; }
.hero .eyebrow__num { border-color: #C99A56; color: #C99A56; }
/* Luxe round 5 (operator): round 4's full-gilded clip flattened the Br/Fo
   accents into the rest of the line AND its filter pipeline clipped the
   descender of Together's "g" (the drop-shadow of a clipped text renders
   through an intermediate texture bounded by the tight 1.05 line box).
   Back to a cream headline with a whisper of engraving via text-shadow
   (safe: no clip, no filter, descenders intact) — and the two accent
   pairs alone are struck in engraved gold, standing out of the line like
   element symbols. No tile frames: the operator weighed and rejected
   them ("pas de logique... fait jouet"). Br and Fo carry no descenders,
   so clipping them is safe. */
.hero__title {
  color: #F5EAE0;
  text-shadow: 0 -1px 1px rgba(0, 0, 0, .38), 0 1px 0 rgba(255, 244, 224, .10);
}
.hero .accent-letter--br,
.hero .accent-letter--fo {
  background-image: linear-gradient(160deg, #F0DCA8 0%, #DDB877 45%, #B98A45 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: none;
  /* Row 44b — L'IGNITION: grayscale/brightness are padded into the filter
     list so the cold state below interpolates (same functions, same order).
     Lit is the identity values — this rule renders exactly as before. */
  filter: drop-shadow(0 1px 0 rgba(255, 240, 210, .28)) drop-shadow(0 -1px 1px rgba(0, 0, 0, .55)) grayscale(0) brightness(1);
  transition: filter .8s var(--ease);
}
/* Cold state, set by main.js before first paint and lifted a beat after the
   title lands: the two elements then IGNITE in gold. One-shot, load only. */
.hero .accent-letter--br.is-cold,
.hero .accent-letter--fo.is-cold {
  filter: drop-shadow(0 1px 0 rgba(255, 240, 210, .28)) drop-shadow(0 -1px 1px rgba(0, 0, 0, .55)) grayscale(1) brightness(.62);
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero .accent-letter--br, .hero .accent-letter--fo { color: #DDB877; filter: none; }
}
.hero__baseline { color: #C99A56; border-bottom-color: #B67E46; }
.hero__lead { color: #E4D2C2; }
.hero .cta-note { color: #C9AD97; }
/* Luxe round 4 (operator): round 3's dark ramp read cheap. The CTA now
   tells Rule X literally — SILVER on the left arriving at GOLD on the
   right, in a soft champagne register — and on hover a light beam sweeps
   across left-to-right in ~0.7s (the modern "shine sweep": a skewed
   white gradient band translated across, pure CSS, no library). */
/* Luxe round 6 (operator sent us to the books): luxury-web research is
   unanimous — expensive reads FLAT and restrained (no bevel, no gloss, no
   skeuomorphic metal: rounds 3-5 were wrong), monochrome plus one accent,
   and micro-interactions that are SLOW and quiet, never grabby. Cartier:
   dark ground, flat gold. So: one flat champagne-gold field, engraved
   spaced caps, and a single slow gesture on hover — the field warms one
   step and the letterspacing breathes open over half a second. Nothing
   else. (Sources: iiad.edu.in "why some websites feel expensive",
   typza.com minimalist luxury sites, ambrosemarketing.com luxury UX.) */
.hero .btn--primary {
  background: #C9A45C;
  border-color: #C9A45C;
  color: #35200C;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: background .5s var(--ease), letter-spacing .5s var(--ease);
}
.hero .btn--primary:hover {
  background: #D8B876;
  border-color: #D8B876;
  letter-spacing: .18em;
}
.hero .btn--ghost {
  border-color: #E4D2C2;
  color: #F5EAE0;
}
.hero .btn--ghost:hover { background: #F5EAE0; color: #4E1913; }

/* Anti-friction micro-copy under CTAs */
.cta-note {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: var(--sp-7);
}
.cta-note--form {
  margin-bottom: 0;
  margin-top: 14px;
  text-align: center;
}

/* Hero proof credits — the client's real "Clients seen on" line, sitting with the
   claim it backs (PAIRINGS.md row 10). Replaces the retired .stat-row/.stat-chip
   figures, which were invented and are deleted with their markup. */
.hero__credits {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 14px;
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  max-width: 640px;
}
.hero__credits-names {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* ==========================================================================
   Trust strip
   ========================================================================== */
.trust-strip { padding: var(--sp-6) 0; border-bottom: 1px solid var(--line); }
.trust-strip__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 20px 32px;
}
.trust-strip__label {
  font-size: 13px;
  color: var(--muted);
  white-space: nowrap;
}
.trust-strip__list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 28px;
}
.trust-strip__list li {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: .65;
}

/* Client logo strip — PAIRINGS.md row 20: real third-party marks (the only place
   raster images are used for a brand mark on this site; the site's OWN mark stays
   line-SVG per DESIGN.md §5). Sized per mark by LEGIBILITY, not by an identical
   box height (round-4 operator feedback): each `<li>` may set its own `--logo-h`,
   which the img inherits and falls back to the strip default when unset. Width
   stays auto so aspect ratio never distorts. Row 31 (2026-09-06, operator)
   SUPERSEDES row 10's marquee rejection for this surface: with JS and motion
   allowed the roster scrolls as a slow continuous marquee (styles under
   .is-marquee below); without either it wraps statically as before. */
.logo-strip__label--secondary { margin-top: var(--sp-6); }
/* Client call 2026-09-09 (A3): the roster labels step up from whisper to
   heading — centred display type; the logos, not the phrase, stay the proof. */
.logo-strip .trust-strip__label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(20px, 2.4vw, 30px);
  letter-spacing: -.018em;
  line-height: 1.15;
  color: var(--ink);
  text-align: center;
  white-space: normal;
  margin: 0;
}
.logo-strip .logo-strip__label--secondary {
  font-size: clamp(16px, 1.7vw, 21px);
  margin-top: var(--sp-7);
}
/* Round 5 (operator): the earlier full-bleed treatment (100vw + negative
   margin) is WITHDRAWN — the grid sits back inside .container like every
   other section; logos simply wrap onto more rows. */
/* Default mark height: 28px -> 34px (one Fibonacci step). The client's
   « aggrandir les logo qui sont trop petit » applies to a whole band of marks
   that sat at the default and read as fine grey lines; raising the default
   fixes them all at once, and the per-mark table below only handles the
   outliers on either side. */
.logo-strip { --logo-h: 34px; overflow: hidden; }
.logo-strip__grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center; /* centred rows under the centred heading (A3/A4) */
  align-items: center;
  gap: var(--sp-5) var(--sp-6);
  margin-top: var(--sp-5);
  list-style: none;
  padding: 0;
}
.logo-strip__logo {
  height: var(--logo-h);
  width: auto;
  max-width: 260px;
  object-fit: contain;
  /* --p (0..1) is the cursor-radius / touch-stagger proximity, written by
     js/main.js — 0 is the resting muted state, 1 is full color. Defaults to
     0 so the logo sits grayscale until script says otherwise; the no-JS and
     reduced-motion paths below force it to full color regardless. */
  --p: 0;
  /* Client call 2026-09-11: « il faut qu'on comprenne quelle est la marque
     directement a la 1ere vue ». The muted resting state was doing the
     opposite: grayscale(1) at .75 opacity washed thin and light marks off the
     cream entirely (measured: seven marks below 22% ink coverage, one at 0).
     The monochrome register is kept - it is the house look - but it now runs
     at near-full opacity with more contrast, so each mark reads as a solid
     silhouette instead of a ghost. Colour still arrives on proximity/hover. */
  filter: grayscale(calc(1 - var(--p))) contrast(calc(1.05 + (1 - var(--p)) * .2));
  opacity: calc(.92 + var(--p) * .08);
  transition: opacity .2s var(--ease), filter .2s var(--ease);
}
/* Marks DRAWN IN WHITE for dark grounds. On paper they are invisible at any
   size or opacity - there is no amount of contrast that rescues white on
   cream. Flipping them to ink is the only fix. (Measured 2026-09-11: THE DOUX
   differed from the page ground by 20/765 at its darkest pixel.) */
.logo-strip__logo[data-ink="light"] {
  filter: grayscale(calc(1 - var(--p))) invert(1) contrast(1.1);
}
/* Marks whose identity IS the colour: a filled badge or tile, where grayscale
   flattens the whole shape to one grey slab and the name inside it disappears.
   O'Tacos (white roundel knocked out of orange) and Y Combinator (white Y on
   orange) both measured under 190/765 peak contrast in monochrome. They keep
   their own ink - two colour marks among forty reads as a deliberate accent,
   not as a broken wall. */
.logo-strip__logo[data-ink="colour"] {
  filter: none;
  opacity: calc(.92 + var(--p) * .08);
}
/* Marks drawn in a PALE tint (light lilac, mid grey) rather than pure white:
   inverting them would be wrong - it flips their whole shape - but left alone
   they sit only a few shades off the paper and the name never resolves.
   Darkened into ink instead, which preserves the drawing. */
.logo-strip__logo[data-ink="pale"] {
  filter: grayscale(calc(1 - var(--p))) brightness(.62) contrast(1.5);
}
.logo-strip__logo:hover { filter: none; opacity: 1; }
/* Per-mark size overrides (round-4: "size by legibility, not by an identical
   box height"). Each rule sets --logo-h on the <li>; .logo-strip__logo reads it
   via the strip default above. Revlon / L'Oréal / Ajax already read well at
   28px and keep it. Colgate-Palmolive's shape reads fine but its wordmark's
   internal text is tiny at 28px, so it grows even though it wasn't asked to
   shrink. Turkish Airlines, O'Tacos and Dettol were flagged as too small /
   their in-logo text illegible, so they grow the most. The "Featured in" row
   (Shark Tank US/Egypt, Y Combinator) was the other "top-row" case called out
   as too small and grows to match. */
/* Row 31 v2: per-mark overrides target data-mark attributes, NOT nth-child —
   the marquee build slices the roster into three rows and clones each one,
   so positional indexes no longer survive; attributes do. Marks that sat at
   the 36px strip default (Revlon, L'Oréal, Ajax) need no rule at all. */
/* Client pass 5 (A4): uniformise by LEGIBILITY — the marks measured under
   ~60px wide at the 28px strip default were unreadable; each steps up until
   its NAME reads. Not one identical height: one identical presence. */
/* Client pass 2026-09-11: sizes re-derived from MEASURED ink coverage rather
   than by eye. Each mark was composited onto the real page ground at its real
   displayed size and its ink area recorded; marks far under the roster median
   are raised, marks far over it (the ones that ship as a filled rectangle, so
   their "ink" is mostly box) are trimmed, and the marks whose internal TEXT is
   the legibility limit (Colgate, Turkish, Dettol, ORS) keep the larger sizes
   they were given for that reason. */
.logo-strip__logo[src*="pg.svg"] { --logo-h: 48px; }
.logo-strip__logo[src*="ajax.svg"] { --logo-h: 50px; }
.logo-strip__logo[src*="billie.svg"] { --logo-h: 50px; }
.logo-strip__logo[src*="cantu.png"] { --logo-h: 47px; }
.logo-strip__logo[src*="lysol.svg"] { --logo-h: 55px; }
.logo-strip__logo[src*="purell.svg"] { --logo-h: 40px; }
.logo-strip__logo[src*="jackblack.svg"] { --logo-h: 40px; }
.logo-strip__logo[src*="mielle.svg"] { --logo-h: 42px; }
.logo-strip__logo[src*="desertsands.svg"] { --logo-h: 40px; } /* tiny set text */
.logo-strip__logo[src*="sharktankegypt.png"] { --logo-h: 55px; }
/* Raised hardest: measured at 8-21% ink, i.e. barely on the page. */
.logo-strip__logo[src*="roux.png"] { --logo-h: 83px; } /* x1.5 (was 55) */
.logo-strip__logo[src*="naturall.png"] { --logo-h: 110px; } /* x2 (was 55) */
.logo-strip__logo[src*="cremo.png"] { --logo-h: 66px; } /* x1.2 (was 55) */
.logo-strip__logo[src*="lottabody.png"] { --logo-h: 58px; } /* x1.7 (was the 34 strip default -- no prior override) */
.logo-strip__logo[src*="wonderpawpaw.png"] { --logo-h: 83px; } /* x1.5 (was 55) */
.logo-strip__logo[src*="fabuloso.png"] { --logo-h: 83px; } /* x1.5 (was 55) */
/* Trimmed: these ship as a solid filled rectangle, so at the default they
   read as blocks of ink shouting over their neighbours. */
.logo-strip__logo[src*="tresemme.png"] { --logo-h: 28px; }
.logo-strip__logo[src*="nexxus.png"] { --logo-h: 28px; }
.logo-strip__logo[src*="beardguyz.png"] { --logo-h: 40px; } /* now an illustrated lockup, not a plain wordmark -- needs the room */
.logo-strip__logo[src*="amika.png"] { --logo-h: 28px; }
/* A dark solid-ground square badge, same family as O'Tacos/Dettol/ORS/Miche
   already on this strip -- reads cleanly in grayscale at a normal height,
   no colour exemption needed. */
.logo-strip__logo[src*="everymanjack.png"] { --logo-h: 42px; }
.logo-strip__logo[src*="cremeofnature.svg"] { --logo-h: 30px; }
.logo-strip__logo[src*="miche.png"] { --logo-h: 38px; }
/* Inverted (see data-ink="light"), this one turns into the inkiest mark on the
   wall - it is a very heavy bold wordmark, so 72% of its box becomes solid.
   Held back a step so it sits with its neighbours instead of shouting. */
.logo-strip__logo[src*="thedoux.png"] { --logo-h: 26px; }
.logo-strip__logo[src*="vo5.png"] { --logo-h: 38px; }
.logo-strip__grid > li[data-mark="colgate"] { --logo-h: 52px; } /* wordmark text too small below */
.logo-strip__logo[src*="carolsdaughter.png"] { --logo-h: 44px; } /* x1.3 (was the 34 strip default) */
.logo-strip__grid > li[data-mark="turkish"] { --logo-h: 60px; } /* tiny in-logo text */
.logo-strip__grid > li[data-mark="dettol"] { --logo-h: 55px; }
.logo-strip__grid > li[data-mark="otacos"] { --logo-h: 68px; } /* x1.7 (client call 2026-09-11: "trop petit") */
.logo-strip__grid > li[data-mark="ors"] { --logo-h: 57px; } /* circular badge */
.logo-strip__label--secondary + .logo-strip__grid > li { --logo-h: 49px; } /* "Featured in" row: Shark Tank US/Egypt, Y Combinator — too small at strip default */
/* The full lockup is a wide wordmark (icon + "Combinator"), not a square
   icon -- held to a touch under the row default so it does not tower over
   Shark Tank's marks at the width that implies. */
.logo-strip__grid > li[data-mark="ycombinator"] { --logo-h: 42px; }
/* Touch/coarse-pointer ambient light-up (PAIRINGS.md row 20): a slower, softer
   transition than the desktop cursor radius so each logo's turn reads as a
   gentle glow rather than a snap. */
.logo-strip.is-touch-lit .logo-strip__logo {
  transition: opacity .9s var(--ease), filter .9s var(--ease);
}
/* --- Row 31: the roster as a slow continuous marquee. Every rule is gated
   behind .is-marquee, which ONLY js/main.js adds (JS on + motion allowed),
   so the no-JS and reduced-motion paths keep the static wrapped grid above
   untouched. The seamless loop: the track holds the original <ul> plus one
   aria-hidden clone; each <ul> carries its own column gap as padding-right,
   so translateX(-50%) of the track is an exact one-copy period. Duration is
   set inline by JS from the real track width (constant px/s at any size). --- */
.logo-strip.is-marquee .logo-strip__viewport {
  overflow: hidden;
  margin-top: 20px;
  /* Soft fade at both ends so marks enter/exit like ink resolving on the
     parchment instead of being guillotined at the container edge. */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
}
/* Row 31 v2 (operator): THREE rows — outer two drift east, the middle one
   west. Each track holds one row's <ul> plus its aria-hidden clone; both
   keyframes travel exactly one copy width (50% of the track), so the loop
   is seamless in either direction. Rows are sliced so every mark exists in
   exactly one row, and each row's single copy is wider than the container,
   so a mark and its clone are never in the visible window together. */
.logo-strip.is-marquee .logo-strip__track {
  display: flex;
  width: max-content;
}
.logo-strip.is-marquee .logo-strip__track--west { animation: logo-marquee-west 90s linear infinite; }
.logo-strip.is-marquee .logo-strip__track--east { animation: logo-marquee-east 90s linear infinite; }
/* Hovering a row pauses THAT row so a mark can be inspected; the existing
   .logo-strip__logo:hover rule colorizes the one under the cursor. This
   replaces row 20's cursor-radius proximity (its measured centres go stale
   on a moving track). */
.logo-strip.is-marquee .logo-strip__track:hover { animation-play-state: paused; }
.logo-strip.is-marquee .logo-strip__track .logo-strip__grid {
  flex-wrap: nowrap;
  width: max-content;
  margin-top: 0;
  padding-right: 36px; /* = the grid's own column gap: makes one copy an exact period */
}
@keyframes logo-marquee-west {
  to { transform: translateX(-50%); }
}
@keyframes logo-marquee-east {
  from { transform: translateX(-50%); }
  to { transform: translateX(0); }
}
/* Defense in depth: if the OS preference flips to reduced motion after the
   class already landed, the track freezes in place and stays legible. */
@media (prefers-reduced-motion: reduce) {
  .logo-strip.is-marquee .logo-strip__track { animation: none; }
}
/* Text placeholder for any mark that could not be sourced as a real file within
   scope (CONCEPT.md §7 tier 4's mandatory fallback) — never a fabricated logo. */
.logo-strip__placeholder {
  height: var(--logo-h);
  display: flex;
  align-items: center;
  padding: 0 10px;
  border: 1px dashed var(--line);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
/* Mobile: same legibility-tuned scale, just compressed so the strip's own
   grown marks don't overwhelm a 375px row. Ratios between marks are kept. */
@media (max-width: 640px) {
  .logo-strip { --logo-h: 29px; }
  .logo-strip__grid > li[data-mark="colgate"] { --logo-h: 39px; }
  .logo-strip__grid > li[data-mark="turkish"] { --logo-h: 44px; }
  .logo-strip__grid > li[data-mark="dettol"] { --logo-h: 42px; }
  .logo-strip__grid > li[data-mark="otacos"] { --logo-h: 88px; } /* x1.7 */
  .logo-strip__grid > li[data-mark="ors"] { --logo-h: 42px; }
  .logo-strip__label--secondary + .logo-strip__grid > li { --logo-h: 36px; }
}

/* ==========================================================================
   Section shell
   ========================================================================== */
/* Fibonacci ladder (2026-09-11). Was a flat 112px, so ANY two adjacent
   sections were separated by 224px whether or not they belonged together --
   the "espaces qui n'ont pas de sens" the client flagged. --sp-7 puts the
   normal join at 110px and frees --sp-8 to mark the joins that DO carry
   weight (page opening, the closing oxblood movement). */
.section { padding: var(--sp-7) 0; }
/* Every page OPENS at the same height, whatever the first section is. */
main > .section:first-child { padding-top: var(--sp-8); }
/* Four Stages section: reduced top padding (112px → 72px) to trim empty space */
/* Round 9: the craft-cube section now OPENS the Services page — its 112px
   section padding pushed the pinned frame down so far that the idling die's
   bottom left the viewport on arrival. Flush to the header instead. */
.craft-cube.section { padding-top: 0; }
/* Row 47a: the zeroed top padding serves the live pin only — every flat
   state needs its clearance under the fixed header back. */
.craft-cube.section:not(.is-live) { padding-top: var(--sp-8); }
/* Client call 2026-09-09 (T7): no die on small screens — the six discipline
   panels below carry every word; the flat leather net read as a broken toy
   on a phone. */
@media (max-width: 899px) {
  .craft-cube:not(.is-live) .craft-cube__stage { display: none; }
}

/* PAIRINGS.md row 21 (round 4): the stage object, its cast shadow and the graph
   curve must be free to escape this section's box; the old clipping was the
   bug. `overflow-x: clip` is deliberate and MUST NOT become bare
   `overflow-x: hidden`: a bare hidden on one axis forces the other axis to
   `auto` per spec, which breaks `position: sticky` (this section's own pin, and
   the header's) site-wide. `clip` has no such side effect. */
#stages { padding-top: var(--sp-7); overflow-x: clip; overflow-y: visible; }

/* Services hero: since the Four Stages block that used to follow it was
   removed (it now lives only on Home), the hero's stock 112px bottom padding
   plus the craft-cube section's 112px top padding left ~224px of empty space
   before Six Crafts. Trimmed to 56px here to close the gap. */
.hero-services { overflow-x: clip; padding-bottom: var(--sp-7); }

/* ==========================================================================
   Elements grid (periodic table of services)
   ========================================================================== */
.elements-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  perspective: 900px;
}
.element-card {
  --accent: var(--maroon);
  --accent-tint: var(--maroon-tint);
  background: var(--card);
  padding: 24px 22px 26px;
  min-height: 240px;
  display: flex;
  flex-direction: column;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transform-style: preserve-3d;
  transition: background var(--slow), border-color var(--slow);
  will-change: transform;
}
.element-card--br { --accent: var(--craft-identity);    --accent-tint: var(--craft-identity-tint); }
.element-card--fo { --accent: var(--craft-formulation); --accent-tint: var(--craft-formulation-tint); }
.element-card--mk { --accent: var(--craft-marketing);   --accent-tint: var(--craft-marketing-tint); }
.element-card--au { --accent: var(--craft-audit);       --accent-tint: var(--craft-audit-tint); }
.element-card--wk { --accent: var(--craft-workshops);   --accent-tint: var(--craft-workshops-tint); }
.element-card--ex { --accent: var(--craft-expansion);   --accent-tint: var(--craft-expansion-tint); }
.element-card:hover {
  background: var(--accent-tint);
  /* Luxe pass: fly-up + drop shadow retired — the card answers with a
     slow warm border instead. */
  border-color: var(--accent, var(--maroon));
  z-index: 1;
}
.element-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 18px;
}
.element-card__num {
  font-family: var(--font-display);
  font-size: 12px;
  color: var(--accent);
}
.element-card__icon { width: 20px; height: 20px; color: var(--accent); }
.element-card__sym {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 48px;
  line-height: 1;
  color: var(--accent);
  margin-bottom: 10px;
}
.element-card__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: .06em;
  text-transform: uppercase;
  margin-bottom: 10px;
}
.element-card__desc { font-size: 14px; color: var(--muted); text-wrap: pretty; }

/* "Al" (Maison Alchemy) card — the brand element the formula resolves into. */
.element-card--al { --accent: var(--maroon); --accent-tint: var(--maroon-tint); }
/* Georgia serif so the lowercase "l" never reads as a capital "I". */
.element-card__sym--al { font-family: Georgia, serif; }

/* Inline standalone "Al" inside prose (Al(Chemist), AlTanoor, ...) — same
   Georgia exception as the brand mark: Space Grotesk's "l" is a bare stroke
   and would read as "AI". Reused wherever the mark appears in running text. */
.al { font-family: Georgia, serif; }
/* Client call 2026-09-09 (T3/AB2): the gilt word — "alchemy" (and its kin)
   steps forward in gold wherever it appears inside a sentence. Never applied
   to the "Maison Alchemy" name itself. */
.gilt { color: #93641D; font-weight: 600; }

/* ==========================================================================
   About / pillars
   ========================================================================== */
.pillars {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 32px;
  overflow-x: clip;
}
.pillar {
  position: relative;
  border-top: 2px solid var(--ink);
  padding-top: 20px;
}
/* Icon scaled to the card's own background (round-3 pass), enlarged further and
   let loose past the card edge (round-4 global item 2): oversized, low-opacity,
   sits behind the copy in stacking order. `.pillar` no longer clips it -- the
   sigil is meant to spill into the grid gutter / neighbouring card, that
   cropped look is the point. `.pillars` clips horizontally as the safety net
   (html/body already carry a site-wide `overflow-x: clip`, so this is belt and
   braces, not the only guard). Opacity 0.06 is not a by-eye guess -- it's the
   highest value that still keeps the darkest realistic case (a fully solid icon fill, far
   worse than this stroke-only glyph ever produces) at >= 4.5:1 for --muted body text over
   --paper: ink-tinted blend measures 4.83:1, maroon-tinted blend measures 4.92:1 at 0.06
   (see commit message for the full computation). Decorative only. */
.pillar__icon-bg {
  position: absolute;
  z-index: 0;
  top: 50%;
  left: 50%;
  width: 145%;
  height: 145%;
  min-width: 120%;
  min-height: 120%;
  transform: translate(-50%, -50%);
  color: var(--ink);
  opacity: 0.06;
  pointer-events: none;
}
.pillar--feature .pillar__icon-bg { color: var(--maroon); }
.pillar__num { position: relative; z-index: 1; font-family: var(--font-display); font-size: 12px; color: var(--maroon); }
.pillar h3 {
  position: relative;
  z-index: 1;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 19px;
  margin: 10px 0 10px;
  text-wrap: balance;
}
.pillar p { position: relative; z-index: 1; font-size: 14.5px; color: var(--muted); text-wrap: pretty; }

/* Client roster interleaved inside the pillar whose claim it evidences. Type, not
   raster logos (PAIRINGS.md row 10); reuses the .trust-strip__list type treatment. */
.pillar__proof {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
.pillar__proof .trust-strip__label { margin-bottom: 10px; white-space: normal; }
.pillar__proof .trust-strip__list { gap: 8px 18px; }
/* The strip's inherited .65 opacity lands at 4.1:1 on --paper; inside the pillar the
   roster is body-adjacent reading, so raise it to clear DESIGN.md 7's 4.5:1 floor (6.4:1). */
.pillar__proof .trust-strip__list li { opacity: .8; }

.about-intro { max-width: 880px; display: flex; flex-direction: column; gap: var(--sp-5); margin-top: var(--sp-3); } /* T2: wider measure, air for the reading */
.about-intro strong { color: var(--ink); font-weight: 650; } /* AB2: key claims step out of the muted voice */
.about-intro p { font-size: 15.5px; line-height: 1.7; color: var(--muted); text-wrap: pretty; }

/* ==========================================================================
   About / founders
   ========================================================================== */
.founder {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 40px;
  padding: 40px 0;
  border-top: 1px solid var(--line);
}
.founder__portrait {
  width: 100%;
  height: auto;
  border: 1.5px solid var(--ink);
  filter: grayscale(1) contrast(1.05);
}
.founder__bio h3 {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.4vw, 26px);
  font-weight: 600;
  margin: 0 0 16px;
  text-wrap: balance;
}
.founder__title { font-size: 14px; font-weight: 500; color: var(--maroon); }
.founder__bio p { font-size: 14.5px; line-height: 1.7; color: var(--muted); margin: 0 0 var(--sp-5); text-wrap: pretty; }
.founder__bio p:last-child { margin-bottom: 0; }

.founder__instrument-icon {
  width: 22px;
  height: 22px;
  float: left;
  margin: 1px 10px 4px 0;
  color: var(--maroon);
}

/* Luxe round row 33: the founders' words speak from the deck's own oxblood,
   in cream serif with a gold signature — the reference sheet's creme<->red
   rhythm, contained as a printed plate rather than a full-bleed band. */
.founder-quote {
  margin: 48px 0 0;
  padding: 48px clamp(28px, 6vw, 72px);
  background: #4E1913;
  border: 1px solid #6d3325;
}
.founder-quote p {
  font-family: Georgia, 'Times New Roman', serif;
  font-style: italic;
  font-size: clamp(20px, 2.7vw, 27px);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: .005em;
  max-width: 780px;
  text-wrap: balance;
  color: #F5EAE0;
}
.founder-quote footer {
  margin-top: 18px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: #C99A56;
}
.founder-quote footer::before { content: '\2726\00a0\00a0'; }

@media (max-width: 720px) {
  .founder { grid-template-columns: 1fr; }
  .founder__portrait { max-width: 220px; }
}

/* --- Credential plate-cells (PAIRINGS.md row 5) --------------------------
   Proof lands AT the claim, never bunched into a credibility wall: a small
   bordered plate-cell that sits beside (or wraps under) the sentence making the
   claim. Type only, sharp corners, hairline border. No motion of its own. */
.credentials {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 14px;
  padding: 0;
  list-style: none;
}
.credential {
  border: 1px solid var(--line);
  border-top: 3px solid var(--maroon);
  padding: 10px 14px 12px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  background: var(--card);
}
.credential__label {
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}
.credential__value {
  /* Client call 2026-09-09 (AB5): the plates' figures join the hero's number
     voice — body face, engraved gold. The display face's notched zero
     ("12Ø+") read wrong here; ONE number typography across the site. */
  font-family: var(--font-body);
  font-size: 20px;
  font-weight: 650;
  color: #93641D;
  text-shadow: 0 -1px 1px rgba(23, 20, 18, .28), 0 1px 0 rgba(255, 255, 255, .8);
  line-height: 1.15;
}

/* --- Craft plate-cells (Home §"Our Crafts", condensed) -------------------
   Lighter, static cousin of .element-card / the Services 3D periodic table:
   same bordered-cell language and craft accent colors, but flat — no
   perspective/rotation/hover-lift, no symbol/icon glyph. Was a bare
   .included-list <ul>, whose bullet dot relies on --accent, a custom
   property only ever defined by .element-card--xx / .discipline-card--xx;
   used bare here --accent was unset, so every bullet computed to a
   transparent/invisible marker (the reported layout bug). */
.craft-cells {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.craft-cell {
  --accent: var(--maroon);
  background: var(--card);
  padding: 22px 22px 24px;
  display: flex;
  flex-direction: column;
}
.craft-cell--br { --accent: var(--craft-identity); }
.craft-cell--fo { --accent: var(--craft-formulation); }
.craft-cell--mk { --accent: var(--craft-marketing); }
.craft-cell--au { --accent: var(--craft-audit); }
.craft-cell__num {
  font-family: var(--font-display);
  font-size: 12px;
  color: var(--accent);
  margin-bottom: 10px;
}
.craft-cell__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 16px;
  line-height: 1.3;
  margin-bottom: 10px;
  border-top: 2px solid var(--accent);
  padding-top: 10px;
}
.craft-cell__desc { font-size: 14px; line-height: 1.6; color: var(--muted); text-wrap: pretty; }

@media (max-width: 640px) {
  .craft-cells { grid-template-columns: 1fr; }
}

/* Spacing utility for the Core Crafts CTA button */
.crafts-cta { margin-top: clamp(32px, 6vw, 48px); }

/* --- Roster plate-strip (PAIRINGS.md row 10) -----------------------------
   Client / "featured in" names set as TYPE, not logos — no raster marks
   (§5/§8), no marquee, no animation at all. Split and placed at the claim it
   backs rather than collected into one wall. */
.roster {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 16px 0;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
}
.roster__label {
  flex: 0 0 100%;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}
.roster li {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink);
}

/* --- The emphasised pillar (PAIRINGS.md row 9) ---------------------------
   The hinge of the document raises its voice TYPOGRAPHICALLY — maroon rule and
   numeral on the middle pillar — never with a new animation, tint fill or
   gradient. */
.pillar--feature { border-top-color: var(--maroon); }
.pillar--feature .pillar__num { color: var(--maroon); font-weight: 700; }

/* About: The interrupted experiment. CONCEPT current direction, PAIRINGS 24–25.
   One engraving, semantic anchor map and a persistent marginal reading. */
.lexicon-section { background: var(--paper); }
.lexicon-section__head { max-width: none; margin-bottom: 40px; }
.lexicon-section__head .section-lead { max-width: 740px; }
.lexicon-plate { border-top: 1px solid var(--ink); scroll-margin-top: 100px; }
.lexicon-plate [hidden] { display: none !important; }
.lexicon-plate .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
.lexicon-plate__folio,
.lexicon-plate__reader-top {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-family: var(--font-display);
  font-size: 10px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--muted);
}
.lexicon-plate__folio { padding: 17px 0; border-bottom: 1px solid var(--line); }
.lexicon-plate__layout { padding-top: 24px; }
.lexicon-plate.is-enhanced .lexicon-plate__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 310px;
  gap: 28px;
  align-items: start;
}
.lexicon-plate__art { min-width: 0; }
.lexicon-plate__map { position: relative; isolation: isolate; --focus-x: 50%; --focus-y: 46%; }
.lexicon-plate__image { display: block; width: 100%; height: auto; mix-blend-mode: multiply; }
.lexicon-plate__hotspot {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  min-width: 44px; min-height: 44px;
  scroll-margin-top: 100px;
  z-index: 3;
  color: var(--ink);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.lexicon-plate__marker {
  display: grid;
  place-items: center;
  position: absolute;
  left: 0; top: 0;
  width: 27px; height: 27px;
  background: var(--paper);
  border: 1px solid var(--muted);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .02em;
  transition: background 180ms, color 180ms;
}
.lexicon-plate__hotspot.is-active .lexicon-plate__marker,
.lexicon-plate__hotspot:hover .lexicon-plate__marker,
.lexicon-plate__hotspot:focus-visible .lexicon-plate__marker {
  background: var(--maroon); border-color: var(--maroon); color: var(--paper);
}
.lexicon-plate__hotspot:focus-visible { outline: 2px solid var(--maroon); outline-offset: 3px; }
.lexicon-plate__label {
  position: absolute;
  left: 33px; top: 0;
  padding: 5px 8px;
  width: max-content;
  max-width: 185px;
  font-family: var(--font-display);
  font-size: 11px;
  line-height: 1.45;
  background: var(--paper);
  color: var(--maroon);
  opacity: 0;
  pointer-events: none;
  transform: translateY(3px);
  transition: opacity 180ms, transform 180ms;
}
.lexicon-plate__hotspot:nth-of-type(5) .lexicon-plate__label,
.lexicon-plate__hotspot:nth-of-type(6) .lexicon-plate__label,
.lexicon-plate__hotspot:nth-of-type(8) .lexicon-plate__label { left: auto; right: calc(100% - 27px); top: -31px; }
.lexicon-plate__hotspot:hover .lexicon-plate__label,
.lexicon-plate__hotspot:focus-visible .lexicon-plate__label,
.lexicon-plate__hotspot.is-active .lexicon-plate__label { opacity: 1; transform: none; }
.lexicon-plate__focus-frame {
  display: none;
  position: absolute;
  width: 19%; height: 26%;
  left: var(--focus-x); top: var(--focus-y);
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 2;
  color: var(--maroon);
  /* No transition: the animated --focus-x/--focus-y vars carry the motion for
     frame and spotlight together (a `transition: left/top` here used to be
     overridden by a later `transition: none` — folded, BACKLOG 1.3). */
}
.is-enhanced .lexicon-plate__focus-frame { display: block; }
.lexicon-plate__focus-frame::before,
.lexicon-plate__focus-frame::after { content: ''; position: absolute; width: 15px; height: 15px; }
.lexicon-plate__focus-frame::before { top: 0; left: 0; border-top: 1px solid; border-left: 1px solid; }
.lexicon-plate__focus-frame::after { bottom: 0; right: 0; border-bottom: 1px solid; border-right: 1px solid; }
.lexicon-plate__caption { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 18px 0; }
.lexicon-plate__caption p { margin: 0; font-family: Georgia, serif; font-size: 21px; font-style: italic; color: var(--ink-soft); }
.lexicon-plate button { font: inherit; cursor: pointer; border-radius: 0; }
.lexicon-plate__magnify {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px;
  padding: 8px 0 8px 8px; border: 0; background: transparent;
  font-size: 11px !important; color: var(--muted);
}
.lexicon-plate__magnify svg { width: 18px; height: 18px; }
.lexicon-plate__magnify[aria-pressed="true"] { color: var(--maroon); }
.lexicon-plate__loupe {
  position: absolute; width: 180px; height: 180px;
  overflow: hidden; border-radius: 50%; border: 1px solid var(--ink);
  outline: 4px solid var(--paper); background: var(--paper);
  z-index: 5; pointer-events: none;
}
.lexicon-plate__loupe-image { position: absolute; top: 0; left: 0; max-width: none; height: auto; transform-origin: 0 0; }
.lexicon-plate__reader { min-width: 0; border-left: 1px solid var(--line); padding-left: 28px; }
.lexicon-plate__reader-top { padding: 0 0 17px; }
.lexicon-plate__detail {
  height: 190px; position: relative; overflow: hidden;
  background: var(--paper-alt); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.lexicon-plate__detail-image { position: absolute; left: 0; top: 0; max-width: none; height: auto; transform-origin: 0 0; }
.lexicon-plate__detail > span {
  position: absolute; bottom: 8px; right: 8px; padding: 3px 6px;
  background: var(--paper); font-size: 9px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
}
.lexicon-plate__reading { padding-top: 22px; }
.lexicon-plate__index { color: var(--maroon); font-family: var(--font-display); font-size: 12px; }
#lexicon-reading-term { font-family: var(--font-display); font-size: 26px; font-weight: 500; line-height: 1.16; letter-spacing: -.035em; margin: 9px 0 17px; }
#lexicon-reading-definition { color: var(--ink-soft); font-size: 14px; line-height: 1.8; }
.lexicon-plate__navigation { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 24px; padding-top: 12px; border-top: 1px solid var(--line); }
.lexicon-plate__navigation button { display: grid; place-items: center; width: 44px; height: 44px; flex: 0 0 44px; background: transparent; border: 1px solid var(--line); color: var(--ink); }
.lexicon-plate__navigation button:hover { border-color: var(--maroon); color: var(--maroon); }
.lexicon-plate__navigation svg { width: 20px; height: 20px; }
.lexicon-plate__navigation a { font-size: 10px; color: var(--muted); text-underline-offset: 3px; }
.lexicon-plate__mobile-picker { display: none; }
.lexicon-plate__all { margin-top: 30px; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--line); scroll-margin-top: 100px; }
.lexicon-plate__all summary { list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 20px; padding: 23px 0; cursor: pointer; font-family: var(--font-display); font-size: 15px; }
.lexicon-plate__all summary::-webkit-details-marker { display: none; }
.lexicon-plate__all-count { display: flex; align-items: center; gap: 25px; color: var(--muted); font-size: 11px; }
.lexicon-plate__all-count > span { color: var(--maroon); font-size: 22px; font-weight: 400; }
.lexicon-plate__all[open] .lexicon-plate__all-count > span { transform: rotate(45deg); }
.lexicon-list { margin: 0; max-width: none; }
.lexicon-entry { padding: 24px 0; border-top: 1px solid var(--line); }
.lexicon-entry__term { font-family: var(--font-display); font-size: 19px; font-weight: 500; color: var(--ink); scroll-margin-top: 100px; }
.lexicon-entry__num { display: inline-block; margin-right: 16px; font-size: 12px; font-weight: 400; color: var(--maroon); }
.lexicon-entry__def { margin: 12px 0 0; padding-left: 34px; max-width: 800px; color: var(--ink-soft); font-size: 15px; line-height: 1.8; }
.lexicon-plate:not(.is-enhanced) .lexicon-plate__focus-frame { display: none; }
.lexicon-plate.is-image-unavailable .lexicon-plate__map { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 20px; }
.lexicon-plate.is-image-unavailable .lexicon-plate__map picture { display: none; }
.lexicon-plate.is-image-unavailable .lexicon-plate__hotspot { position: static; width: auto; height: auto; min-width: 0; min-height: 64px; display: flex; align-items: center; gap: 12px; border-bottom: 1px solid var(--line); }
.lexicon-plate.is-image-unavailable .lexicon-plate__marker { position: static; flex: 0 0 27px; }
.lexicon-plate.is-image-unavailable .lexicon-plate__label { display: block; position: static; opacity: 1; transform: none; padding: 0; width: auto; max-width: none; background: transparent; }
.lexicon-plate.is-image-unavailable .lexicon-plate__detail,
.lexicon-plate.is-image-unavailable .lexicon-plate__focus-frame { display: none; }
@media (min-width: 1000px) {
  .lexicon-plate__all[open] .lexicon-list { display: grid; grid-template-columns: 1fr 1fr; gap: 0 40px; }
}
@media (max-width: 1100px) and (min-width: 801px) {
  .lexicon-plate.is-enhanced .lexicon-plate__layout { grid-template-columns: minmax(0, 1fr) 270px; gap: 20px; }
  .lexicon-plate__reader { padding-left: 20px; }
  .lexicon-plate__magnify { font-size: 10px !important; }
  .lexicon-plate__caption p { font-size: 18px; }
}
@media (max-width: 800px) {
  .lexicon-plate.is-enhanced .lexicon-plate__layout { display: block; }
  .lexicon-plate__reader { border-left: 0; border-top: 1px solid var(--line); padding: 20px 0 0; }
  .lexicon-plate__reader-top { padding-bottom: 18px; }
  .lexicon-plate__detail { display: none; }
  .lexicon-plate__reading { padding-top: 20px; }
  #lexicon-reading-term { max-width: 500px; }
  #lexicon-reading-definition { font-size: 16px; line-height: 1.8; max-width: 620px; }
  .lexicon-plate__mobile-picker { display: grid; gap: 8px; font-family: var(--font-display); font-size: 11px; color: var(--muted); }
  .lexicon-plate__select { width: 100%; min-height: 48px; padding: 10px 32px 10px 12px; border: 1px solid var(--line); border-radius: 0; background: var(--paper); font: 15px var(--font-display); color: var(--ink); }
  .lexicon-plate__navigation { max-width: 620px; }
  .lexicon-plate__navigation a { font-size: 12px; }
  .lexicon-plate__label { display: none; }
  .lexicon-plate__marker { width: 24px; height: 24px; font-size: 9px; }
  .lexicon-plate__all summary { font-size: 14px; }
  .lexicon-plate__all-count { gap: 16px; font-size: 10px; }
}
@media (max-width: 480px) {
  .lexicon-section__head { margin-bottom: 28px; }
  .lexicon-plate__folio { font-size: 9px; }
  .lexicon-plate__caption { padding: 17px 0; }
  .lexicon-plate__caption p { font-size: 18px; }
  .lexicon-plate__all-count { font-size: 0; }
  .lexicon-entry__term { font-size: 18px; gap: 12px; }
  .lexicon-entry__def { padding-left: 0; }
  .lexicon-plate.is-image-unavailable .lexicon-plate__map { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .lexicon-plate *, .lexicon-plate *::before, .lexicon-plate *::after { transition: none !important; animation: none !important; }
  .lexicon-plate__loupe, .lexicon-plate__magnify { display: none !important; }
}
@media print {
  .lexicon-plate__all::details-content { content-visibility: visible; }
  .lexicon-plate__reader, .lexicon-plate__loupe, .lexicon-plate__magnify { display: none !important; }
}

/* ==========================================================================
   Contact
   ========================================================================== */
/* ==========================================================================
   FAQ (native <details> accordions)
   ========================================================================== */
.faq-list {
  max-width: 820px;
  border-top: 1px solid var(--line);
}
.faq-item {
  position: relative;
  border-bottom: 1px solid var(--line);
}
.faq-item summary {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 22px 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item__num {
  font-size: 12px;
  color: var(--maroon);
  flex: 0 0 auto;
  padding-top: 3px;
}
.faq-item__q {
  flex: 1 1 auto;
  font-size: clamp(17px, 2vw, 20px);
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--ink);
  text-wrap: balance;
}
.faq-item__mark {
  position: relative;
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  align-self: center;
}
.faq-item__mark::before,
.faq-item__mark::after {
  content: "";
  position: absolute;
  background: var(--maroon);
  transition: transform .25s var(--ease), opacity .25s var(--ease);
}
.faq-item__mark::before { top: 7px; left: 0; width: 16px; height: 2px; }        /* horizontal */
.faq-item__mark::after  { top: 0; left: 7px; width: 2px; height: 16px; }         /* vertical */
.faq-item[open] .faq-item__mark::after { transform: scaleY(0); opacity: 0; }     /* − when open */
.faq-item > .faq-item__a {
  display: block; /* override UA `details:not([open]) > *:not(summary){display:none}` so JS can animate height */
  /* Normal document flow (physical accordion): the height animation pushes
     the rows below it down and makes room, it never floats over them. */
  /* Luxe pass (operator 2026-09-07): transparent so the sheet's texture
     runs through the open answer — the opaque paper-alt slab broke it. */
  background: transparent;
  padding: 0 0 0 44px;
  max-width: 62ch;
  color: var(--muted);
  font-size: 15.5px;
  text-wrap: pretty;
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height .3s var(--ease), opacity .2s var(--ease), padding-bottom .3s var(--ease);
}
.faq-item[open] > .faq-item__a {
  padding-bottom: 24px;
  opacity: 1;
  /* max-height is set inline (px) by js/main.js to the measured content height */
}
@media (max-width: 720px) {
  .faq-item__a { padding-left: 0; }
}

/* What-happens-next steps in the contact block */
.contact__next {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 28px;
  padding-top: 24px;
  border-top: 1px solid rgba(250, 247, 242, .18);
}
.contact__next li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  font-size: 15px;
  color: #E6DCD3;
}
.contact__next-num {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid #E8B7A8;
  color: #E8B7A8;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
}

/* The closing movement earns a full step more than an ordinary section. */
.contact { background: var(--maroon-dark); color: var(--paper); padding: var(--sp-8) 0; }
.contact__inner {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: var(--sp-7);
  /* Client pass 13: stretch (the default) instead of start — the intro
     column fills the row (whose height the taller form sets), and its
     flex layout below can then pin the coordinates to its foot so both
     columns END at the same level. */
}
/* The intro is a flex column so margin-top:auto on the coordinates pushes
   them to the column's foot — level with the form's bottom edge. */
.contact__intro { display: flex; flex-direction: column; align-items: flex-start; }
/* Grid items may not shrink below their content's intrinsic width by default;
   the select's longest option was forcing the whole page wider than a phone
   viewport (412px at 390px). Let every column and control shrink and truncate. */
.contact__inner > * { min-width: 0; }
.field input, .field textarea, .field select { width: 100%; min-width: 0; }
.contact__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(30px, 4vw, 44px);
  line-height: 1.15;
  color: var(--paper);
  margin-bottom: 18px;
  text-wrap: balance;
}
/* Client call 2026-09-09 (CT1/CT2/CT4) — the contact intro's furnishings */
.contact__iconic {
  display: inline-block;
  width: auto;
  height: 44px;
  vertical-align: -12px;
  margin-left: 6px;
}
/* Client pass 10: the two lead paragraphs above the proverb were flush
   against each other (all <p> reset to margin:0 site-wide) — give the
   second one room to breathe. */
.contact__intro .section-lead + .section-lead { margin-top: var(--sp-5); }
.contact__quote {
  margin: 26px 0;
  padding: 4px 0 4px 22px;
  border-left: 3px solid #C9A45C;
}
.contact__quote p {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 19px;
  line-height: 1.5;
  color: #DDB877;
  margin: 0;
  text-wrap: pretty;
}
.contact__quote footer { margin-top: 8px; font-size: 13px; color: #C9AD97; }
.contact__social { display: flex; gap: 16px; margin-top: 30px; align-items: center; }
.contact__social a { display: block; transition: filter var(--slow), transform var(--slow); }
.contact__social a:hover { filter: brightness(1.18); transform: translateY(-1px); }
/* Client pass 13: the icons are inline <svg> (pass 5 reverted the engraved
   <img> marks back to line SVGs) but this rule still targeted img — with no
   width of their own the SVGs collapsed to ~16px and the row was invisible
   in practice. Size the SVGs; keep img for safety. */
.contact__social img, .contact__social svg { width: 26px; height: 26px; display: block; }
.contact__social a { color: #C9AD97; }
.contact__social a:hover { color: #DDB877; }

/* CT5 #1 v2 (client pass 5): the pigeon and the telegraph key are ENGRAVED
   INTO the oxblood ground — barely-lifted tone, part of the decor, found by
   the eye that lingers (the pin-globe is dropped). Positioned in the calm
   zones: the pigeon flies high between the columns, the key sits low-left
   under the coordinates. */
.contact { position: relative; isolation: isolate; overflow: hidden; }
.contact::before,
.contact__inner::after {
  content: "";
  position: absolute;
  z-index: -1;
  background: #E4D2C2;
  opacity: .10; /* client pass 8: the middle way — .07 was invisible, .13 pulled the eye */
  pointer-events: none;
}
.contact::before {
  bottom: 300px;
  left: 24%;
  width: 300px;
  height: 258px;
  -webkit-mask: url("../img/engravings/pigeon-post-v1.webp") no-repeat center / contain;
  mask: url("../img/engravings/pigeon-post-v1.webp") no-repeat center / contain;
}
/* Client call 2026-09-11: the telegraph key moves from the section's own
   bottom corner (where it floated in dead space, tied to nothing) to the FORM's
   bottom-left corner, half-tucked UNDER the paper card - « c'est pas grave si
   ca passe un peu en dessous ».

   It rides the GRID, not a magic percentage: the pseudo-element is placed as a
   grid item in the form's own cell (column 2, row 1) and pinned to that cell's
   bottom-left corner, so it tracks the card at every viewport with no numbers
   to re-tune. Negative margins push it out past the corner; z-index:-1 puts it
   behind the card's opaque paper fill, so the overlap reads as the engraving
   sliding underneath rather than a stain on the form. The 75px spill stays
   inside .contact's --sp-8 bottom padding, so its overflow never clips it.
   (.contact__form's own ::before/::after are taken - they draw the card's
   corner stitches, row 3765.) */
.contact__inner { position: relative; }
.contact__inner::after {
  grid-column: 2;
  grid-row: 1;
  align-self: end;
  justify-self: start;
  width: 380px;
  height: 130px;
  margin: 0 0 -75px -172px;
  -webkit-mask: url("../img/engravings/telegraph-hand-v1.webp") no-repeat center / contain;
  mask: url("../img/engravings/telegraph-hand-v1.webp") no-repeat center / contain;
}
/* Single column: the card is full-width and the form is row 2, so the key
   tucks under the card's foot instead of beside it. */
@media (max-width: 900px) {
  .contact__inner::after {
    grid-column: 1;
    grid-row: 2;
    width: 300px;
    height: 104px;
    margin: 0 0 -58px -22px;
  }
}
.contact__coordinates { display: flex; flex-direction: column; gap: 12px; margin-top: auto; padding-top: 28px; color: #E4D2C2; }
.contact__coordinates p { margin: 0; }
.contact__coordinates a:hover { color: #DDB877; }
.contact__signoff { font-family: var(--font-display); font-weight: 600; color: #DDB877; }
.contact__details { display: flex; flex-direction: column; gap: 6px; margin-top: 32px; }
.contact__details a {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 4px;
  width: fit-content;
}

.contact__form {
  background: var(--paper);
  color: var(--ink);
  padding: 32px;
  display: grid;
  gap: 18px;
}
.field { display: grid; gap: 6px; }
.field label { font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.field input, .field textarea {
  border: 1.5px solid var(--line);
  background: var(--card);
  padding: 11px 13px;
  color: var(--ink);
  resize: vertical;
}
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--maroon);
  box-shadow: 0 0 0 3px rgba(122, 36, 24, .15);
}

.field select {
  border: 1.5px solid var(--line);
  background-color: var(--card);
  padding: 11px 13px;
  padding-right: 36px;
  color: var(--ink);
  font: inherit;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1 L5 5 L9 1' stroke='%23171412' fill='none' stroke-width='1.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 12px 8px;
  cursor: pointer;
}

.field select:focus {
  outline: none;
  border-color: var(--maroon);
  box-shadow: 0 0 0 3px rgba(122, 36, 24, .15);
}

/* ==========================================================================
   Footer
   ========================================================================== */
/* Luxe round rows 33+35: the footer deepens from charcoal to the deck's own
   oxblood, crowned by a double gold rule — the reference's ground + ink. */
.site-footer {
  background: #421510;
  color: var(--paper);
  padding-top: 56px;
  border-top: 4px double #B67E46;
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
/* F2 v5 (client pass 5): the footer salamander is WITHDRAWN for now — alone
   at the right edge she pulled the eye instead of hiding in the decor. The
   emblem (img/salamander-seal.svg) keeps its two quieter posts: the Home
   cul-de-lampe and the 404. */
.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-bottom: 40px;
  border-bottom: 1px solid rgba(250, 247, 242, .16);
}
.footer-nav { display: flex; flex-wrap: wrap; gap: 24px; }
.footer-nav a { font-size: 14px; color: #D9CFC6; transition: color .2s var(--ease); }
.footer-nav a:hover { color: var(--paper); }

.footer-contact { display: flex; flex-wrap: wrap; gap: 4px 20px; font-size: 14px; color: #D9CFC6; }
.footer-contact a { color: #D9CFC6; transition: color .2s var(--ease); }
.footer-contact a:hover { color: var(--paper); }

.footer-social { display: flex; align-items: center; gap: 16px; }
.footer-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid rgba(250, 247, 242, .24);
  color: #D9CFC6;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.footer-social a:hover, .footer-social a:focus-visible { color: var(--paper); border-color: rgba(250, 247, 242, .55); }
.footer-social svg { width: 18px; height: 18px; }

.site-footer__tagline { font-size: 15px; color: var(--paper); font-weight: 500; }

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px;
  padding: 20px 24px 26px; /* the copy strip below closes the footer */
  font-size: 12.5px;
  color: #8C8477;
}
/* Client pass 6: the DOUBLE FOOTER, done properly — the copyright + legal
   thread is now a DIRECT child of the footer (no 100vw margin tricks, which
   left it 24px off to the right inside the padded flex row): a true second
   bar, full width by construction, one centred line, a touch lighter, a gold
   hairline separating it from the footer above. The very last thing on the
   page, on every page. */
.site-footer__copy {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0;
  padding: 13px 24px;
  background: #4E1B14;
  border-top: 1px solid rgba(201, 164, 92, .22);
  font-size: 12.5px;
  color: #C9AD97;
}

/* Contact closing CTA headline: reuses the hero's .accent-letter--xx device
   (line ~398) on "Formula" -- a few letters colored with the site's craft
   accent tokens, no tile/box/atomic-number styling. The section sits on the
   dark .contact background, where the full-strength craft tones fail contrast,
   so swap in their existing light "-tint" tokens here instead of new colors. */
.contact .accent-letter--fo { color: var(--craft-formulation-tint); }
.contact .accent-letter--mk { color: var(--craft-marketing-tint); }

/* Services closing CTA: plain centered standard button, no element/periodic-table motif. */
/* Client call 2026-09-11: the closing lockup on Services. The button used to
   be a section of its own containing nothing else; it is now the foot of the
   closing statement, with the reassurance line under it so the ask has a
   reason attached. Left-anchored like the kicker/title/lead above it, so the
   whole close reads as one column rather than a centred afterthought.
   --sp-7 above (block to block), --sp-5 between button and note (a line that
   belongs to the button, not a new thought). */
.services-close {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-5);
  margin-top: var(--sp-7);
}
.services-close__note {
  font-size: 14px;
  color: #C9AD97; /* the oxblood ground's readable cream, not --muted (which
                     is an ink-on-paper value and vanished here) */
  max-width: 52ch;
  text-wrap: pretty;
}


/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 900px) {
  .elements-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pillars { grid-template-columns: 1fr; gap: var(--sp-6); }
  .contact__inner { grid-template-columns: 1fr; gap: var(--sp-7); }
}

@media (max-width: 720px) {
  .main-nav {
    position: fixed;
    inset: 76px 0 0 0;
    background: var(--paper);
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: 12px 24px 24px;
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s var(--ease), transform .25s var(--ease);
  }
  .main-nav.is-open { opacity: 1; transform: none; pointer-events: auto; }
  /* Row 47 v2 (operator): the transparent-menu bug. The scrolled header's
     backdrop-filter makes the fixed header the CONTAINING BLOCK for the
     fixed flyout (inset resolves against the header's own 76px box → the
     flyout collapses to zero height and its paper ground vanishes). While
     the menu is open the header drops the blur — nothing to blur behind an
     opaque flyout anyway — and takes a near-solid scrolled ground. This
     rule must stay AFTER .site-header.is-scrolled in the file so its
     backdrop-filter: none wins when both classes sit on the header. */
  .site-header.has-menu {
    background: rgba(250, 247, 242, .97);
    backdrop-filter: none;
    border-bottom-color: var(--line);
  }
  body.dark-hero .site-header.has-menu .brand-word__top { color: var(--muted); }
  body.dark-hero .site-header.has-menu .brand-word__bottom { color: var(--ink); }
  body.dark-hero .site-header.has-menu .brand-mark { border-color: var(--ink); background: transparent; }
  body.dark-hero .site-header.has-menu .brand-mark__sym,
  body.dark-hero .site-header.has-menu .brand-mark__num { color: var(--ink); }
  body.dark-hero .site-header.has-menu .nav-toggle span { background: var(--ink); }
  .main-nav a { width: 100%; padding: 16px 0; border-bottom: 1px solid var(--line); }
  .main-nav__cta { border: 1.5px solid var(--ink); text-align: center; margin-top: 12px; }
  .nav-toggle { display: flex; }

  /* Dark header pages (e.g. contact.html): when mobile menu opens, revert text
     to dark for legibility on the light flyout background */
  body.dark-hero .main-nav.is-open a { color: var(--ink-soft); }
  body.dark-hero .main-nav.is-open a:hover { color: var(--maroon); }
  body.dark-hero .main-nav.is-open .main-nav__cta {
    border-color: var(--ink);
    color: var(--ink) !important;
  }
  body.dark-hero .main-nav.is-open .main-nav__cta:not(.btn-react):hover { background: var(--ink); color: var(--paper) !important; }

  /* Hero critique R5 (2026-09-09): tighten the mobile rhythm so the compact
     proof line (.hero__proof-mobile) actually clears the fold instead of
     landing 100+px below it — the point of adding it. Nothing here changes
     what any element says, only the air around it. */
  .hero { padding: 96px 0 64px; }
  .eyebrow { margin-bottom: 14px; }
  .hero__title { margin-bottom: 14px; }
  .hero__baseline { padding-bottom: 8px; margin-bottom: 12px; }
  .hero__lead { margin-bottom: 22px; }
  .hero__actions { margin-bottom: 12px; }
  .cta-note { margin-bottom: 16px; } /* desktop's 56px was the last big gap keeping the proof line off-screen */
  .elements-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Mobile sticky "Book a call" CTA
   Desktop already exposes the header CTA; on small screens it hides behind
   the hamburger, so this persistent bottom bar covers that gap. JS toggles
   `.is-visible` once the hero is scrolled past and hides it again while the
   contact section is in view so it never sits over the form.
   ========================================================================== */
.mobile-cta { display: none; }

@media (max-width: 720px) {
  .mobile-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 90;
    padding: 14px 24px;
    background: var(--maroon);
    color: var(--paper);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 15px;
    letter-spacing: .01em;
    border-top: 1.5px solid var(--maroon-dark);
    opacity: 0;
    transform: translateY(100%);
    pointer-events: none;
    transition: opacity .25s var(--ease), transform .25s var(--ease);
  }
  /* .btn-react (~L4575, shared "reaction" glow effect on every CTA on the
     site, same 0,1,0 specificity as .mobile-cta above) sets its own
     position: relative and comes later in the file, so it was winning the
     cascade and un-fixing this element. That put a ~53px-tall link into
     normal flow at the very end of <body> — on every page short enough for
     it to land below the footer, it read as a band of dead white space
     under the footer instead of the page actually ending there. The id
     selector's specificity beats a class regardless of source order, so
     this can't regress the same way again. */
  #mobile-cta { position: fixed; }
  .mobile-cta.is-visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
  .mobile-cta:hover,
  .mobile-cta:focus-visible {
    background: var(--maroon-dark);
  }
}

/* ==========================================================================
   The Elemental Table — hover-driven periodic grid + detail panel (no scroll)
   Hover/focus an element: it tilts into CSS 3D (extruded), its colour glows,
   the others dim, and a white detail panel unfurls FROM THAT ELEMENT'S
   BOTTOM-RIGHT CORNER — spanning the full height of the grid and growing
   rightward over whatever cells sit in its path — with number, name,
   description and bonds. js/main.js sets `left`/`top`/`bottom` and the
   `--origin-y` reveal-origin custom property per active element.
   No JS -> a plain, readable grid.
   ========================================================================== */
.ptable-section { background: var(--paper); }
.ptable {
  --cell: clamp(168px, 21vw, 228px);
  --gap: 6px;
  --depth: 16px;
  position: relative;
  margin-top: 12px;
  min-height: calc(var(--cell) * 2 + var(--gap));
}

/* --- bond-line overlay: hairline connectors between the active element and
   its data-bonds, drawn/positioned by js/main.js. Never intercepts input. --- */
.ptable__bonds {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 2;
  overflow: visible;
}
.ptable__bonds line {
  stroke-width: 1;
  fill: none;
  opacity: 0;
  transition: opacity .18s var(--ease);
}
.ptable__bonds line.is-visible { opacity: .55; }
@media (prefers-reduced-motion: reduce) {
  .ptable__bonds line { transition: none; }
}

/* --- the grid of element tiles: 4 - 2 - 1 (operator, coherence pass
   2026-09-06 — supersedes the earlier 4+3): row one is the four Core
   Elements, row two the two Specialized Programs and, across the gap,
   the house's own 7th element closing the table edge. Family captions
   are grid children with a shared hairline, so the three groups read as
   one table with named families, not three lists. --- */
.ptable__grid {
  display: grid;
  grid-template-columns: repeat(4, var(--cell));
  gap: var(--gap);
  row-gap: 10px;
  width: max-content;
}
.el--wk { grid-row: 3; grid-column: 1; }
.el--ex { grid-row: 3; grid-column: 2; }
.el--al { grid-row: 3; grid-column: 4; }
.ptable__family {
  border-top: 1px solid var(--line);
  padding-top: 7px;
  margin-bottom: 14px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 10.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--muted);
}
.ptable__family--core { grid-row: 2; grid-column: 1 / -1; }
.ptable__family--programs { grid-row: 4; grid-column: 1 / 3; }
.ptable__family--house { grid-row: 4; grid-column: 4; }

/* Craft accents for the six tiles — one modifier per real Craft (CONCEPT.md §5),
   so the tile hue lives in the stylesheet rather than in a per-tile inline style. */
.el--br { --accent: var(--craft-identity);    --tint: var(--craft-identity-tint); }
.el--fo { --accent: var(--craft-formulation); --tint: var(--craft-formulation-tint); }
.el--mk { --accent: var(--craft-marketing);   --tint: var(--craft-marketing-tint); }
.el--au { --accent: var(--craft-audit);       --tint: var(--craft-audit-tint); }
.el--wk { --accent: var(--craft-workshops);   --tint: var(--craft-workshops-tint); }
.el--ex { --accent: var(--craft-expansion);   --tint: var(--craft-expansion-tint); }

.el {
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  width: var(--cell);
  height: var(--cell);
  position: relative;
  perspective: 1000px;           /* own stacking context; grid stays context-free */
  cursor: pointer;
  transition: opacity .35s var(--ease);
}
.el__box {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  /* proximity "excitation": distance-scaled tilt/rise/scale, written as
     --ex/--rx/--ry/--rise/--sc/--dz by js/main.js, batched per pointermove.
     --dz is the idle depth term (subtle translateZ), fading out as --ex
     rises so it never fights the pointer tilt. */
  transform: translateY(calc(var(--rise, 0px) * -1)) scale(var(--sc, 1)) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateZ(var(--dz, 0px));
  transition: transform .5s var(--ease);
  will-change: transform;
}
.el:not(.is-active) .el__box { transition: transform .16s var(--ease); }
/* While the js/main.js rAF loop is live it writes --rx/--ry/--rise/--sc every
   frame and does its own easing (sine idle + a critically-damped lerp toward
   the pointer target), so the CSS transition would only smear it. */
.ptable.is-live .el:not(.is-active) .el__box { transition: none; }
.el__face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: 15px 15px 14px;
  background: var(--card);
  /* Row 37 (operator): a real periodic-table cell wall — 2px, in the cell's
     own accent at low alpha so each element's family colour frames it. */
  border: 2px solid color-mix(in srgb, var(--accent) 55%, var(--line));
  transform: translateZ(calc(var(--depth) / 2));
  transition: background .35s var(--ease), border-color .35s var(--ease);
  overflow: hidden; /* clips the A5 glint band below */
}
/* Client call 2026-09-09 (A5): the press-strike glint — entering a cell
   sweeps one band of champagne light across the engraved face, like a
   stamp catching the lamp. JS re-arms it per entry via .is-struck. */
.el__face::after {
  content: "";
  position: absolute;
  inset: -2px;
  background: linear-gradient(115deg, transparent 32%, rgba(233, 205, 140, .38) 50%, transparent 68%);
  transform: translateX(-135%);
  pointer-events: none;
}
@keyframes el-glint {
  from { transform: translateX(-135%); }
  to { transform: translateX(135%); }
}
.el.is-struck .el__face::after { animation: el-glint .75s var(--ease); }
/* A5: the chain reaction — the struck cell's bonded elements answer with a
   brief accent flush, staggered by JS like a reaction propagating. */
.el.is-bond-lit .el__face { border-color: var(--accent); }
.el.is-bond-lit .el__glow { opacity: .2; transition: opacity .22s var(--ease); }
/* solid-tone accent wash that brightens with proximity excitement — a flat
   colour layer whose opacity animates, not a gradient/glow (DESIGN.md §10). */
.el__glow {
  position: absolute;
  inset: 0;
  background: var(--accent);
  opacity: calc(var(--ex, 0) * .14);
  pointer-events: none;
}
.el__side { position: absolute; background: var(--accent); }
.el__side--right,
.el__side--left {
  top: 0; height: var(--cell); width: var(--depth);
  left: calc((var(--cell) - var(--depth)) / 2);
}
.el__side--right { transform: rotateY(90deg)  translateZ(calc(var(--cell) / 2)); filter: brightness(.82); }
.el__side--left  { transform: rotateY(-90deg) translateZ(calc(var(--cell) / 2)); filter: brightness(.82); }
.el__side--top,
.el__side--bottom {
  left: 0; width: var(--cell); height: var(--depth);
  top: calc((var(--cell) - var(--depth)) / 2);
}
.el__side--top    { transform: rotateX(90deg)  translateZ(calc(var(--cell) / 2)); filter: brightness(1.05); }
.el__side--bottom { transform: rotateX(-90deg) translateZ(calc(var(--cell) / 2)); filter: brightness(.68); }

.el__num { font-family: var(--font-display); font-weight: 600; font-size: 12px; color: var(--accent);   text-shadow: 0 -1px 0 rgba(23, 20, 18, .22), 0 1px 0 rgba(255, 255, 255, .7);
}
.el__icon { position: absolute; top: 15px; right: 15px; width: 20px; height: 20px; color: var(--accent); }
.el__sym {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(30px, 4vw, 44px);
  line-height: 1;
  color: var(--accent);
  /* Row 37: engraved lettering — dark bite above, paper lip below, the
     classic letterpress recess. */
  text-shadow: 0 -1px 1px rgba(23, 20, 18, .38), 0 1px 0 rgba(255, 255, 255, .85);
  margin-top: auto;
}
.el__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink);
  margin-top: 6px;
}

/* active pose: straight-on 3D pop + colour glow. Client call 2026-09-09 (A5):
   the lateral lean (rotateY -18 / rotateX 9) is RETIRED — the cell rises flat
   toward the reader; the fixed pop still composes with the live --rise/--sc
   the rAF loop keeps writing. */
.el.is-active { z-index: 3; }
.el.is-active .el__box {
  transform: translateZ(34px) translateY(calc(-8px - var(--rise, 0px) * .5)) scale(var(--sc, 1));
}
.el.is-active .el__face { background: var(--tint); border-color: var(--accent); }
/* dim the others so the active one gets natural focus */
.ptable.has-active .el:not(.is-active) { opacity: .32; }

.el:focus-visible { outline: none; }
.el:focus-visible .el__face { outline: 2px solid var(--maroon); outline-offset: 3px; }

/* Proximity excitation is opt-in from JS (js/main.js checks the same media
   features before it ever writes --ex/--rx/--ry/--rise/--sc), but this is a
   belt-and-braces CSS fallback so the tilt/hum/glow-by-distance can never
   render even if a media feature flips after load: reduced-motion and
   coarse/touch pointers keep the flat grid and the plain is-active pop only. */
@media (prefers-reduced-motion: reduce), (pointer: coarse) {
  .el__box { transform: none; animation: none; }
  .el.is-active .el__box { transform: translateZ(30px) translateY(-6px); }
  .el__glow { opacity: 0; }
  .el.is-struck .el__face::after { animation: none; }
}

/* --------------------------------------------------------------------
   Idle "alive" motion (PAIRINGS.md row 18) — NOT a CSS @keyframes
   animation any more. Round 2 shipped it as `animation: el-idle` on
   `.el__box`; because a running *or paused* CSS animation beats the base
   `transform` declaration in the cascade, the idle keyframes owned the
   transform property outright: pointer tilt survived only through the
   vars the keyframes happened to re-declare, its rise/scale were damped
   by the frozen keyframe blend, and the `transition: transform .16s`
   below could never run (transitions do not apply to a property an
   animation is animating). Idle motion now comes from the same rAF loop
   in js/main.js that computes proximity excitation, composed into the
   SAME --rx/--ry/--rise/--sc custom properties, so there is exactly one
   transform declaration on `.el__box` and idle + pointer states cannot
   fight over it. Reduced-motion / coarse pointers keep the flat grid via
   the media block above (JS never starts the loop there either).
   -------------------------------------------------------------------- */

/* --- detail panel: js/main.js positions `left`/`top`/`bottom` from the
   active element's own geometry (so it starts at that element's right edge
   and spans the grid's full height), and sets `--origin-y` — the element's
   bottom edge as a % of grid height — as the clip-path collapse point, so
   the reveal opens from that element's bottom-right corner and grows right. */
.ptable__panel {
  position: absolute;
  z-index: 2;
  top: 0; bottom: 0; right: 0;
  width: min(400px, calc(100% - var(--cell) * 2));
  --origin-y: 100%;
  display: flex;
  flex-direction: column;
  padding: 32px 34px 30px;
  background: #FFFDF8; /* floats over the grid: stays solid (luxe pass) */
  border: 1px solid var(--line);
  box-shadow: -24px 34px 60px -38px rgba(23, 20, 18, .28); /* quieted */
  opacity: 0;
  visibility: hidden;
  clip-path: inset(var(--origin-y) 100% calc(100% - var(--origin-y)) 0);
  transition: clip-path .42s var(--ease), opacity .2s var(--ease), visibility 0s .42s;
}
.ptable.is-open .ptable__panel {
  opacity: 1;
  visibility: visible;
  clip-path: inset(0 0 0 0);
  transition: clip-path .44s var(--ease), opacity .16s var(--ease);
}
.ptable__panel-num {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--pa, var(--maroon));
}
.ptable__panel-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(26px, 2.8vw, 38px);
  line-height: 1.1;
  letter-spacing: -.02em;
  color: var(--ink);
  margin: 6px 0 14px;
  text-wrap: balance;
}
.ptable__panel-bonds { margin-top: auto; padding-top: var(--sp-5); }
.ptable__panel-bonds-label {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 10px;
}
.ptable__panel-bonds-list { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.bond { display: inline-flex; align-items: center; }
.bond__link { width: 14px; height: 1.5px; background: var(--line); }
.bond__sym {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  line-height: 1;
  padding: 6px 10px;
  color: var(--bc, var(--ink-soft));
  border: 1px solid var(--bc, var(--line));
  background: var(--paper);
}

/* --- mobile / touch: stack the panel beneath the grid. `position: static`
   makes the JS-set left/top/bottom inline styles inert here, so the panel
   simply flows below the grid instead of overlapping it. --- */
@media (max-width: 860px) {
  .ptable { --cell: clamp(96px, 27vw, 150px); }
  .el { width: 100%; aspect-ratio: 1 / 1; height: auto; }
  /* Row 47 v2 (operator): the fluid 1fr cells no longer match --cell, so the
     extrusion sides' edge-on projections drew a stray inner square. No 3D
     depth is perceptible on touch anyway — the sides go. */
  .el__side { display: none; }
  .el__box, .el__face { }              /* still square via aspect below */
  .ptable__panel {
    position: static;
    left: auto;
    margin-top: 18px;
    clip-path: none;
    height: 0;
    padding: 0 24px;
    border-width: 0;
    overflow: hidden;
    transition: opacity .2s var(--ease);
  }
  .ptable.is-open .ptable__panel {
    clip-path: none;
    height: auto;
    padding: 26px 24px 28px;
    border-width: 1px;
  }
}

/* ==========================================================================
   Journal
   ========================================================================== */
.journal-categories {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  margin-bottom: 40px;
}
.journal-categories__item {
  background: var(--card);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.journal-categories__name {
  font-family: var(--font-display, inherit);
  font-weight: 700;
  font-size: 22px; /* Client call 2026-09-09 (C1): the card titles step up for impact */
  letter-spacing: -.01em;
  color: var(--ink);
}
.journal-categories__desc {
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
}
@media (max-width: 720px) {
  .journal-categories { grid-template-columns: 1fr; }
}

.journal-status {
  border-top: 2px solid var(--ink);
  padding-top: 24px;
  color: var(--muted);
  font-size: 15px;
}
/* Client call 2026-09-09 (C3): the Journal's lead runs the full container width */
#journal .section-head .section-lead { max-width: none; }

/* ==========================================================================
   The fine print (client call 2026-09-09, F1): /legal and /privacy — the
   house voice, set for sustained reading; and the footer's legal thread.
   ========================================================================== */
.legal-doc { max-width: 78ch; }
.legal-doc h2 {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -.01em;
  margin: 36px 0 12px;
  color: var(--ink);
}
.legal-doc p { font-size: 15.5px; line-height: 1.75; color: var(--muted); margin: 0 0 12px; text-wrap: pretty; }
.legal-doc strong { color: var(--ink); font-weight: 650; }
.legal-doc a { color: var(--maroon); }
.legal-doc__updated { margin-top: 36px; font-size: 12.5px; letter-spacing: .06em; text-transform: uppercase; }
/* Placeholders awaiting the entity's real papers — deliberately loud (client:
   "mets-le en gras pour qu'on puisse bien le voir"). */
.legal-doc__placeholder { color: var(--maroon); font-weight: 700; }
/* Client call 2026-09-09 v3: the legal thread folds INTO the copyright line —
   same size, same voice, separated by middots. Present, discreet, no longer
   a competing block in the footer's composition. */
.footer-legal-links { white-space: nowrap; }
.footer-legal-links a { color: inherit; text-decoration: none; }
.footer-legal-links a:hover { color: #DDB877; }

/* Client call 2026-09-09 (CT5 #3, v2 pass 5): the compass rose breathes
   behind AlchAdemy's journey — the FULL circle, rising OUT of the section's
   top edge into the block above (trans-section, per the client), still half
   off the right edge. No overflow clip: the body's own overflow-x: clip
   keeps the page from growing a scrollbar. */
.academy-journey { position: relative; isolation: isolate; }
.academy-journey::before {
  content: "";
  position: absolute;
  z-index: -1;
  right: -130px;
  top: -120px;
  width: 540px;
  height: 540px;
  background: url("../img/engravings/compass-rose-v1.webp") no-repeat center / contain;
  opacity: .12;
  pointer-events: none;
}
/* (CT5 #4: the instruments plate moved to the Services Formulation card —
   see .discipline-card--fo::after.) */

/* Client call 2026-09-09 (F2a): the salamander's cul-de-lampe — one discreet
   bow between chapters, flanked by threads of gold. */
.salamander-lamp {
  display: flex;
  align-items: center;
  gap: 18px;
  max-width: 420px;
  margin: 0 auto;
}
.salamander-lamp__line { flex: 1; height: 1px; background: linear-gradient(90deg, transparent, #C9A45C); }
.salamander-lamp__mark + .salamander-lamp__line { background: linear-gradient(90deg, #C9A45C, transparent); }
.salamander-lamp__mark {
  /* Client pass 11 (2026-09-10): swapped for the client's own salamander
     illustration (docs/creative/extracted-assets/salamandre_MA.png),
     used everywhere a salamander is needed. */
  width: 42px;
  height: 42px;
  background: #93641D;
  -webkit-mask: url("../img/salamander-ma.png") no-repeat center / contain;
  mask: url("../img/salamander-ma.png") no-repeat center / contain;
  opacity: .9;
  flex: 0 0 auto;
}

.journal-list {
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.journal-list__item { background: var(--card); }
.journal-list__link {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 22px 24px;
  transition: background .2s var(--ease);
}
.journal-list__link:hover,
.journal-list__link:focus-visible { background: var(--maroon-tint); }
.journal-list__main {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.journal-list__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 17px;
  text-wrap: balance;
}
.journal-list__category {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--maroon, #7A2418);
}
.journal-list__excerpt {
  font-size: 14px;
  color: var(--muted);
  max-width: 60ch;
}
.journal-list__date {
  font-size: 13px;
  color: var(--muted);
  white-space: nowrap;
}

.journal-detail {
  max-width: 680px;
}
.journal-detail__back {
  display: inline-block;
  margin-bottom: 24px;
  font-size: 14px;
  color: var(--muted);
}
.journal-detail__back:hover,
.journal-detail__back:focus-visible { color: var(--ink); }
.journal-detail__title {
  font-family: var(--font-display);
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 700;
  margin-bottom: 8px;
  text-wrap: balance;
}
.journal-detail__date {
  font-size: 14px;
  color: var(--muted);
  margin-bottom: 32px;
}
.journal-detail__body {
  font-size: 17px;
  line-height: 1.7;
  text-wrap: pretty;
}
.journal-detail__body > * + * { margin-top: 1.2em; }
.journal-detail__body h1,
.journal-detail__body h2,
.journal-detail__body h3 {
  font-family: var(--font-display);
  font-weight: 700;
  margin-top: 1.6em;
}
.journal-detail__body a { color: var(--maroon); text-decoration: underline; }
.journal-detail__body ul,
.journal-detail__body ol { padding-left: 1.4em; }

/* ============ SERVICES: methodology, four stages, disciplines ============ */
.methodology-copy { max-width: 68ch; }
.methodology-copy strong { color: var(--ink); font-weight: 650; } /* S3: key claims step out of the muted voice */
.methodology-copy > * + * { margin-top: var(--sp-5); }
.methodology-copy p { font-size: 17px; line-height: 1.7; color: var(--ink-soft); text-wrap: pretty; }

.stages {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.stage-plate__glyph { width: 26px; height: 26px; color: var(--maroon); }
.stage-plate__num {
  font-family: var(--font-display);
  font-size: 34px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1;
}
.stage-plate__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 16px;
  color: var(--ink);
}
.stage-plate__name span { font-weight: 500; color: var(--muted); }
.stage-plate__text { font-size: 14px; line-height: 1.6; color: var(--muted); text-wrap: pretty; }

/* Three-plate variant (AlchAdemy journey has 3 stages, not 4) -- same
   engraved-plate component, just a column count matched to the content. */
/* AlchAdemy "The Journey" stage sigils as oversized card backgrounds (round-3
   feedback, enlarged and let overflow the card in round-4 global item 2).
   Reuses the exact .pillar__icon-bg contract from Home's Foundations pillars
   (index.html, css/style.css ~L707) verbatim -- same oversized/centred/
   low-opacity/z-index-0-behind-copy rule shape, including the same "spill past
   the card" sizing -- rather than inventing a parallel sizing scheme. Scoped
   to .stages--three only so services.html's four-stage plates keep their
   small glyph-badge look. Colour is --craft-marketing (the Mk gold accent)
   instead of --ink/--maroon to keep AlchAdemy's own page personality. The
   card no longer clips the glyph; `.stages--three` clips horizontally as the
   safety net (html/body already carry a site-wide `overflow-x: clip`). */
.stages--three .stage-plate {
  position: relative;
}
.stages--three {
  grid-template-columns: repeat(3, 1fr);
  overflow-x: clip;
}
.stages--three .stage-plate__glyph {
  position: absolute;
  z-index: 0;
  top: 50%;
  left: 50%;
  width: 145%;
  height: 145%;
  min-width: 120%;
  min-height: 120%;
  transform: translate(-50%, -50%);
  color: var(--craft-marketing);
  opacity: 0.06;
  pointer-events: none;
}
.stages--three .stage-plate__num,
.stages--three .stage-plate__name,
.stages--three .stage-plate__rule,
.stages--three .stage-plate__text {
  position: relative;
  z-index: 1;
}

@media (max-width: 860px) {
  .stages { grid-template-columns: 1fr; }
}

/* Stage plates now live on AlchAdemy only (.stages--three); the Home spine's
   .stages--spine variant was retired with the "Matter, mastered" rework. */
/* Stage badges retain the singular maroon accent. */
.stage-plate {
  background: var(--card);
  padding: 28px 22px;
  display: flex;
  flex-direction: column;
  gap: 10px; --stage-accent: var(--maroon); }
.stage-plate__glyph, .stage-plate__num { color: var(--stage-accent); }
.stage-plate__rule {
  display: block;
  height: 1px; background: var(--stage-accent); }

/* The one recurring ornament (PAIRINGS.md row 4): engraved hairline ray-burst. */
.rayburst {
  display: block;
  width: 64px;
  height: 32px;
  margin-top: 18px;
  color: var(--maroon);
}

.disciplines {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.discipline-card {
  background: var(--card);
  padding: 36px;
  border-top: 3px solid var(--accent);
}
/* Row 22: the cube's per-face panel is a manuscript page, not a white card —
   it sits on the aged-plate paper tone. --ink-soft on --paper-alt is 10.28:1. */
.craft-panel.discipline-card { background: var(--paper-alt); }
.discipline-card--br { --accent: var(--craft-identity); }
.discipline-card--fo { --accent: var(--craft-formulation); }
/* Client pass 11 (2026-09-10): the instruments-plate engraving is removed
   from the Formulation card entirely (was moved here from About in pass 6,
   now dropped outright, not relocated). */
.discipline-card--mk { --accent: var(--craft-marketing); }
.discipline-card--au { --accent: var(--craft-audit); }
.discipline-card--wk { --accent: var(--craft-workshops); }
.discipline-card--ex { --accent: var(--craft-expansion); }
.discipline-card__num {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12px;
  color: var(--accent);
}
.discipline-card__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 22px;
  margin: 6px 0 4px;
  text-wrap: balance;
}
.discipline-card__hook { font-weight: 600; color: var(--ink); margin-bottom: var(--sp-4); }
.discipline-card__copy { font-size: 15px; line-height: 1.65; color: var(--ink-soft); text-wrap: pretty; }
.discipline-card__copy + .discipline-card__copy { margin-top: var(--sp-5); }
.discipline-card__included-label {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink);
  /* a new sub-block inside the card, so one rank ABOVE paragraph spacing */
  margin-top: var(--sp-6);
  margin-bottom: var(--sp-4);
}
.included-list {
  margin-top: 16px;
}
.included-list li {
  position: relative;
  padding-left: 16px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.included-list li + li { margin-top: 8px; }
.included-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  width: 6px;
  height: 6px;
  background: var(--accent);
}
.discipline-card .included-list + .btn {
  margin-top: 32px;
}
/* --- The cheminement (PAIRINGS.md row 22) --------------------------------
   The Services cube's per-face "What's included" content. NOT a bullet list and
   not a restyled bullet: the deliverables sit on a serpentine route, each item at
   a node, consecutive nodes joined by a stepped hairline drawn as an inline SVG.
   Markup stays a real <ol> in source order (the progression is announced), and
   every drawn element (node mark, connector, index numeral) is aria-hidden
   decoration. No motion of its own, so prefers-reduced-motion needs no branch. */
.cheminement {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  --o-step: 28px;
}
/* Client call 2026-09-11: Marketing's "What's included" is the one discipline
   whose source deck (MA_v2.pdf p.6) groups the list under its own bold
   sub-headers ("Social media", "Website") rather than one flat run — checked
   against all six discipline pages; only Marketing carries this structure.
   Rendered as its own small heading between separate .cheminement lists
   (each list keeps its own 2-column layout and restarts its numbering, so it
   reads as three distinct checklists). --sp-6 above matches "a new sub-block
   inside a card" elsewhere on this page; a plain .cheminement immediately
   after one needs less than its own default 16px lead-in. */
.cheminement-group {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--accent);
  margin: var(--sp-6) 0 0;
}
.cheminement-group + .cheminement { margin-top: var(--sp-4); }
.cheminement__step {
  --o: 0;   /* which column of the route this step sits in (0|1|2) */
  --dir: 1; /* +1 the route steps right into the next node, -1 it steps back left */
  position: relative;
  margin-left: calc(var(--o) * var(--o-step));
  padding-left: 52px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.cheminement__step + .cheminement__step { margin-top: 22px; }
/* Each step leads with its key value term (editorial <strong> in the HTML,
   the Workshops list's own pattern extended to all six crafts). */
.cheminement__text strong { font-weight: 600; color: var(--ink); }
/* Client 2026-09-07 (#6): the serpentine offsets are RETIRED — « l'arborescence,
   ça fonctionne pas ». Every step sits on one left edge, a classic list; the
   engraved node mark and index numeral stay as the house bullet. The stepped
   connector hairlines go with the route (rule below). Row 22 superseded. */
.cheminement__link { display: none; }
/* Engraved node mark — the same hairline drawing language as the other symbols. */
.cheminement__node {
  position: absolute;
  left: 0;
  top: 4px;
  width: 12px;
  height: 12px;
  color: var(--accent);
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
}
.cheminement__index {
  position: absolute;
  left: 20px;
  top: 3px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: .06em;
  line-height: 1.25;
  color: var(--muted);
}
/* The route itself: runs from this node down and across to the next one. The
   box is stretched vertically (preserveAspectRatio="none"); the stroke stays a
   true hairline via vector-effect. */
.cheminement__link {
  position: absolute;
  top: 10px;
  left: calc(5px + (var(--dir) - 1) * 14px);
  width: var(--o-step);
  height: calc(100% + 22px);
  transform: scaleX(var(--dir));
  fill: none;
  stroke: var(--line);
  stroke-width: 1;
}
/* Small screens: the route collapses to one readable stacked column with the
   hairline running straight down the left edge — still a route, never a list. */
@media (max-width: 639px) {
  .cheminement { --o-step: 0px; }
  .cheminement__link {
    left: 5px;
    width: 1px;
    transform: none;
  }
}

.disclaimer {
  margin-top: 22px;
  font-size: 12px;
  font-style: italic;
  line-height: 1.6;
  color: var(--muted);
}

@media (max-width: 860px) {
  .disciplines { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------
   Services — the craft cube (PAIRINGS.md row 16 / DESIGN.md §10.1)

   Two states, base-first:

   1. FLAT CROSS-NET (the default, and the ONLY state under
      prefers-reduced-motion, with JS off, or below 1200px): `.craft-cube__cube`
      is a plain 2D CSS grid laid out as a literal unfolded cube net (cross),
      no `preserve-3d`, no transform, no animation; the six panels sit in the
      normal two-column `.disciplines` grid, all content visible at once.
   2. LIVE (`.craft-cube.is-live`, added by js/main.js only when motion is
      permitted and the viewport is at least 1200px wide): the track grows, the pin
      sticks, the six net cells fold into a solid cube that idles in a slow
      self-rotation, and scrolling shifts it aside while `data-face` steps the
      cube and the panels through the six crafts one at a time.

   Round-6 operator directive (SUPERSEDES round 5's all-obsidian faces; that
   styling is archived verbatim in assets/craft-cube-obsidienne-v1-archive.css
   and overrides DESIGN.md §10's flat-matte policy FOR THIS COMPONENT ONLY):
   each face is now THREE DEPTHS of cut stone, read from the surface down —
     1. a FRAME of very light white marble (Carrara-like: cool off-white,
        faint grey-blue veining) around the rim of the face,
     2. sunk BELOW the frame, a recessed floor of the round-5 polished
        obsidian (the frame casts a real shadow onto it: dark inner lip at
        the top/left, light-caught lip at the bottom/right — one light
        source, upper-left, shared with every other effect on the cube),
     3. cut deeper still into that black floor, the ENGRAVINGS: the atomic
        number top-left, the big element symbol + craft name centred, and an
        alchemical sigil bottom-right. The craft accent colours the letters
        only, as a reflection inside the glyphs (background-clip: text).
   Implementation constraint carried over from round 4: everything is
   background LAYERS + border-radius + inset shadows; never `filter` or
   `clip-path` on a face itself (both are grouping properties: they flatten a
   preserve-3d child and reintroduce the round-4 depth-sort flicker). The
   recessed floor is the face's ::before (a positioned pseudo paints above
   non-positioned inline content, so the engraved spans carry position:
   relative to stay on top of it).
   -------------------------------------------------------------------- */
/* Bigger and freer per PAIRINGS.md round 3 (row 16): before clamp(190px, 22vw,
   280px) / live clamp(180px, min(20vw,26vh), 280px) — after clamp(200px, 26vw,
   340px) / live clamp(220px, min(24vw,30vh), 340px), larger at every step.
   (Min kept at 200px, not 220px, so the flat cross-net's 3-column width never
   exceeds `.container` between the 700px media query and the 768px breakpoint.) */
.craft-cube { --cube-size: clamp(200px, 26vw, 340px); }
.craft-cube__intro { max-width: 860px; margin: 0 auto 48px; text-align: center; } /* T2: wider measure */
.craft-cube__intro .methodology-copy { margin-top: var(--sp-5); max-width: none; }
.craft-cube__head { margin-bottom: 28px; }
.craft-cube__model { display: none; }
.craft-cube__model-stage { position: relative; }

/* --- 1. Flat cross-net (base) --- */
.craft-cube__cube {
  display: grid;
  grid-template-columns: repeat(3, var(--cube-size));
  grid-template-rows: repeat(4, var(--cube-size));
  grid-template-areas:
    ".    top    ."
    "left front  right"
    ".    bottom ."
    ".    back   .";
  gap: 6px;
  justify-content: center;
  margin: 0 auto 48px;
  width: max-content;
  max-width: 100%;
}
.craft-face {
  /* Frame width scales with the face so the marble rim keeps its proportion
     from the flat net (200px faces) up to the live cube (340px). */
  --frame: clamp(14px, calc(var(--cube-size) * .07), 24px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: calc(var(--frame) + 16px);
  /* DEPTH 1 — the FRAME. Client pass 5 (D1 v3, transmutation): the fallback
     rim mirrors the GLB's iron-umber patina with GOLD showing through at
     the worn spots — dark base metal turning noble, worn-gold pools from
     the upper-left, deep oxidation at the lower-right, tooling strokes at
     whisper alpha. */
  background-image:
    linear-gradient(133deg, rgba(232,196,124,.26) 0%, rgba(170,134,76,.10) 30%, transparent 55%, rgba(14,9,4,.5) 100%),
    radial-gradient(320px 200px at 24% 16%, rgba(226,190,120,.22), transparent 62%),
    radial-gradient(180px 120px at 60% 88%, rgba(216,178,104,.10), transparent 70%),
    radial-gradient(260px 170px at 78% 74%, rgba(12,8,3,.36), transparent 66%),
    repeating-linear-gradient(98deg, transparent 0 5px, rgba(24,16,6,.14) 5px 6px, transparent 6px 13px),
    repeating-linear-gradient(9deg, transparent 0 11px, rgba(226,190,124,.06) 11px 12px, transparent 12px 27px);
  background-color: #3b2c1d;
  /* Fine dark arris where two bronze frames meet on the assembled cube. */
  border: 1px solid rgba(26, 17, 7, .6);
  position: relative;
  /* Referenced by the assembled per-face shading rules further down — same
     names as round 5, values re-lit for aged bronze instead of pale stone. */
  --bevel-hi: inset 2px 2px 3px rgba(232, 198, 132, .38);
  --bevel-lo: inset -3px -3px 8px rgba(20, 13, 5, .5);
  box-shadow: var(--bevel-hi), var(--bevel-lo);
}
/* DEPTH 2 — the recessed obsidian floor, sunk below the marble frame. The
   floor itself is the round-5 polished-obsidian layer stack, unchanged
   (sheet reflection, smoky clouds, dust specks, striations + flow bands).
   What makes it read as CUT INTO the marble is the lighting of the pit:
   with light from the upper-left, the frame's top/left walls throw a hard
   shadow across the floor's near edge (the two big dark inset shadows),
   while the bottom/right inner lip catches a sliver of light (the pale
   bottom/right border + the faint light inset). A pseudo-element, not a
   wrapper div: the markup stays six flat faces, and — being a positioned
   box — it needs no z-index of its own, only position: relative on the
   engraved spans above it. */
.craft-face::before {
  content: "";
  position: absolute;
  inset: var(--frame);
  border-radius: 7px 5px 8px 6px;
  /* Round-12 BONE face skin (client: the face is light — toward white, never
     pure — matching the regenerated GLB). The round-6 obsidian values this
     replaced were folded away in place (BACKLOG 1.3): this IS the final skin. */
  background-color: #E7DFCE;
  background-image:
    linear-gradient(133deg, rgba(255,252,244,.5) 0%, rgba(255,252,244,.12) 24%, transparent 47%, rgba(74,52,30,.16) 100%),
    radial-gradient(420px 240px at 70% 10%, rgba(184,164,132,.13), transparent 62%),
    radial-gradient(340px 260px at 20% 82%, rgba(158,140,112,.09), transparent 66%),
    repeating-linear-gradient(94deg, rgba(255,252,244,.06) 0 2px, transparent 2px 9px),
    repeating-linear-gradient(4deg, rgba(74,52,30,.05) 0 1px, transparent 1px 17px);
  background-size: auto, auto, auto, auto, auto;
  background-position: 0 0;
  border: 1px solid rgba(74, 52, 30, .35);
  border-bottom-color: rgba(255, 252, 244, .75);
  border-right-color: rgba(255, 252, 244, .5);
  box-shadow:
    inset 4px 5px 9px rgba(60, 40, 22, .32),
    inset 12px 14px 30px rgba(60, 40, 22, .14),
    inset -1px -2px 3px rgba(255, 252, 244, .35),
    /* orientation veil: the assembled-cube shading rules below tint each
       face's frame with an inset shadow, but a positioned ::before paints
       ABOVE its parent's inset shadows — so the same veil is re-applied
       here through an inherited custom property, or the recessed floors
       would stay uniformly lit while their frames darken. */
    inset 0 0 0 999px var(--pit-shade, rgba(0, 0, 0, 0));
}
/* Truncated corners, as on the reference cube (its corners are cut at 45°).
   Done with border-radius, NOT clip-path (clip-path is a grouping property —
   it would flatten the face out of the preserve-3d context and reintroduce
   the round-4 flicker). Kept slightly irregular per face: cut stone, not a
   machined die. On the assembled cube these radii open small notches at the
   eight vertices — exactly where the reference cube's truncations sit. */
.craft-face--front  {
  grid-area: front; border-radius: 14px 11px 16px 12px; }
.craft-face--back   {
  grid-area: back; border-radius: 11px 15px 12px 14px; }
.craft-face--right  {
  grid-area: right; border-radius: 15px 12px 13px 11px; }
.craft-face--left   {
  grid-area: left; border-radius: 12px 13px 11px 16px; }
.craft-face--top    {
  grid-area: top; border-radius: 13px 14px 11px 15px; }
.craft-face--bottom {
  grid-area: bottom; border-radius: 11px 15px 14px 12px; }
/* DEPTH 3 — ENGRAVED LETTERING (round-5 treatment, kept for round 6: the
   incisions now cut into the recessed obsidian floor rather than the face
   surface). All text pieces are incised, centred as a group by the face's
   own flex centring, and carry position: relative so they paint ABOVE the
   positioned ::before floor. The
   craft --accent (each face carries the `.el--xx` modifier that defines it —
   see services.html; it is never unset/transparent, the exact trap flagged in
   this repo's memory) appears ONLY here: as a coloured reflection band inside
   the letterforms, via a gradient clipped to the glyphs. Incision depth comes
   from two drop-shadows following the glyph contour — lit bottom lip, dark
   top edge (light from the upper-left, same source as the face sheen). Safe
   w.r.t. the round-4 flicker rule: `filter` is forbidden on the FACES (direct
   children of the preserve-3d context); these spans are grandchildren and
   flatten into their face's plane, so depth sorting is untouched. */
.craft-face__num,
.craft-face__sym,
.craft-face__name {
  /* fallback when background-clip:text is unsupported: plain incision, cut
     into the round-12 bone face (was obsidian; folded, BACKLOG 1.3) */
  color: #4A3216;
  text-shadow: 0 1px 0 rgba(255, 252, 244, .5);
  /* above the positioned ::before bone floor */
  position: relative;
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .craft-face__num,
  .craft-face__sym,
  .craft-face__name {
    /* The reflection band: dark glass above, a hot accent-tinted core (the
       craft accents are all deep, muted tones — mixed 38% toward white here
       so the glint actually catches), pure accent just under it, then a fast
       fall back to glassy black. Each span clips this gradient to its own
       box, so num, sym and name each carry their own band. */
    background-image: linear-gradient(
      157deg,
      #08080b 0%,
      #292931 26%,
      color-mix(in srgb, var(--accent) 62%, #fff 38%) 46%,
      var(--accent) 58%,
      color-mix(in srgb, var(--accent) 32%, #08080b) 72%,
      #060608 100%
    );
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    text-shadow: none;
    filter: drop-shadow(0 1px 0 rgba(255, 255, 255, .11)) drop-shadow(0 -1px 0 rgba(0, 0, 0, .65));
  }
  /* The small pieces (chip number, craft name) are a shallower cut: at 12-13px
     the deep near-black band above renders them illegible on the dark glass
     (verified on a 1140px raster). Lighter frosted-glass greys with the same
     accent reflection keep them readable while still reading as engraved. */
  }
/* Atomic-number chip, top-left INSIDE the recessed floor — same reading
   order as the home .el tile. No accent fill (colour lives only in the
   letters); the chip is a stamped border on the black floor, its number
   engraved like the rest of the face. Offsets clear the frame width plus
   the pit's own shadowed lip. */
.craft-face__sym {
  font-family: var(--font-display);
  font-weight: 700;
  /* .30, down from round 5's .34: the engraved area lost the frame's width
     on each side, and the big glyph must not crowd the pit walls. */
  font-size: calc(var(--cube-size) * .30);
  line-height: 1;
}
.craft-face__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-align: center;
}
/* Alchemical sigil, bottom-right of the recessed floor (round-6): one line
   sign per craft (sun / water / air / earth / fire / mercury — see
   services.html for the mapping rationale). Engraved NEUTRAL: the accent
   colour belongs to the letters alone, so the sigil takes the frosted-grey
   incision treatment. drop-shadow here is safe w.r.t. the round-4 flicker
   rule for the same reason as the text spans: the svg is a CHILD of the
   face, it flattens into the face's plane. */
/* --- 2. Live state (JS-added: motion allowed AND >=1200px) --- */
.craft-cube.is-live .craft-cube__track { height: calc(6 * 100vh); }
/* In the pinned frame the cube is sized against viewport HEIGHT too, so the
   intro copy and the idling cube always clear each other on short screens. */
/* Round 9 (operator): the live cube x1.3 — every bound of the round-3 clamp
   (220 / 24vw / 30vh / 340) scaled by 1.3. */
/* Client pass 14 (2026-09-10): "réduire de moitié" — the previous pass only
   shrank the SEQ-phase die (the atelier chapters); this arrival/idle die kept
   its original clamp, so the page still opened on the big cube and read as
   unchanged. Halved here (renders ~130px at 1440x900 vs ~253px before,
   including the idle scale(.72) below). */
.craft-cube.is-live { --cube-size: clamp(170px, min(16vw, 20vh), 240px); }
/* Every layer inside the pin is absolutely positioned against it: the intro,
   the cube and the text panel each need their own pose per phase, and sharing
   one flow would let the tall intro copy dictate the frame's height.
   Full-bleed (viewport-width, not container-width): this is what lets the
   larger cube visually overflow the `.container` box beside it (task: "may
   visually overflow its container") while `overflow: hidden` still caps it at
   100vw — so it never adds a horizontal page scrollbar. */
.craft-cube.is-live .craft-cube__pin {
  position: sticky;
  top: 0;
  height: 100vh;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  overflow: hidden;
}
.craft-cube.is-live .craft-cube__intro,
.craft-cube.is-live .craft-cube__stage,
.craft-cube.is-live .craft-cube__panels {
  position: absolute;
  left: 50%;
  top: 50%;
  margin: 0;
  transition: transform .8s var(--ease), opacity .5s var(--ease);
}
/* The methodology intro holds the frame first, sitting above the idling cube,
   then is pushed up and out the moment the cube sequence takes over. */
.craft-cube.is-live .craft-cube__intro {
  /* Compressed against the flowing fallback: the pinned frame has to hold the
     whole intro AND the idling cube inside one viewport height. Round 9: the
     section now OPENS the page, so at scroll 0 the pin sits below the fixed
     header and loses ~8vh — intro raised (-18vh -> -21vh) and the idle cube
     scaled down (see __stage below) so the whole die stays inside the
     viewport on arrival. */
  /* Client call 2026-09-09 (S1/S2): wider column = fewer lines = the intro
     no longer starts under the header nor crowds the die below — and it
     gains real clearance from the fixed header (-19vh -> -15vh). */
  width: min(840px, 92%);
  transform: translate(-50%, -50%) translateY(-15vh);
}
.craft-cube.is-live .craft-cube__intro .section-title { font-size: clamp(26px, 3vw, 34px); }
.craft-cube.is-live .craft-cube__intro .methodology-copy p { font-size: 14px; line-height: 1.6; }
.craft-cube.is-live .craft-cube__intro .methodology-copy p + p { margin-top: 10px; }
.craft-cube.is-live[data-phase="seq"] .craft-cube__intro {
  transform: translate(-50%, -50%) translateY(-70vh);
  opacity: 0;
  pointer-events: none;
}
/* Centred (below the intro) while the cube idles; slid to the left of the
   frame once the sequence starts, so the text panel can hold the centre. */
.craft-cube.is-live .craft-cube__stage {
  perspective: 1400px;
  /* Idle: raised and scaled to .8 so the FULL die (plus its overshoot during
     the idle spin) fits under the intro and above the viewport's bottom edge
     even with the fixed header eating the top of the pin at scroll 0. The
     seq-phase rule below replaces this transform entirely, so the cube grows
     back to full size as the sequence takes the frame (the .8s transform
     transition carries the morph). */
  transform: translate(-50%, -50%) translateY(25vh) scale(.72); /* S1/S2: cleared down+smaller so the widened intro never overlaps the idling die */
}
.craft-cube.is-live .craft-cube__model-stage {
  width: var(--cube-size);
  height: var(--cube-size);
  margin: 0 auto;
  touch-action: pan-y;
  cursor: grab;
}
.craft-cube.is-live .craft-cube__model-stage:focus-visible {
  outline: 2px solid var(--maroon);
  outline-offset: 10px;
}
.craft-cube.is-live.is-dragging .craft-cube__model-stage { cursor: grabbing; }
.craft-cube.is-live .craft-cube__model {
  position: absolute;
  z-index: 2;
  /* Round 9: the render canvas extends well past the cube-size stage box.
     A rotating cube's projected extent grows to its bounding sphere
     (sqrt(3) x the face size at the worst corner-on pose): clipped at the
     stage box, its corners were visibly cut mid-turn. The pin (overflow:
     hidden, full-bleed 100vw) still bounds it; js/craft-cube-3d.js's camera
     radius compensates so the FACE keeps the stage-box size on screen. */
  inset: -50%;
  display: block;
  pointer-events: none;
}
.craft-cube.is-live .craft-cube__model canvas {
  display: block;
  width: 100%;
  height: 100%;
}
/* Round 9: the model is a <model-viewer> element (js/craft-cube-3d.js). It
   fills the stage box; the section's parchment shows through (no poster, no
   background of its own). */
.craft-cube.is-live .craft-cube__model model-viewer {
  display: block;
  width: 100%;
  height: 100%;
  background: transparent;
  --poster-color: transparent;
}
.craft-cube.is-live .craft-cube__model-stage .craft-cube__cube {
  position: absolute;
  inset: 0;
  margin: 0;
}
/* The GLB replaces only the wide-screen live presentation. The CSS cube
   stays in the DOM as the input surface, the <1200px flat-net presentation,
   and the guaranteed fallback — but on the 3D path it must never be SEEN:
   js/craft-cube-3d.js sets is-model-loading synchronously the moment it
   decides to load the model (round 10: without this the visitor watched the
   CSS cube render and fold, then get swapped out), and clears it again if
   the model fails, letting the CSS cube step back in. */
.craft-cube.is-model-loading .craft-cube__cube { opacity: 0; transition: none; }
.craft-cube.is-live.is-model-ready .craft-cube__cube { opacity: 0; }
.craft-cube.is-live[data-phase="seq"] .craft-cube__stage {
  /* Pushed further left than the panel needs (was max(-290px, -24vw)) so the
     now-larger cube's box crosses the `.container` edge on desktop — the pin
     is full-bleed to 100vw, so this stays visual overflow only, never a
     horizontal scrollbar. */
  transform: translate(-50%, -50%) translateX(max(-470px, -33vw));
}
/* The face title only belongs to the sequence, so it takes no vertical room
   while the intro and the idling cube share the frame. */
.craft-cube.is-live .craft-cube__head {
  text-align: center;
  width: min(360px, 80vw);
  margin: 0 auto;
  height: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity .5s var(--ease);
}
.craft-cube.is-live .craft-cube__head .section-title { font-size: 24px; }
.craft-cube.is-live[data-phase="seq"] .craft-cube__head {
  height: auto;
  margin: 0 auto 20px; opacity: 1; }

/* 2a/2b. ONE transform source, always (see js/main.js "Services -- the craft
   cube"). This used to be three sources fighting over `transform` on the same
   element: a `@keyframes craft-cube-idle` self-rotation, a stack of
   `[data-face="n"]` transform rules, and the JS-written --cube-rx/--cube-ry
   drag pose. Switching phase dropped the running keyframe, which snapped the
   cube back to rotateY(0) and then eased forward again — the "closes up and
   rewinds" glitch — and the assembly fold (scale .42 -> 1) never played at all
   because the idle keyframe's own `scale(1)` preempted it on the same frame.
   Now JS owns rx/ry unconditionally (idle spin included) and the fold rides a
   separate custom property, so nothing can preempt anything.
   2c. Manual drag / keyboard rotation (PAIRINGS.md row 16 (b)+(d)). Once the
   visitor has grabbed the cube, JS owns the pose through --cube-rx/--cube-ry
   for every subsequent face change too, so scroll, drag and keyboard all write
   to ONE transform source and can never fight each other. */
.craft-cube.is-live .craft-cube__cube {
  display: block;
  position: relative;
  width: var(--cube-size);
  height: var(--cube-size);
  margin: 0 auto;
  transform-style: preserve-3d;
  /* The ONLY `transform` declaration on this element. --cube-scale carries the
     assembly fold, --cube-rx/--cube-ry carry the pose (JS-written in every
     phase: idle spin, scroll/wheel steps, drag and keyboard alike). */
  transform: scale(var(--cube-scale)) rotateX(var(--cube-rx)) rotateY(var(--cube-ry));
  transition: transform 1.1s cubic-bezier(.22, .68, .28, 1.01);
  --cube-rx: -10deg;
  --cube-ry: 0deg;
  --cube-scale: .42;
  touch-action: pan-y; /* horizontal = ours, vertical = the page's scroll */
  cursor: grab;
}
.craft-cube.is-live .craft-face {
  position: absolute;
  inset: 0;
  /* pre-assembly: the six cells laid out flat in the cross net */
  transform: translate3d(calc(var(--nx) * 106%), calc(var(--ny) * 106%), 0);
  transition: transform 1.1s cubic-bezier(.22, .68, .28, 1.01), box-shadow .8s var(--ease);
  /* Opaque solids: never paint the inside of a face we are looking at from
     behind. Halves the overdraw at the silhouette, where two faces meet. */
  backface-visibility: hidden;
}
.craft-cube.is-live .craft-face--front  { --nx: 0;  --ny: 0; }
.craft-cube.is-live .craft-face--right  { --nx: 1;  --ny: 0; }
.craft-cube.is-live .craft-face--left   { --nx: -1; --ny: 0; }
.craft-cube.is-live .craft-face--top    { --nx: 0;  --ny: -1; }
.craft-cube.is-live .craft-face--bottom { --nx: 0;  --ny: 1; }
.craft-cube.is-live .craft-face--back   { --nx: 0;  --ny: 2; }

/* assembled: each cell folds onto its own cube face */
.craft-cube.is-assembled .craft-face--front  { transform: translateZ(calc(var(--cube-size) / 2)); }
.craft-cube.is-assembled .craft-face--back   { transform: rotateY(180deg) translateZ(calc(var(--cube-size) / 2)); }
.craft-cube.is-assembled .craft-face--right  { transform: rotateY(90deg)  translateZ(calc(var(--cube-size) / 2)); }
.craft-cube.is-assembled .craft-face--left   { transform: rotateY(-90deg) translateZ(calc(var(--cube-size) / 2)); }
/* Matte stepped shading so the solid reads as a solid, never a lit surface.
   ROOT CAUSE OF THE FLICKER (fixed here): this used to be `filter: brightness()`.
   A `filter` on a child of a `transform-style: preserve-3d` parent forces that
   child into its own flattened rendering group, so the compositor stopped
   depth-sorting the shaded faces against the unshaded ones — at the silhouette,
   where the front face and the side face meet on almost the same plane, the two
   groups swapped z every frame and the cube shimmered. An inset box-shadow
   paints the same matte step inside the face's own background layer and keeps
   the face a plain 3D-sorted box.
   Round-5 (obsidian): the dark veils sit over the faces' smoky reflection
   layers, so away-facing sides genuinely lose their sheen; the top face
   mirrors the sky and reads clearly lighter, as in the reference photo. */
.craft-cube.is-assembled .craft-face--right,
.craft-cube.is-assembled .craft-face--left   { box-shadow: var(--bevel-hi), var(--bevel-lo), inset 0 0 0 999px rgba(0, 0, 0, .24); --pit-shade: rgba(0, 0, 0, .24); }
.craft-cube.is-assembled .craft-face--bottom {
  transform: rotateX(-90deg) translateZ(calc(var(--cube-size) / 2)); box-shadow: var(--bevel-hi), var(--bevel-lo), inset 0 0 0 999px rgba(0, 0, 0, .38); --pit-shade: rgba(0, 0, 0, .38); }
.craft-cube.is-assembled .craft-face--top    {
  transform: rotateX(90deg) translateZ(calc(var(--cube-size) / 2)); box-shadow: var(--bevel-hi), var(--bevel-lo), inset 0 0 0 999px rgba(233, 238, 246, .12); --pit-shade: rgba(233, 238, 246, .12); }

/* The assembly fold is a property of its own, so it can never be clobbered by
   a pose change: the net lies flat at .42 and folds to 1 exactly once. */
/* Once the six faces are folded the pose eases; during the fold itself the
   longer fold curve holds. */
.craft-cube.is-live.is-assembled .craft-cube__cube {
  --cube-scale: 1;
  transition: transform .9s cubic-bezier(.3, .7, .2, 1);
}
/* Pointer drag and the idle self-rotation are both driven frame by frame, so
   they must not be smoothed a second time by a transition. */
.craft-cube.is-live.is-dragging .craft-cube__cube,
.craft-cube.is-live.is-spinning .craft-cube__cube { transition: none; }
.craft-cube.is-live.is-dragging .craft-cube__cube { cursor: grabbing; }
.craft-cube.is-live .craft-cube__cube:focus-visible {
  outline: 2px solid var(--maroon);
  outline-offset: 10px;
}

/* --- Panels: all six stacked in the base state, one at a time when live --- */
.craft-cube.is-live .craft-cube__panels {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  /* Sized and offset in % of the pinned frame (not vw) so the panel always
     stays inside the container gutter at every width. */
  width: 50%;
  background: none;
  border: 0;
  transform: translate(-50%, -50%) translateX(48%);
  opacity: 0;
  pointer-events: none;
}
.craft-cube.is-live[data-phase="seq"] .craft-cube__panels { opacity: 1; pointer-events: auto; }
.craft-cube.is-live .craft-panel {
  grid-area: 1 / 1 / 2 / 2;
  border: 1px solid var(--line);
  border-top: 3px solid var(--accent);
  padding: 24px 28px;
  max-height: 86vh;
  overflow: auto;
  opacity: 0;
  transform: translateY(18px);
  pointer-events: none;
  /* Kept in the accessibility tree (opacity only, never visibility/hidden) so a
     screen-reader user still reads all six crafts in document order. */
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
.craft-cube.is-live .craft-panel.is-active {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.craft-cube.is-live .craft-panel .discipline-card__name { font-size: 20px; }
.craft-cube.is-live .craft-panel .discipline-card__copy { font-size: 13.5px; line-height: 1.6; }
.craft-cube.is-live .craft-panel .disclaimer { margin-top: 16px; }
/* Round 9 (operator): in the LIVE panel the serpentine route reads as noise
   next to the crafted 3D die — the cube carries the personality, the panel's
   job is to be effortlessly scannable. So here (and only here — the flat
   fallback keeps the full cheminement) the route collapses to a calm
   two-column register: no elbows, no stagger, engraved node + number + text
   on one aligned edge. Multicol (not grid) so items read DOWN each column in
   source order, and long entries keep their node with break-inside. */
.craft-cube.is-live .craft-panel .cheminement {
  --o-step: 0px;
  column-count: 2;
  column-gap: 34px;
  margin-top: 14px;
}
.craft-cube.is-live .craft-panel .cheminement__step {
  margin-left: 0;
  break-inside: avoid;
  font-size: 13.5px;
  line-height: 1.55;
}
.craft-cube.is-live .craft-panel .cheminement__step + .cheminement__step { margin-top: 12px; }
.craft-cube.is-live .craft-panel .cheminement__link { display: none; }
/* Panels long enough to scroll get a focus ring and a tab stop from js/main.js. */
.craft-cube.is-live .craft-panel:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }

.discipline-card__program-tag {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 10px;
}

@media (max-width: 700px) {
  .craft-cube { --cube-size: min(150px, 30vw); }
  .craft-cube__intro { margin-bottom: 36px; }
}
/* Row 47a — flat staging: everywhere the live gates (1200×680) don't hold,
   the chapter opens with its reading — intro first, the net as a compact
   frontispiece, then the six notices. The live layout owns its own order. */
@media (max-width: 1199px), (max-height: 679px) {
  .craft-cube:not(.is-live) .craft-cube__pin { display: flex; flex-direction: column; }
  .craft-cube:not(.is-live) .craft-cube__intro { order: 1; }
  .craft-cube:not(.is-live) .craft-cube__stage { order: 2; }
  .craft-cube:not(.is-live) .craft-cube__panels { order: 3; }
}
@media (max-width: 480px) {
  /* Row 47a — phone frontispiece: two-up plates in craft order 01→06
     (front/right/back/left/top/bottom are the faces' net names). */
  .craft-cube__cube {
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: auto;
    grid-template-areas:
      "front right"
      "back  left"
      "top   bottom";
    width: 100%;
  }
  .craft-face { min-height: 130px; }
  /* The engraved sigil crowds the craft name on the small plates. */
  .craft-face__glyph { display: none; }
}


/* --- Home Process: Matter, mastered (PAIRINGS rows 15 and 21, Astra) -------
   The illustration accompanies the actual four-step copy. No synthetic track.
   These selectors are exclusive to Home; Services stage plates are unchanged. */
#stages.process-section { padding-block: 72px 80px; }
.process-section > .container { max-width: 1360px; }
.process-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px;
  margin: 0 0 32px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}
.process-heading .section-title {
  max-width: 820px;
  font-size: clamp(36px, 4vw, 58px);
  line-height: 1.08;
  letter-spacing: -.045em;
}
.process-heading .rayburst { flex: 0 0 64px; margin: 0 0 8px; }
.process-journey {
  --process-progress: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.52fr) minmax(0, 1fr);
  align-items: start;
  gap: clamp(32px, 5vw, 72px);
}
.process-study { position: relative; min-width: 0; }
.process-journey.is-enhanced .process-study {
  position: sticky;
  top: 104px;
}
.stage-object {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  margin: 0;
  pointer-events: none;
}
.stage-object picture { display: block; width: 100%; height: 100%; }
.stage-object__still,
.stage-object__canvas {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.stage-object__canvas { position: absolute; inset: 0; }
.stage-object.is-live picture { visibility: hidden; }
.process-nav { position: relative; margin: 0 12px; border-top: 1px solid var(--line); }
.process-nav::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  height: 1px;
  width: 100%;
  background: var(--maroon);
  transform: scaleX(var(--process-progress));
  transform-origin: left center;
}
.process-nav ol { display: flex; justify-content: space-between; }
.process-nav a {
  display: grid;
  place-items: center;
  min-width: 48px;
  min-height: 48px;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
}
.process-nav a:hover, .process-nav a[aria-current] { color: var(--maroon); }
.process-nav a[aria-current] { background: var(--maroon-tint); }
.process-steps { padding-top: var(--sp-5); }
.process-step {
  position: relative;
  padding: 25px 0 34px;
  border-top: 1px solid var(--line);
  scroll-margin-top: 108px;
}
.process-step.is-active { border-color: var(--maroon); }
.process-step__heading {
  display: grid;
  grid-template-columns: 22px 1fr 28px;
  align-items: start;
  gap: 14px;
  margin-bottom: 16px;
}
.process-step__index {
  padding-top: 6px;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 12px;
}
.process-step__name {
  font-family: var(--font-display);
  font-size: clamp(23px, 2vw, 28px);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -.035em;
}
/* Client call 2026-09-11: the alchemical phase (Calcination, Dissolution,
   Conjunction, Coagulation) is the name that carries the metaphor - it read
   as a whispered caption under the plain-English step name. Bold, uppercase
   and tracked so it reads as the stage's true title, not a footnote. */
.process-step__phase {
  color: var(--maroon);
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  margin-top: var(--sp-2);
}
.process-step__glyph { width: 24px; height: 24px; margin-top: 4px; color: var(--maroon); }
.process-step__text { color: var(--ink-soft); font-size: 15px; line-height: 1.7; padding-left: 36px; }
.process-step:focus { outline: none; }
.process-step:focus-visible { outline: 2px solid var(--maroon); outline-offset: 8px; }
/* --- Pinned presentation (operator, round 2026-09-06) ---------------------
   When the heading reaches the top of the viewport the whole composition
   freezes; scroll then walks the four stages one by one before the page
   resumes. js/stages-journey.js adds .is-pinned (same gate as .is-enhanced),
   sets the section's total track height and the journey's on-screen height
   inline, and slides the clipped step column so the active step stays in
   view. Non-enhanced devices never get the class: plain flow, as before. */
#stages.process-section.is-pinned { padding-block: 0; }
.process-section.is-pinned > .container {
  position: sticky;
  top: var(--process-pin-top, 88px);
  padding-bottom: 24px;
}
.process-section.is-pinned .process-heading { margin-bottom: 20px; padding-top: 20px; }
/* Operator round 2026-09-06d: the left side returns to Astra's exact
   presentation — the 4:3 perspective study in its own column, the I–IV nav
   printed under it — with ONLY our pin + light-play kept on top of it.
   Selectors carry the #stages id so this pinned geometry also beats the
   (max-height: 780px) media block below on short laptop windows. */
.process-section.is-pinned .process-journey { align-items: stretch; }
/* The implicit grid row must OBEY the journey's imposed height instead of
   growing to the study's min-content (which pushed the canvas past the fold
   on short windows: row 612px inside a 409px journey at 1366x700). */
#stages.process-section.is-pinned .process-journey { grid-template-rows: minmax(0, 100%); }
#stages.process-section.is-pinned .process-study {
  min-height: 0;
  position: relative;
  top: auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
#stages.process-section.is-pinned .stage-object {
  flex: 0 1 auto;
  min-height: 0;
  width: 100%;
  aspect-ratio: 4 / 3;
  max-height: calc(100% - 64px);
}
#stages.process-section.is-pinned .process-steps {
  position: relative;
  height: 100%;
  overflow: hidden;
  padding-top: 0;
  /* the cut at the clip edges reads as a soft fade, not a hard crop */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
}
/* The light play: the active stage reads at full strength, the others recede. */
.process-section.is-pinned .process-step {
  opacity: .3;
  transition: opacity .5s var(--ease), border-color .5s var(--ease);
}
.process-section.is-pinned .process-step.is-active { opacity: 1; }

@media (min-width: 900px) and (max-height: 780px) {
  .process-journey.is-enhanced .process-study { top: 88px; }
  .process-journey.is-enhanced .stage-object { max-height: calc(100svh - 158px); aspect-ratio: 4 / 3; }
  .process-section.is-pinned .process-heading .section-title { font-size: clamp(30px, 3vw, 40px); }
}
@media (max-width: 1100px) {
  .process-journey { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 32px; }
  .process-step__heading { gap: 10px; grid-template-columns: 20px 1fr 24px; }
  .process-step__text { padding-left: 30px; }
}
@media (max-width: 899px) {
  #stages.process-section { padding-block: 48px 56px; }
  .process-heading { margin-bottom: 16px; gap: 16px; }
  .process-heading .rayburst { flex-basis: 48px; width: 48px; }
  .process-journey { display: block; }
  .process-study { max-width: 650px; margin: 0 auto 28px; }
  .process-steps { display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; }
  .process-step { padding-block: 24px 28px; }
  .process-step__text { padding-left: 0; }
}
@media (max-width: 540px) {
  .process-heading .section-title { font-size: 36px; }
  .process-heading .rayburst { display: none; }
  .process-study { margin-inline: -12px; margin-bottom: 20px; }
  .process-steps { display: block; }
  .process-step__text { font-size: 14px; }
  .process-step__name { font-size: 25px; }
}
@media (prefers-reduced-motion: reduce) {
  .process-journey.is-enhanced .process-study { position: relative; top: auto; }
}


/* ==========================================================================
   CREAM GROUND, TEXTURED (operator round 2026-09-06b)
   The one-day oxblood experiment is reverted: the canvas returns to the
   original cream WORKING PLATE palette, now carrying a PAPYRUS texture —
   two crossed fibre layers (anisotropic turbulence, warm and whisper-faint)
   plus the barely-there engraved symbol stencil, all inline SVG, fixed so
   every section scrolls over one continuous sheet. Also home to the MA_v2
   component styles and the round-12 bone-face cube fallback.
   ========================================================================== */
/* Round 2026-09-06d (operator): the blotting-paper mottle of round c is
   WITHDRAWN ("ça fait sale") — back to two layers. The symbol stencil
   returns to its subliminal 0.025 opacity but with 3x thicker strokes
   (2 -> 6): the geometry reads as broad soft engravings rather than
   fine lines. The round-c fibre strengthening (octave 4, .08/.065) is
   kept — that part IS the grunge. Round d also ends the dark themes'
   texture exemption: they now carry cream-ink variants of both layers
   (see the theme block near the end of this file) instead of a flat
   ground. */
body {
  background-color: var(--paper);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1100' height='1100' fill='none' stroke='%23171412' stroke-opacity='0.006' stroke-width='6'%3E%3Cg transform='rotate(8 250 290)'%3E%3Cpath d='M250 180 350 400H150Z'/%3E%3Cpath d='M195 330h110'/%3E%3C/g%3E%3Ccircle cx='790' cy='190' r='95'/%3E%3Ccircle cx='790' cy='190' r='6'/%3E%3Cg transform='rotate(168 920 660)'%3E%3Cpath d='M920 560 1020 760H820Z'/%3E%3C/g%3E%3Cg transform='translate(400 700) scale(1.15)'%3E%3Cpath d='M60 18a34 34 0 0 0 68 0'/%3E%3Ccircle cx='94' cy='84' r='34'/%3E%3Cpath d='M94 118v54M70 146h48'/%3E%3C/g%3E%3Cpath d='M180 990V800M180 990 120 830M180 990 60 880M180 990 240 830M180 990 300 880'/%3E%3Cg transform='rotate(-6 640 430)'%3E%3Crect x='560' y='350' width='160' height='160'/%3E%3Cpath d='M576 374h20'/%3E%3C/g%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='980'%20height='980'%20fill='none'%20stroke='%23C99B3F'%20stroke-opacity='0.13'%20stroke-width='1.2'%20stroke-linecap='round'%3E%3Cpath%20d='M212%2084V318'%20stroke-dasharray='5.5%205.5'/%3E%3Cpath%20d='M694%20596%20806%20708'%20stroke-dasharray='5%205.5'/%3E%3Cpath%20d='M446%20882H584'%20stroke-dasharray='5.5%205.5'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='7'%20height='7'%3E%3Cg%20fill='none'%20stroke-width='1.3'%20stroke-linecap='butt'%3E%3Cpath%20d='M-2%209%209%20-2M-5.5%205.5%205.5%20-5.5M1.5%2012.5%2012.5%201.5'%20stroke='%233A2B18'%20stroke-opacity='0.03'/%3E%3Cpath%20d='M-1.2%209.8%209.8%20-1.2M-4.7%206.3%206.3%20-4.7M2.3%2013.3%2013.3%202.3'%20stroke='%23FFFDF6'%20stroke-opacity='0.045'/%3E%3C/g%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='700'%20height='700'%3E%3Cfilter%20id='c'%20x='0'%20y='0'%20width='100%'%20height='100%'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.008'%20numOctaves='3'%20seed='5'%20stitchTiles='stitch'/%3E%3CfeColorMatrix%20type='matrix'%20values='0%200%200%200%200.42%200%200%200%200%200.33%200%200%200%200%200.2%200%200%200%200.04%200'/%3E%3C/filter%3E%3Crect%20width='700'%20height='700'%20filter='url(%23c)'/%3E%3C/svg%3E");
  background-attachment: fixed, fixed, fixed, fixed;
  background-size: 1100px 1100px, 980px 980px, 7px 7px, 700px 700px;
}
/* Alternating sections shade the shared sheet translucently so the papyrus
   fibres continue through them (visually equivalent to the old --paper-alt). */
.section--alt { background: rgba(90, 60, 20, .06); }

/* --- MA_v2 additions (component styles) --------------------------------- */

/* The 7th element: AlchAdemy — the house's own cell */
.el--al { --accent: var(--maroon); --tint: var(--maroon-tint); }

@media (max-width: 860px) {
  /* Narrow screens: two-up, families stacked in reading order; the lone
     7th cell centres under the table so it reads as its foot. */
  .ptable__grid { width: 100%; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .el--wk, .el--ex, .el--al, .ptable__family { grid-row: auto; grid-column: auto; }
  .ptable__family { grid-column: 1 / -1; }
  .el--al { grid-column: 1 / -1; width: calc(50% - var(--gap) / 2); margin: 0 auto; }
}

/* Stats strip (deck page 2) above the client logos */
.stat-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: 0 0 26px;
}
.stat-strip__cell {
  flex: 1 1 150px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  border: 1px solid var(--line);
  background: var(--card);
  padding: 14px 10px 12px;
}
/* Client call 2026-09-09 v4 (A1/SP): the topstitch — ONE fine gold thread
   sewn ON the frame line itself (v3's inset read as a second frame): the
   corner is the border, gone over again in gold. Framed plates only: the
   hero stat cells and the contact form plate. */
.stat-strip__cell, .contact__form { position: relative; }
/* Client pass 6: champagne gold vanished on the form plate's cream — its
   thread darkens to the engraved gold so the corners actually read. */
.contact__form { --stitch: #93641D; }
.stat-strip__cell::before,
.stat-strip__cell::after,
.contact__form::before,
.contact__form::after {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  border: 0 solid var(--stitch, #C9A45C);
  pointer-events: none;
}
.stat-strip__cell::before,
.contact__form::before { top: -1px; left: -1px; border-top-width: 1.5px; border-left-width: 1.5px; }
.stat-strip__cell::after,
.contact__form::after { bottom: -1px; right: -1px; border-bottom-width: 1.5px; border-right-width: 1.5px; }
/* Client pass 6: on the form plate (a much larger frame than a stat cell)
   the thread scales with it — longer arms, a touch heavier, engraved gold. */
.contact__form::before,
.contact__form::after { width: 24px; height: 24px; }
.contact__form::before { border-top-width: 2.5px; border-left-width: 2.5px; }
.contact__form::after { border-bottom-width: 2.5px; border-right-width: 2.5px; }
.stat-strip__num {
  /* Client 2026-09-07 (#4): the display face "ne va pas" on the figures —
     they switch to the body face, a quieter, more instrumental voice. The
     engraved gold (row 41) stays. */
  font-family: var(--font-body);
  font-weight: 650;
  font-size: 37px; /* Client call 2026-09-09 (A2): x1.5 — the frames were outsizing their text */
  letter-spacing: 0;
  color: #93641D;
  text-shadow: 0 -1px 1px rgba(23, 20, 18, .28), 0 1px 0 rgba(255, 255, 255, .8);
}
.stat-strip__label {
  font-size: 15px; /* Client call 2026-09-09 (A2): x1.5 with the figures */
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Craft plate metadata (deck craft cards): one engraved meta line per panel */
.craft-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 26px;
  margin: 16px 0 4px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.craft-meta__item { display: flex; gap: 8px; font-size: 12.5px; line-height: 1.5; }
.craft-meta dt {
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
}
.craft-meta dd { margin: 0; color: var(--ink-soft); }

/* The ten rules (deck pages 15–25) moved to manifesto.html (PAIRINGS row 26);
   About now carries the sealed entry plate (row 27) — see the manifesto
   section at the end of this file. The old .rules-grid/.rule-plate styles
   left with their markup. */

/* --- Round-12 BONE faces: the ::before skin and the engraved-span incision
   colours were folded back into the base .craft-face rules (BACKLOG 1.3);
   only the background-clip glint below still lives here, layered on the
   @supports fallback above it. --- */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .craft-face__sym {
    background-image: linear-gradient(157deg,
      color-mix(in srgb, var(--accent) 70%, #2A1A10) 0%,
      var(--accent) 40%,
      color-mix(in srgb, var(--accent) 70%, #fff) 52%,
      var(--accent) 64%,
      color-mix(in srgb, var(--accent) 60%, #2A1A10) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    text-shadow: none;
    filter: drop-shadow(0 1px 0 rgba(255, 252, 244, .5)) drop-shadow(0 -1px 0 rgba(74, 52, 30, .5));
  }
  .craft-face__num,
  .craft-face__name {
    background-image: linear-gradient(157deg,
      #7C674C 0%,
      #6E5C44 30%,
      color-mix(in srgb, var(--accent) 60%, #6E5C44) 55%,
      #7C6A50 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}
.craft-face__num {
  position: absolute;
  top: calc(var(--frame) + 10px);
  left: calc(var(--frame) + 12px);
  padding: 2px 6px;
  border: 1px solid rgba(74, 52, 30, .4);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13px;
}
.craft-face__glyph {
  position: absolute;
  right: calc(var(--frame) + 12px);
  bottom: calc(var(--frame) + 10px);
  width: 22px;
  height: 22px;
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, .10)) drop-shadow(0 -1px 0 rgba(0, 0, 0, .6));
  color: #8A7A62;
}

/* --- Operator round 2026-09-06c ------------------------------------------ */
/* The elemental table breathes: its section gets the wide container (the 4+3
   grid left ~250px for the detail panel in the 1180 box — far too tight).
   The panel's generous width moved into the base .ptable__panel rule
   (BACKLOG 1.3). */
.ptable-section > .container { max-width: 1360px; }
.ptable__panel-desc {
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-soft);
  text-wrap: pretty;
  max-width: none;
}


/* ==========================================================================
   About lexicon — round 2026-09-06e (operator)
   1. The plate rests GREY; the active term alone carries colour, through a
      soft spotlight window that glides with the focus point; engaging the
      plate darkens everything else further (still readable, just receded).
   2. Drifting alchemical mist + warm glow at rest invite the hand — no
      tooltip, no arrow; the mist clears the moment the visitor engages.
   3. The reader column keeps ONE height (the plate's): long definitions
      scroll inside their own area instead of pumping the page.
   4. The detail window frames the term via its hotspot extents (see
      lexicon-plate.js) and grew a little taller.
   ========================================================================== */
@property --focus-x { syntax: '<percentage>'; inherits: true; initial-value: 50%; }
@property --focus-y { syntax: '<percentage>'; inherits: true; initial-value: 46%; }
.lexicon-plate.is-enhanced .lexicon-plate__map {
  transition: --focus-x .5s var(--ease), --focus-y .5s var(--ease);
}

.lexicon-plate.is-enhanced:not(.is-image-unavailable) .lexicon-plate__image {
  filter: grayscale(.92) contrast(.97);
}
.lexicon-plate__veil,
.lexicon-plate__spotlight,
.lexicon-plate__mist { display: none; }
.lexicon-plate.is-enhanced:not(.is-image-unavailable) .lexicon-plate__veil,
.lexicon-plate.is-enhanced:not(.is-image-unavailable) .lexicon-plate__spotlight,
.lexicon-plate.is-enhanced:not(.is-image-unavailable) .lexicon-plate__mist { display: block; }

.lexicon-plate__veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: #171412;
  opacity: .05;
  transition: opacity .5s var(--ease);
}
.lexicon-plate__map:hover .lexicon-plate__veil { opacity: .34; }

.lexicon-plate__spotlight {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(ellipse 19% 26% at var(--focus-x) var(--focus-y), #000 46%, transparent 100%);
          mask-image: radial-gradient(ellipse 19% 26% at var(--focus-x) var(--focus-y), #000 46%, transparent 100%);
}
.lexicon-plate__spotlight-image {
  display: block;
  width: 100%;
  height: auto;
  mix-blend-mode: multiply;
  filter: saturate(1.15) contrast(1.04) brightness(1.05);
  transition: filter .5s var(--ease);
}
.lexicon-plate__map:hover .lexicon-plate__spotlight-image { filter: saturate(1.28) contrast(1.06) brightness(1.12); }

/* The mist: slow smoke and a breath of furnace warmth over the plate. */
.lexicon-plate__mist {
  position: absolute;
  inset: -4%;
  z-index: 2;
  pointer-events: none;
  overflow: hidden;
  opacity: .8;
  transition: opacity .6s var(--ease);
}
.lexicon-plate__map:hover .lexicon-plate__mist { opacity: .08; }
.lexicon-plate__mist::before,
.lexicon-plate__mist::after {
  content: "";
  position: absolute;
  inset: -30%;
  background:
    radial-gradient(38% 30% at 24% 68%, rgba(250, 247, 242, .5), transparent 70%),
    radial-gradient(30% 24% at 72% 30%, rgba(250, 247, 242, .38), transparent 70%),
    radial-gradient(26% 30% at 55% 78%, rgba(23, 20, 18, .14), transparent 70%);
  filter: blur(22px);
  animation: lexicon-mist-a 26s ease-in-out infinite alternate;
}
.lexicon-plate__mist::after {
  background:
    radial-gradient(32% 26% at 66% 64%, rgba(250, 247, 242, .42), transparent 70%),
    radial-gradient(24% 20% at 30% 26%, rgba(122, 36, 24, .10), transparent 70%),
    radial-gradient(30% 24% at 46% 44%, rgba(250, 247, 242, .3), transparent 72%);
  filter: blur(28px);
  animation: lexicon-mist-b 34s ease-in-out infinite alternate;
}
@keyframes lexicon-mist-a {
  from { transform: translate3d(-4%, 2%, 0) rotate(-2deg) scale(1); }
  50%  { transform: translate3d(3%, -3%, 0) rotate(1.5deg) scale(1.06); }
  to   { transform: translate3d(-2%, 3%, 0) rotate(-1deg) scale(1.02); }
}
@keyframes lexicon-mist-b {
  from { transform: translate3d(3%, -2%, 0) rotate(1deg) scale(1.04); }
  50%  { transform: translate3d(-3%, 2%, 0) rotate(-2deg) scale(1); }
  to   { transform: translate3d(2%, -3%, 0) rotate(2deg) scale(1.07); }
}

/* One constant reader height: the plate rules the row; a long definition
   scrolls in place instead of resizing the whole section. GRID layout only —
   below 801px the layout is block and the height-0 trick would collapse the
   reader to nothing (it swallowed the navigation under the next section). */
@media (min-width: 801px) {
  .lexicon-plate.is-enhanced .lexicon-plate__layout { align-items: stretch; }
  .lexicon-plate.is-enhanced .lexicon-plate__reader {
    height: 0;
    min-height: 100%;
    display: flex;
    flex-direction: column;
  }
  .lexicon-plate.is-enhanced .lexicon-plate__reading {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: thin;
  }
  .lexicon-plate.is-enhanced .lexicon-plate__navigation { margin-top: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .lexicon-plate__mist,
  .lexicon-plate__veil,
  .lexicon-plate__spotlight { display: none !important; }
  .lexicon-plate.is-enhanced:not(.is-image-unavailable) .lexicon-plate__image { filter: none; }
}

/* ==========================================================================
   The Secret Formula — manifesto page, sealed entry, footer exergue
   PAIRINGS.md rows 26–28 / BACKLOG.md §3 (2026-09-06)
   ========================================================================== */

/* --- Row 26: manifesto.html — ten scroll-snap screens, transmuting ink.
   The snap container is the document scroller itself; `proximity`, never
   `mandatory`, so a screen taller than the viewport can never trap scroll.
   Each screen's --mf-ink is a static step on the charcoal→maroon→ochre→gold
   ramp: the "transmutation" is the reader's own scroll, zero JS. --- */
html.page-manifesto { scroll-snap-type: y proximity; }

.manifesto__list { list-style: none; margin: 0; padding: 0; }
.manifesto__screen {
  min-height: 100vh;
  min-height: 100svh;
  scroll-snap-align: start;
  display: grid;
  align-items: center;
  justify-items: start;
  padding: 96px 0;
}
.manifesto__body {
  width: min(1040px, calc(100% - 48px));
  margin: 0 auto;
}
.manifesto__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(38px, 6vw, 72px);
  letter-spacing: -.02em;
  line-height: 1.05;
  margin: 10px 0 22px;
}
.manifesto__lead {
  color: var(--ink-soft);
  font-size: clamp(16px, 1.6vw, 19px);
  line-height: 1.65;
  max-width: 54ch;
}
.manifesto__hint {
  margin-top: 48px;
  font-size: 28px;
  color: var(--muted);
}
/* The numeral is engraved, not printed: the screen's ink at low opacity,
   oversized, sitting above the rule like a chapter plate. */
.manifesto__numeral {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(110px, 22vw, 260px);
  line-height: .9;
  letter-spacing: -.04em;
  color: var(--mf-ink, var(--ink));
  opacity: .16;
  user-select: none;
}
/* Client call 2026-09-09 (pass 9): "faut vraiment que ce soit impactant…
   c'est vraiment le titre, la Rule, qui doit être mis en avant." The rule
   name was reading as a modest subhead (58px ceiling) on a full-bleed,
   one-rule-per-screen page built to hold a single statement. It becomes the
   poster line the screen exists for; the body grows too so it's never
   thin against it, but at a smaller step — the SIZE GAP between the two
   widens on purpose, so the rule still reads as the thing being declared
   and the paragraph as the thing explaining it. */
.manifesto__rule {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(44px, 7.6vw, 118px);
  letter-spacing: -.028em;
  line-height: 1.02;
  color: var(--mf-ink, var(--ink));
  margin: 22px 0 30px;
}
/* Client pass 11 (2026-09-10): "les sauts de ligne sont sans logique". At this
   font size the OLD 13ch max-width + text-wrap:balance let the browser pick
   its own break points mid-phrase — but the real limiter was never that
   max-width, it was .manifesto__body's own 1040px cap (a 24-37 character
   title at 100px+ simply cannot fit inside it). Each rule's line breaks are
   now authored explicitly (<br> in the markup, at a comma where there is
   one); nowrap here stops the browser from adding any wrap of its own
   between them. A rule with no <br> (I, VI) renders on one line even if
   that overflows the 1040px column — html's site-wide `overflow-x: clip`
   (~L106) is the existing safety net, so this never creates a scrollbar. */
/* Desktop only. The nowrap above exists to stop the browser choosing its
   own break points on a title wider than the column — a desktop problem,
   because there the type is at the clamp ceiling. Below 900px the type is
   at its 44px floor and the column is narrow, so natural word wrapping is
   both needed and fine. Leaving nowrap on here CUT the longer rules off
   screen (measured: "Transmutation Takes Time" lost 76px at 375px, all
   three engines) — `.manifesto__body` is a grid item, and a grid item's
   `min-width: auto` resolves to min-content, so an unbreakable line
   widens the whole body past the viewport instead of being clipped.
   The authored <br>s still apply at every width. */
@media (min-width: 900px) {
  .manifesto__rule { white-space: nowrap; }
}
/* Client pass 12 (2026-09-10): "same size" as the other nine rules matters
   more than fitting the column, so this trades font-size for tracking.
   Real precedent for the exact problem (fixed space, long inscription, no
   size change allowed) is medal/seal engraving and manuscript titling: the
   lever is negative letter-spacing (tracking), not point size — the
   numeral behind each rule is already this site's own version of a fixed
   drop-cap anchor, sized the same on every screen regardless of the rule's
   length. Same principle applied here, tuned empirically against real
   render widths (1280-1920px), not guessed. */
.manifesto__rule--long { letter-spacing: -.04em; }
/* Rules II, III and VII clip their last word at common laptop widths
   (~1440px): the column is already at its 1040px ceiling but the margin
   either side is still tight there, and font-size (vw-based) is close to
   its own ceiling too — the one width band where neither side gives. A
   modest trim (not the drastic one --long needs) clears it everywhere. */
.manifesto__rule--trim { font-size: clamp(40px, 6.9vw, 104px); }
.manifesto__text {
  color: var(--ink-soft);
  font-size: clamp(17px, 2vw, 23px);
  line-height: 1.6;
  max-width: 62ch;
}
/* Rule X: the gold ramp of the Home sphere's finished state, clipped into the
   type (same primitive as the cube faces' glint); solid ochre fallback. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .manifesto__screen--gold .manifesto__rule {
    background-image: linear-gradient(157deg,
      #7A5216 0%, #93641D 34%, #C99B3F 48%, #E8C97A 55%, #C99B3F 64%, #93641D 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}
.manifesto__screen--close .manifesto__body { text-align: center; justify-self: center; }
.manifesto__colophon {
  color: var(--muted);
  font-size: 14px;
  letter-spacing: .08em;
  text-transform: uppercase;
  margin: 0 0 28px;
}
.manifesto__return a { color: var(--maroon); text-decoration: none; }
.manifesto__return a:hover { text-decoration: underline; }

/* --- Client pass 14 (2026-09-10): the manifesto moves onto the house
   oxblood ground (--maroon-dark, the Contact/footer red). The ink ramp in
   the markup flips with it — the rules used to transmute charcoal -> gold
   on cream; on oxblood they transmute cream -> gold instead, so the page
   still PERFORMS the metaphor, now as a light engraving warming into gold.
   The body sets .dark-hero, which the header already knows how to dress
   (paper wordmark/nav over a dark ground — same treatment as Home and
   Contact). Every reading surface is re-inked for the dark ground; the
   quietest tone used for body copy (#E4D2C2) measures ~9:1 on #59180F and
   the deepest ramp step (#DBAD62, rule IX) ~6.5:1 — both clear of the
   4.5:1 floor (DESIGN.md §7). `html.page-manifesto body` outranks the
   site-wide textured body rule by specificity, whatever their order. --- */
html.page-manifesto body { background: var(--maroon-dark); }
.manifesto .section-kicker { color: #DDB877; }
.manifesto__title { color: var(--paper); }
.manifesto__lead { color: #E4D2C2; }
.manifesto__hint { color: #C9AD97; }
.manifesto__text { color: #E4D2C2; }
.manifesto__colophon { color: #C9AD97; }
.manifesto__return a { color: #DDB877; }

/* --- Row 27: the sealed entry plate on About. One link, styled as the
   existing engraved-plate register; the wax disc carries the client's own
   alchemical seal mark (img/symbol-alchemy-seal.png, multiplied). --- */
.seal-plate {
  display: flex;
  align-items: center;
  gap: 34px;
  border: 1px solid var(--line);
  background: var(--card);
  padding: 40px 44px;
  text-decoration: none;
  color: inherit;
  transition: border-color var(--slow), box-shadow var(--slow);
}
.seal-plate:hover,
.seal-plate:focus-visible {
  /* Luxe pass: lift retired; the plate answers with a slow gold border. */
  border-color: #B67E46;
  box-shadow: 0 10px 30px -24px rgba(23, 20, 18, .3);
}
.seal-plate__wax {
  flex: 0 0 auto;
  width: 92px;
  height: 92px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #a03a28, var(--maroon) 55%, var(--maroon-dark));
  box-shadow:
    inset 0 2px 5px rgba(255, 252, 244, .28),
    inset 0 -3px 7px rgba(0, 0, 0, .35),
    0 3px 8px -3px rgba(23, 20, 18, .4);
  display: grid;
  place-items: center;
}
.seal-plate__wax img {
  width: 56px;
  height: auto;
  mix-blend-mode: multiply;
  opacity: .8;
  filter: contrast(1.2);
}
.seal-plate__name {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(21px, 2.4vw, 28px);
  letter-spacing: -.02em;
  margin: 0 0 8px;
}
.seal-plate__invite { display: block; color: var(--muted); font-size: 15px; margin: 0; }
.seal-plate__invite strong { color: var(--maroon); font-weight: 600; }
@media (max-width: 639px) {
  .seal-plate { flex-direction: column; text-align: center; padding: 32px 24px; }
}

/* --- Row 28: the footer exergue — one rule per visit (js/main.js swaps the
   static Rule X default), italic serif, signed, linking to the manifesto. --- */
.footer-exergue {
  margin: 0 0 18px;
  text-align: center;
}
/* Luxe round 4 (operator): the rule was set in parchment-era muted grey —
   near-invisible on the oxblood footer. Cream serif for the words, gold
   spaced caps for the attribution on its own line, a small gold star to
   mark it as a RULE of the house. */
.footer-exergue a {
  color: #E4D2C2;
  text-decoration: none;
}
.footer-exergue a:hover .footer-exergue__quote { color: #E8C97A; }
.footer-exergue__quote {
  font-family: Georgia, serif;
  font-style: italic;
  font-size: 17px;
  color: #F5EAE0;
  transition: color .2s var(--ease);
}
.footer-exergue__quote::before {
  content: '\2726';
  font-style: normal;
  font-size: 11px;
  color: #C99A56;
  margin-right: 10px;
  vertical-align: 2px;
}
.footer-exergue__sig {
  display: block;
  margin: 7px 0 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 10.5px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: #C99A56;
}

/* --- Luxe round row 34: the house seal. Gold engraved ring; sized for the
   footer's bottom block, larger on the manifesto's closing screen. --- */
/* The wrapper takes the full flex row (so the seal sits alone, centred,
   above the exergue/tagline line); the SVG itself is a plain fixed-size
   inline block — flex sizing never touches it. */
/* Operator 2026-09-08: the footer hallmark is WITHDRAWN (client: « le sceau,
   pas ouf ») — its row now carries the house exergue instead. "Iconic" is
   struck as the illustrated word: italic serif in the champagne engraving
   the hero accents wear on dark grounds. .maison-seal survives for the
   manifesto's in-page seal only. */
/* Client call 2026-09-11: « agrandir le Iconic en x2 [...] sans que ca fasse
   vulgaire ». At 42px inline the mark was a footnote beside the words. Doubled
   to 84px it can no longer sit ON the baseline without dwarfing the phrase, so
   the pair becomes a stacked SIGN-OFF: the sentence, then the mark under it as
   a signature. Bigger and calmer at once - the emphasis comes from the stack,
   not from shouting. */
.footer-iconic {
  flex-basis: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  text-align: center;
  margin: var(--sp-2) 0 var(--sp-6);
  font-family: var(--font-display);
  font-size: clamp(21px, 2.4vw, 28px);
  font-weight: 600;
  letter-spacing: .01em;
  color: #E4D2C2;
}
.footer-iconic__mark {
  /* The client's own ICONIC wordmark (extracted-assets, I-Co-Ni-C periodic
     tiles) — champagne on alpha for the oxblood footer; it had been
     withdrawn early on and the operator restores it here (2026-09-07).
     It replaces the WORD, so the alt carries it. */
  display: block;
  width: auto;
  /* x2 (42px -> 84px). The source is 253x79, so 84px is a 6% upscale -- still
     crisp at 2dppx (verified). It also gets a brightness lift: the bronze ink
     was sinking into the oxblood ground at any size. */
  height: 84px;
  max-width: 100%;
  margin: 0;
  filter: brightness(1.3) saturate(1.05);
}
@media (max-width: 560px) {
  .footer-iconic__mark { height: 62px; }
}
.maison-seal {
  display: inline-block;
  width: 118px;
  height: 118px;
  margin: 4px 0 22px;
  opacity: .92;
  background: linear-gradient(135deg,
    #7A5216 0%, #93641D 34%, #C99B3F 48%, #E8C97A 55%, #C99B3F 64%, #93641D 100%);
  -webkit-mask: url("../img/salamander-ma.png") no-repeat center / contain;
  mask: url("../img/salamander-ma.png") no-repeat center / contain;
}
/* Footer text sits on oxblood now (row 33): lift the muted copy to a warm
   readable cream. */
.site-footer__bottom { color: #C9AD97; }
.maison-seal--manifesto {
  width: 150px;
  height: 150px;
  margin: 0 0 30px;
}

/* --- The canonical contact form's honeypot (api/contact.js drops any
   submission that fills it). Visually removed, still in the DOM for bots. --- */
.field--website {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.contact__form .cta-note--form.is-error { color: var(--maroon); }

/* --- Services cube hint (coherence pass point 3, round 2): one line of
   interaction context, living INSIDE .craft-cube__intro (see services.html)
   so it inherits that block's own choreography — same idle position, same
   fade on data-phase="seq" — rather than an absolutely-positioned overlay
   fighting the pin's tuned vh-based layout for the same vertical space
   (round 1 of this fix overlapped the fixed header at scroll 0, then,
   repositioned, overlapped the intro's own kicker — both symptoms of the
   same mistake: competing with this block instead of joining it). */
.craft-cube__hint {
  margin: 10px 0 0;
  font-size: 13px;
  color: var(--muted);
}
/* The hint speaks of turning the die — only the gallery with a die has one.
   Every flat state (mobile, no-JS, reduced-motion) drops it. */
.craft-gallery:not(.has-die) .craft-cube__hint { display: none; }

/* ==========================================================================
   Client pass 15 (2026-09-10) — THE CRAFT GALLERY.
   Replaces the pinned scroll-driven cube sequence (PAIRINGS rows 16/42,
   retired): six full-height rooms in NORMAL document flow, gentle
   scroll-snap, all text readable at once. The die is a single sticky stage
   that idles under the intro, glides to the left rail as room 01 arrives,
   and turns toward the room being read (js/main.js drives the pose; the
   GLB mount in js/craft-cube-3d.js is unchanged). The die always appears
   fully formed — the flat cross-net fallback and the net-fold assembly are
   REMOVED at the client's explicit direction (an unfolded cube reads as a
   Latin cross; the house will not borrow that symbol). Without JS / below
   1200px / reduced motion: no die at all, just the rooms as plain cards.
   ========================================================================== */
/* Gentle snap, the Manifesto's own register (proximity never traps). Rooms
   opt in via scroll-snap-align; the rest of the page has no snap points. */
html.page-services { scroll-snap-type: y proximity; }

.craft-gallery { position: relative; }

/* The die rail: a zero-height sticky strip spanning intro + rooms. Sticky
   (not fixed) so it exists only while the gallery is on screen; height 0 so
   it takes no room of its own. Hidden until JS confirms the enhanced path. */
/* Client pass 16 (2026-09-10): position: sticky here refused to release once
   the gallery's own bottom scrolled past the viewport top — the die kept
   riding along into the sections below indefinitely ("ça n'a pas de sens").
   Root cause: this wrapper's own height is 0 (only its absolutely-positioned
   stage child has size), and a sticky element's exit bound is normally
   `container bottom − element height` — with height 0 that bound never
   actually arrives before the container itself is long gone, at least in
   the engines tested here. Rather than fight that, js/main.js now computes
   the equivalent clamped offset itself and writes it as `top` on this
   plain `position: absolute` box (containing block: .craft-gallery,
   position: relative) — same "sticks while the gallery is in view, then
   holds at its final position" behavior, but exact and deterministic:
   once scrolled level with the gallery's own end, `top` simply stops
   advancing, so the die stays put at its LAST position and scrolls away
   with the page like any other content — and resumes tracking the instant
   you scroll back up into the gallery's range. */
.craft-gallery__die {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 0;
  z-index: 5;
  display: none;
}
.craft-gallery.has-die .craft-gallery__die { display: block; }

.craft-gallery__die .craft-cube__model-stage {
  --die: 170px;
  position: absolute;
  top: 0;
  left: 0;
  width: var(--die);
  height: var(--die);
  cursor: grab;
  touch-action: pan-y;
  /* js/main.js writes the inline `translate` each scroll frame: undocked it
     tracks the in-flow .craft-gallery__parking spot under the intro copy
     (so no viewport height can ever push it into the text), docked it
     targets the left rail. This one transition IS the glide — continuous
     retargeting through it gives the die a soft pursuit at every move. */
  transition: translate .9s var(--ease);
}
.craft-gallery__die .craft-cube__model-stage:focus-visible {
  outline: 2px solid var(--maroon);
  outline-offset: 6px;
}
.craft-gallery.is-dragging .craft-cube__model-stage { cursor: grabbing; }
/* The undocked die's in-flow seat: real space below the intro copy. */
.craft-gallery__parking { height: 170px; margin-top: var(--sp-7); }
/* The GLB canvas extends past the stage box (a rotating cube's projected
   extent grows to its bounding sphere — clipped at the box, corners were
   visibly cut mid-turn; js/craft-cube-3d.js's camera radius compensates so
   the FACE keeps the stage-box size on screen). The old rules carrying this
   were keyed on .is-live, which the gallery never sets — ported here. */
.craft-gallery.has-die .craft-cube__model {
  position: absolute;
  inset: -50%;
  display: block;
  pointer-events: none;
}
.craft-gallery.has-die .craft-cube__model canvas { display: block; width: 100%; height: 100%; }
.craft-gallery.has-die .craft-cube__model model-viewer {
  display: block;
  width: 100%;
  height: 100%;
  background: transparent;
  --poster-color: transparent;
}

/* The intro is its own antechamber: one calm screen, text centred, the die
   idling below it (the 34vh of bottom padding is the die's parking spot). */
.craft-gallery.has-die .craft-gallery__intro {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin-bottom: 0;
  /* top: the fixed header's clearance (centred content was sliding the
     title under it); the parking element supplies the bottom room. */
  padding-top: 110px;
  padding-bottom: 8vh;
  box-sizing: border-box;
  scroll-snap-align: start;
}

/* Rooms: one discipline per screen-height, content vertically centred,
   normal scrolling. min-height (not height) — a long room simply grows and
   proximity snap never traps it. */
.craft-gallery__rooms .craft-chapter {
  scroll-snap-align: start;
}
.craft-gallery.has-die .craft-gallery__rooms .craft-chapter {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  box-sizing: border-box;
  padding-top: 86px;   /* the fixed header's clearance at a snap stop */
  padding-bottom: 48px;
  /* the rail: text never runs under the die */
  margin-left: 240px;
  border-top: none;    /* the room IS the division; the card border-top
                          accent moves to the name plate below */
  background: transparent;
}
/* The engraved plate register inside a room: the periodic identity leads,
   the accent underlines the name, the copy sits at a comfortable measure. */
.craft-gallery.has-die .craft-chapter .discipline-card__name {
  border-bottom: 3px solid var(--accent);
  padding-bottom: 14px;
  max-width: 21ch;
}
.craft-gallery.has-die .craft-chapter .discipline-card__copy { max-width: 66ch; }
.craft-gallery.has-die .craft-chapter .craft-meta { max-width: 760px; }
/* The included list in the calm two-column register the operator approved
   for the old live mode (« l'arborescence, ça fonctionne pas ») — multicol
   so items read down each column in source order. */
.craft-gallery.has-die .craft-chapter .cheminement {
  --o-step: 0px;
  column-count: 2;
  column-gap: 44px;
  max-width: 980px;
  margin-top: 18px;
}
.craft-gallery.has-die .craft-chapter .cheminement__step {
  break-inside: avoid;
  margin-left: 0;
}
.craft-gallery.has-die .craft-chapter .cheminement__link { display: none; }

/* Without the die (narrow / reduced motion / no JS), the rooms are plain
   stacked cards — the discipline-card base styles as they are. Give them
   the section's rhythm back. */
.craft-gallery:not(.has-die) .craft-gallery__rooms { display: grid; gap: var(--sp-6); }

/* Row 47c - the cloth on touch devices: iOS Safari degrades fixed attachment
   (the drape jumps or tears). The sheet travels with the page there instead;
   same tiles, same geometry, the gold seams recur every 980px of scroll. */
@media (hover: none) and (pointer: coarse) {
  body {
    background-attachment: scroll, scroll, scroll, scroll;
  }
}

/* ==========================================================================
   Row 41 (luxe batch, operator-arbitrated 2026-09-07)
   1. Services' closing statement joins the oxblood+gold house moments.
   3. The lexicon plate's instruments turn gold (the needle, not the frame).
   4. The form CTA keeps its maroon — a different voice than the hero's
      champagne — but learns the same slow manners and reveals a hairline
      of gold on hover.
   ========================================================================== */
/* --- 1. Services closing band --- */
.hero-services {
  background-color: #4E1913;
  background-image:
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='980'%20height='980'%20fill='none'%20stroke='%23C99B3F'%20stroke-opacity='0.16'%20stroke-width='1.2'%20stroke-linecap='round'%3E%3Cpath%20d='M212%2084V318'%20stroke-dasharray='5.5%205.5'/%3E%3Cpath%20d='M694%20596%20806%20708'%20stroke-dasharray='5%205.5'/%3E%3Cpath%20d='M446%20882H584'%20stroke-dasharray='5.5%205.5'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='7'%20height='7'%3E%3Cg%20fill='none'%20stroke-width='1.3'%20stroke-linecap='butt'%3E%3Cpath%20d='M-2%209%209%20-2M-5.5%205.5%205.5%20-5.5M1.5%2012.5%2012.5%201.5'%20stroke='%23FAF7F2'%20stroke-opacity='0.026'/%3E%3Cpath%20d='M-1.2%209.8%209.8%20-1.2M-4.7%206.3%206.3%20-4.7M2.3%2013.3%2013.3%202.3'%20stroke='%23000000'%20stroke-opacity='0.012'/%3E%3C/g%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='700'%20height='700'%3E%3Cfilter%20id='c'%20x='0'%20y='0'%20width='100%'%20height='100%'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.008'%20numOctaves='3'%20seed='5'%20stitchTiles='stitch'/%3E%3CfeColorMatrix%20type='matrix'%20values='0%200%200%200%200.98%200%200%200%200%200.95%200%200%200%200%200.88%200%200%200%200.032%200'/%3E%3C/filter%3E%3Crect%20width='700'%20height='700'%20filter='url(%23c)'/%3E%3C/svg%3E");
  background-size: 980px 980px, 7px 7px, 700px 700px;
  border-top: 4px double #B67E46;
}
.hero-services .section-kicker { color: #C9AD97; }
.hero-services .section-title { color: #F5EAE0; }
.hero-services .section-lead { color: #E4D2C2; }
.hero-services__glyph { color: #F5EAE0; }
.hero-services .btn--primary { background: #C9A45C; border-color: #C9A45C; color: #35200C; font-size: 13px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; }
.hero-services .btn--primary:hover { background: #D8B876; border-color: #D8B876; letter-spacing: .18em; }

/* --- 3. Lexicon instruments in gold --- */
.lexicon-plate__index { color: #B67E46; }
.lexicon-plate__focus-frame { color: #B67E46; }
.lexicon-plate__marker { transition: background var(--slow), border-color var(--slow), color var(--slow); }
.lexicon-plate__hotspot.is-active .lexicon-plate__marker,
.lexicon-plate__hotspot:hover .lexicon-plate__marker,
.lexicon-plate__hotspot:focus-visible .lexicon-plate__marker {
  background: #B67E46;
  border-color: #B67E46;
  color: #FFFDF8;
}
.lexicon-plate__magnify[aria-pressed="true"] { color: #B67E46; }

/* --- 4. Form CTA: maroon voice, slow manners, a hairline of gold --- */
.contact__form .btn--primary {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  box-shadow: inset 0 0 0 1px rgba(182, 126, 70, 0);
  transition: background var(--slow), box-shadow var(--slow), letter-spacing var(--slow);
}
.contact__form .btn--primary:hover {
  background: var(--maroon-dark);
  border-color: var(--maroon-dark);
  letter-spacing: .18em;
  box-shadow: inset 0 0 0 1px #B67E46;
}
/* Services atelier, PAIRINGS 42. All overrides require the enhancement gate;
   the original flowing articles remain the narrow/no-motion/no-JS design. */
.craft-cube.is-live.is-atelier[data-phase="seq"] { --cube-size: var(--atelier-cube-size); }
.craft-cube.is-live.is-atelier[data-phase="seq"] .craft-cube__stage {
  transform: translate(-50%, -50%) translate(calc(var(--atelier-cube-x) - 50vw), calc(var(--atelier-cube-y) - 50vh));
}
.craft-cube.is-live.is-atelier .craft-cube__panels {
  inset: 0;
  width: 100%;
  height: 100%;
  transform: none;
  display: block;
  transition: opacity .35s var(--ease);
}
.craft-cube.is-live.is-atelier .craft-panel {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: visible;
  transform: none;
  transition: none;
  pointer-events: none;
}
.craft-cube.is-live.is-atelier .atelier-heading {
  position: absolute;
  left: var(--atelier-left);
  top: var(--atelier-top);
  width: var(--atelier-width);
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
.craft-cube.is-live.is-atelier .atelier-heading .discipline-card__num {
  display: block;
  position: static;
  margin: 0 0 9px;
  font-size: 12px;
  line-height: 1.3;
  letter-spacing: .1em;
  color: var(--accent);
}
.craft-cube.is-live.is-atelier .atelier-heading .discipline-card__name {
  margin: 0;
  font-size: clamp(28px, 2.3vw, 36px);
  line-height: 1.16;
  font-weight: 500;
  letter-spacing: -.025em;
}
.craft-cube.is-live.is-atelier .atelier-frame {
  position: absolute;
  left: var(--atelier-right);
  top: var(--atelier-reading-top);
  width: var(--atelier-right-width);
  height: var(--atelier-full-height);
  overflow: clip;
  opacity: 0;
  pointer-events: none;
}
/* A reading taller than its window travels through it; dissolve the rows at
   the window edges instead of slicing glyphs on the clip line. Applied by
   craft-atelier.js only where there is actual overflow. */
.craft-cube.is-live.is-atelier .atelier-frame--windowed {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 18px, #000 calc(100% - 18px), transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 18px, #000 calc(100% - 18px), transparent 100%);
}
.craft-cube.is-live.is-atelier .atelier-frame--notice { height: var(--atelier-body-height); }
.craft-cube.is-live.is-atelier .atelier-frame--spread {
  left: var(--atelier-left);
  top: var(--atelier-floor);
  width: var(--atelier-width);
  height: var(--atelier-lower-height);
}
.craft-cube.is-live.is-atelier .atelier-reading { padding: 1px 0 12px; }
.craft-cube.is-live.is-atelier .discipline-card__hook {
  margin: 0 0 24px;
  font-size: clamp(19px, 1.45vw, 23px);
  line-height: 1.4;
  font-weight: 500;
}
.craft-cube.is-live.is-atelier .discipline-card__copy,
.craft-cube.is-live.is-atelier .discipline-card__note {
  font-size: 16px;
  line-height: 1.65;
}
.craft-cube.is-live.is-atelier .discipline-card__program-tag {
  margin: 0 0 18px;
  max-width: 54ch;
  font-size: 11px;
  line-height: 1.6;
}
.craft-cube.is-live.is-atelier .craft-meta {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px 24px;
  margin: 0 0 24px;
  padding: 17px 0;
  border-color: var(--line);
}
.craft-cube.is-live.is-atelier .craft-meta__item { display: block; }
.craft-cube.is-live.is-atelier .craft-meta dt { margin: 0 0 4px; font-size: 10px; letter-spacing: .12em; }
.craft-cube.is-live.is-atelier .craft-meta dd { margin: 0; font-size: 13px; line-height: 1.5; }
.craft-cube.is-live.is-atelier .discipline-card__included-label {
  margin: 0 0 20px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  line-height: 1.4;
  font-weight: 500;
  letter-spacing: .13em;
}
.craft-cube.is-live.is-atelier .atelier-list {
  margin: 0;
  padding: 0;
  column-count: 2;
  column-gap: 32px;
  list-style: none;
}
.craft-cube.is-live.is-atelier .atelier-frame--spread .atelier-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-count: auto;
  gap: 32px;
}
.craft-cube.is-live.is-atelier .atelier-list .cheminement__step {
  display: block;
  position: relative;
  margin: 0 0 22px;
  padding: 0 0 0 21px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--muted);
  break-inside: avoid;
}
.craft-cube.is-live.is-atelier .atelier-list .cheminement__step + .cheminement__step { margin-top: 0; }
.craft-cube.is-live.is-atelier .atelier-list .cheminement__text { display: block; padding: 0; }
.craft-cube.is-live.is-atelier .atelier-list .cheminement__node,
.craft-cube.is-live.is-atelier .atelier-list .cheminement__link,
.craft-cube.is-live.is-atelier .atelier-list .cheminement__index { display: none; }
.craft-cube.is-live.is-atelier .disclaimer { margin: 28px 0 0; font-size: 13px; line-height: 1.7; }

/* --- Row 42 luxe (operator, on the recovered worktree): the atelier takes
   the die's own metal. Chapter titles are struck in the same engraved-gold
   family as the die's glyphs and Rule X; meta labels and the included-label
   turn dark gold; every included item is led by a small gold star. --- */
.craft-cube.is-live.is-atelier .atelier-heading {
  border-bottom: 3px double #C9A45C;
}
.craft-cube.is-live.is-atelier .atelier-heading .discipline-card__name {
  background-image: linear-gradient(163deg, #8A5E1F 0%, #C99B3F 42%, #E3C27A 52%, #A5761F 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 1px 0 rgba(255, 250, 238, .45)) drop-shadow(0 -1px 1px rgba(23, 20, 18, .26));
}
/* Row 42 v3 (operator): each chapter title is struck in ITS face's metal —
   the panel's own --accent (the same token that colours the die glyph),
   run through the engraved ramp: dark edge, brightened body, light sheen
   band, dark tail. The gold ramp above stays as the pre-color-mix fallback. */
@supports (color: color-mix(in srgb, red 50%, blue)) {
  .craft-cube.is-live.is-atelier .atelier-heading .discipline-card__name {
    background-image: linear-gradient(163deg,
      color-mix(in srgb, var(--accent), #171412 38%) 0%,
      color-mix(in srgb, var(--accent), #FFF6E6 16%) 42%,
      color-mix(in srgb, var(--accent), #FFF6E6 55%) 52%,
      color-mix(in srgb, var(--accent), #171412 22%) 100%);
  }
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .craft-cube.is-live.is-atelier .atelier-heading .discipline-card__name { color: var(--accent, #93641D); filter: none; }
}
.craft-cube.is-live.is-atelier .craft-meta dt { color: #93641D; }
.craft-cube.is-live.is-atelier .discipline-card__included-label {
  color: #93641D;
  border-top-color: #C9A45C;
}
.craft-cube.is-live.is-atelier .atelier-list .cheminement__step::before {
  content: '\2726';
  position: absolute;
  left: 0;
  top: 5px;
  color: #B67E46;
  font-size: 10px;
}
/* Row 42 v4 (operator): the included items must not be missable — each one
   leads with its key value term, struck as an engraved spec-sheet head
   (display face, ink, letterpress), with the qualifier reading quietly
   beneath it. The <strong> marks are editorial, set in services.html —
   the same pattern the Workshops list already used. */
.craft-cube.is-live.is-atelier .atelier-list .cheminement__text strong {
  display: block;
  margin: 0 0 3px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 16px;
  line-height: 1.35;
  letter-spacing: .012em;
  color: var(--ink);
  text-shadow: 0 1px 0 rgba(255, 255, 255, .8), 0 -1px 1px rgba(23, 20, 18, .18);
}

/* ==========================================================================
   Client feedback batch, 2026-09-07 (docs/feedback/RETOURS-2026-09-07.md)
   ========================================================================== */
/* #3 — the proof figures close the hero's first screen, on the oxblood. */
.hero .stat-strip { margin: 46px 0 0; }
.hero .stat-strip__cell {
  background: rgba(250, 247, 242, .05);
  border-color: rgba(201, 164, 92, .38);
}
.hero .stat-strip__num {
  color: #DDB877;
  text-shadow: 0 -1px 1px rgba(0, 0, 0, .4), 0 1px 0 rgba(255, 244, 224, .12);
}
.hero .stat-strip__label { color: #C9AD97; }

/* #7 — the classification blocks: values step forward in ink, labels stay
   the quiet gray voice; the client keeps the classification idea. */
.craft-meta dd { color: var(--ink); font-weight: 500; }

/* #12/#20 — the founders' quote takes the full width of the page and sits
   lower, a proper interlude rather than a card in the column. */
.founder-quote {
  margin: var(--sp-8) calc(50% - 50vw) 0;
  padding-inline: clamp(28px, 8vw, 140px);
}
.founder-quote p, .founder-quote footer { max-width: 1160px; margin-inline: auto; }
.founder-quote footer { margin-top: var(--sp-5); }

/* #9/#13 - About and AlchAdemy used to run on their own 76px scale, which is
   why their rhythm disagreed with every other page. The Fibonacci ladder is
   now the single scale; .page-tight keeps only its tighter section head. */
.page-tight .section-head { margin-bottom: var(--sp-6); }
/* A .section-head with nothing after it inside its container has nothing to be
   separated FROM: its 55px tail (34px on .page-tight) simply stacked onto the
   section's own bottom padding. Three sections on the site were in that state
   - About "Where We Work", the About CTA, the Services close. Declared after
   .page-tight so it wins on both scales. */
.section-head:last-child { margin-bottom: 0; }

/* #10/#11 — founder identity under the portrait: name (FAMILY NAME in caps
   in the HTML), then role, both aligned to the plate. */
/* Client call 2026-09-09 (AB3/AB4): the plate under the portrait sits centred,
   and the name + title step up so the person reads before the résumé. */
.founder__ident { display: flex; flex-direction: column; align-items: center; text-align: center; }
.founder__ident h3 {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 600;
  line-height: 1.3;
  margin: 16px 0 0;
}
.founder__ident .founder__title {
  display: block;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 400;
  color: var(--muted);
  margin-top: 5px;
}
/* Client call 2026-09-09 (AB1): "The Al(Chemist)" / the founders' epithets in
   gold — bold enough to catch, still an aside. */
.founder__title em { font-weight: 650; color: #93641D; }
@media (max-width: 900px) {
  .founder__ident { max-width: 220px; }
}

/* #18 — AlchAdemy's engraved athanor fills the empty right of the opening
   plate. House hairline language, decor only. */
.section-head { position: relative; }
.academy-emblem {
  position: absolute;
  right: 0;
  top: 24px;
  width: 320px;
  opacity: .26;
  pointer-events: none;
}
.academy-emblem img { width: 100%; height: auto; }
/* Row 47d — the client's engraving keeps a seat on small screens: a quiet
   centred plate above the credentials instead of the desktop margin cut. */
@media (max-width: 1080px) {
  .academy-emblem {
    position: static;
    width: min(420px, 78%);
    /* Row 47 v2 (operator): clear air between the engraving and the
       credential plates below it. */
    margin: 12px auto 32px;
    opacity: .32;
  }
}

/* --- Row 46 (operator 2026-09-07): « Start a Reaction » starts one. A
   champagne reaction front propagates from the exact point the pointer
   touches the button, a luminous rim leading the reacted body by a beat;
   on leave the front recedes to the exit point. Meaning over fashion: the
   label is the effect. No-JS keeps the plain fills above. --- */
.btn-react { position: relative; overflow: hidden; isolation: isolate; }
.btn-react::before,
.btn-react::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  clip-path: circle(0% at var(--rx, 50%) var(--ry, 50%));
  transition: clip-path .55s var(--ease);
}
.btn-react::after { z-index: -2; background: #E8CD8C; transition-duration: .48s; }
.btn-react::before { z-index: -1; background: #C9A45C; transition-delay: .07s; }
.btn-react.is-reacting::before,
.btn-react.is-reacting::after { clip-path: circle(135% at var(--rx, 50%) var(--ry, 50%)); }
.main-nav__cta.btn-react { transition: color .3s var(--ease) .1s, border-color .45s var(--ease); }
.main-nav__cta.is-reacting,
body.dark-hero .main-nav__cta.is-reacting { color: #35200C !important; border-color: #C9A45C; }
.mobile-cta.is-reacting { color: #35200C; }
/* Row 47b — the tap version: the front must complete inside the short
   tap-to-navigation window, so coarse pointers propagate faster. */
@media (pointer: coarse) {
  .btn-react::after { transition-duration: .24s; }
  .btn-react::before { transition-duration: .3s; transition-delay: .04s; }
}

/* Row 42 v5 — the conveyor's column station: the included content's final
   seat, same geometry the base .atelier-frame already carries (right
   column, full-height window); its list reads as ONE column here. */
.craft-cube.is-live.is-atelier .atelier-frame--column { height: var(--atelier-body-height); }
.craft-cube.is-live.is-atelier .atelier-frame--column .atelier-list { column-count: 1; }
.craft-cube.is-live.is-atelier .atelier-frame--column .discipline-card__included-label { margin: 26px 0 16px; }
