/* =================================================================
   MaxPilates — site.css
   Palette: warm charcoal + wood/beige. Sharp corners, no radius.
   ================================================================= */

:root {
  --c-ink:        #12100e;   /* near-black, warm undertone */
  --c-ink-2:      #1e1a16;   /* elevated dark surfaces */
  --c-ink-3:      #2a2420;   /* borders on dark */
  --c-cream:      #f6efe2;   /* off-white paper */
  --c-cream-2:    #ede2cc;   /* soft beige surface */
  --c-sand:       #c9b18e;   /* mid beige */
  --c-wood:       #a07a52;   /* wood accent (buttons, hover) */
  --c-wood-dk:    #7a5a3b;   /* wood pressed */
  --c-line:       rgba(246,239,226,.14);

  --f-serif:      "Cormorant Garamond", "EB Garamond", "Times New Roman", serif;
  --f-sans:       "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* === MOTION TUNING ==================================================
     --tr-med is the card hover (title lift + panel slide + scrim).
     --tr-slow is the image zoom on hover + scroll parallax easing.
     Suggested ranges (slower = softer, more editorial):
       --tr-fast : 200–320ms  (nav underline, small hovers)
       --tr-med  : 500–900ms  (card hover reveal)  — sweet spot ~700–800
       --tr-slow : 800–1400ms (image zoom / large surfaces)
     Easing: (.22,.7,.2,1) is a gentle "ease-out"; try (.16,.84,.44,1) for
     a softer, more luxurious feel, or (.4,0,.2,1) for a sharper snap.
     ==================================================================== */
  --tr-fast: 280ms cubic-bezier(.22,.7,.2,1);        /* prev: 260 → 220ms */
  --tr-med:  700ms cubic-bezier(.16,.84,.44,1);      /* prev: 1100ms (felt ~2.4s incl. ease-out tail); now feels ~1.5s */
  --tr-slow: 1000ms cubic-bezier(.16,.84,.44,1);     /* prev: 1400ms */

  --nav-h: 72px;
}

/* ---------- Base ---------- */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Every anchor jump (#section, /page#id, Sommario TOC, /corsi#slug…) has
     to clear the fixed nav — otherwise the target lands under it. One line,
     covers every current and future anchor site-wide.
     Previously `nav-h + 20px` breather — that left a 20px sliver of the
     preceding section peeking above the target, most visible on the home
     `#corsi` jump. Snapped flush to the nav bottom now; the target section's
     own top padding (`.section { padding: clamp(80px, 10vw, 140px) ... }`)
     provides all the breathing room needed. */
  scroll-padding-top: var(--nav-h);
  /* Always reserve room for the scrollbar so opening a modal that locks
     body scroll (course-detail overlay, mobile burger, lightbox) doesn't
     shift the page horizontally when the vertical scrollbar disappears.
     `stable` reserves the gutter unconditionally; supported everywhere
     modern (Chromium 94+, Firefox 97+, Safari 16+). */
  scrollbar-gutter: stable;
}
body {
  font-family: var(--f-sans);
  color: var(--c-ink);
  background: var(--c-cream);
  line-height: 1.6;
  font-size: 17px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
a:hover { color: var(--c-wood); }
h1,h2,h3,h4 { font-family: var(--f-serif); font-weight: 500; margin: 0; letter-spacing: -.005em; }
button { font: inherit; cursor: pointer; }
::selection { background: var(--c-wood); color: var(--c-cream); }

/* skip link */
.sr-only { position: absolute; left: -9999px; }

/* ---------- Nav ---------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  height: var(--nav-h);
  transition: background var(--tr-med), border-color var(--tr-med), box-shadow var(--tr-med);
  border-bottom: 1px solid transparent;
}
.nav__inner {
  max-width: 1440px; margin: 0 auto; height: 100%;
  padding: 0 clamp(20px, 4vw, 48px);
  display: flex; align-items: center; gap: 24px;
}
.nav__brand {
  color: #fff;
  display: inline-flex; align-items: center;
  transition: color var(--tr-med);
  position: relative;         /* the two <img> variants stack absolutely below */
  height: 46px;                /* fixed frame so the absolute children have space */
  min-width: 230px;            /* matches the img's intrinsic width */
}
/* Single-file client logo (horizontal PNG). White + black variants stack
   in the same slot; CSS toggles which is visible based on nav state + theme.
   Width/height match the <img> intrinsic to avoid layout shift on first paint. */
.nav__logo {
  display: block;
  height: 45px; width: auto;
  flex: 0 0 auto;
}
.nav__logo--black { position: absolute; inset: 0; }
/* Default: dark nav bg → show WHITE logo, hide BLACK. Solid/light-theme nav
   overrides further below invert this via display: none swaps. */
.nav__logo--black { display: none; }
.nav__links {
  margin-left: auto;
  display: flex; gap: clamp(18px, 2.6vw, 36px);
}
.nav__links a {
  color: #fff;
  font-size: 13.5px; letter-spacing: .18em; text-transform: uppercase;
  padding: 8px 0;
  position: relative;
  transition: color var(--tr-fast);
}
.nav__links a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 2px; height: 1px;
  background: var(--c-sand);
  transition: right var(--tr-med);
}
.nav__links a:hover { color: var(--c-sand); }
.nav__links a:hover::after { right: 0; }
/* Active section — sand-colored label with a persistent underline. */
.nav__links a.is-active { color: var(--c-sand); }
.nav__links a.is-active::after { right: 0; }
.nav__cta {
  color: #fff;
  border: 0;
  /* Padding bumped by the 1px each side that the removed border no longer
     occupies — button silhouette stays the same on hover-fill. */
  padding: 11px 19px;
  font-size: 12.5px; letter-spacing: .22em; text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 10px;
  transition: background var(--tr-fast), color var(--tr-fast);
}
.nav__cta .ico { width: 16px; height: 16px; }
.nav__cta:hover {
  background: #fff; color: var(--c-ink);
}

/* Theme toggle — sun visible in dark theme, moon in light.
   Border removed to match the borderless CTA; the hover tint still gives
   feedback without needing an outline. */
.nav__theme {
  background: transparent;
  border: 0;
  color: #fff;
  width: 38px; height: 38px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
  transition: background var(--tr-fast), color var(--tr-fast);
}
.nav__theme:hover { background: rgba(255,255,255,.14); }
.nav__theme .theme-ico { width: 18px; height: 18px; }
.nav__theme .theme-ico--moon { display: none; }
:root[data-theme="light"] .nav__theme .theme-ico--sun  { display: none; }
:root[data-theme="light"] .nav__theme .theme-ico--moon { display: block; }
.nav__burger {
  display: none; background: transparent; border: 0; padding: 8px;
  width: 40px; height: 40px; flex-direction: column; gap: 5px; align-items: stretch; justify-content: center;
}
.nav__burger span { display: block; height: 2px; background: #fff; transition: transform var(--tr-fast), opacity var(--tr-fast); }

/* Solid nav after scroll, on pages without a hero (.nav--solid), and while
   the course-detail overlay is open (avoids the h2 peek-through). */
.nav.is-scrolled,
.nav.nav--solid,
body.cdet-open .nav {
  background: rgba(18,16,14,.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom-color: var(--c-line);
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  color: #fff;
  /* Content sits near the bottom of the viewport instead of centered. */
  display: flex; align-items: flex-end;
  overflow: hidden;
  isolation: isolate;
}
.hero__media {
  position: absolute; inset: 0; z-index: -2;
  will-change: transform;
}
.hero__media img {
  width: 100%; height: 100%; object-fit: cover; object-position: center 40%;
  /* Cosmetic protection only — blocks casual right-click "Save image as" and
     drag-select. Not a security measure (image is still in the network tab).
     `pointer-events: none` disables the context menu because the event never
     reaches the image; user-select + -webkit-user-drag stop text/drag select. */
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(18,16,14,.55) 0%, rgba(18,16,14,.05) 32%, rgba(18,16,14,.36) 100%),
    linear-gradient(90deg,  rgba(18,16,14,.55) 0%, rgba(18,16,14,0)   55%);
}
.hero__inner {
  max-width: 1440px; margin: 0 auto;
  /* Small bottom padding so text almost sits on the viewport floor,
     leaving room only for the "scroll down" chevron below. */
  padding: 0 clamp(20px, 4vw, 48px) 80px;
  width: 100%;
}
.hero__eyebrow {
  margin: 0 0 24px;
  font-size: 12.5px; letter-spacing: .32em; text-transform: uppercase;
  color: var(--c-cream);
  display: inline-flex; align-items: center; gap: 14px;
}
.hero__eyebrow::before {
  content: ""; width: 42px; height: 1px; background: var(--c-cream);
}
.hero__title {
  /* Prev: clamp(44px, 7.2vw, 96px) — reduced for a calmer, more elegant feel. */
  font-size: clamp(36px, 5vw, 68px);
  line-height: 1.05;
  margin: 0 0 22px;
  max-width: 22ch;
  font-weight: 400;
}
.hero__lead {
  font-size: clamp(16px, 1.4vw, 19px);
  max-width: 58ch;
  color: rgba(255,255,255,.85);
  margin: 0 0 40px;
}
.hero__ctas { display: flex; gap: 14px; flex-wrap: wrap; }
.hero__scroll {
  position: absolute; left: 50%; bottom: 28px;
  transform: translateX(-50%);
  color: rgba(255,255,255,.75);
  padding: 8px;
  animation: bob 2.6s ease-in-out infinite;
}
.hero__scroll:hover { color: #fff; }
@keyframes bob {
  0%, 100% { transform: translate(-50%, 0); }
  50%      { transform: translate(-50%, 8px); }
}

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  padding: 15px 20px;
  font-size: 13px; letter-spacing: .22em; text-transform: uppercase;
  border: 1px solid transparent;
  transition: background var(--tr-fast), color var(--tr-fast), border-color var(--tr-fast), transform var(--tr-fast);
}
.btn .ico { width: 18px; height: 18px; flex: 0 0 auto; }
.btn--primary {
  background: var(--c-cream); color: var(--c-ink);
  border-color: var(--c-cream);
}
.btn--primary:hover { background: var(--c-wood); color: var(--c-cream); border-color: var(--c-wood); }
/* blog-hero and rec-hero have cream backgrounds in the DEFAULT (dark) theme —
   the base cream primary button would sit invisibly on that surface. Flip it
   to ink-on-cream here; the light-theme mirror further down flips it back to
   cream-on-ink because both heros invert to dark in light theme. */
.blog-hero .btn--primary,
.rec-hero .btn--primary        { background: var(--c-ink); color: var(--c-cream); border-color: var(--c-ink); }
.blog-hero .btn--primary:hover,
.rec-hero .btn--primary:hover  { background: var(--c-wood-dk); border-color: var(--c-wood-dk); }
.btn--ghost {
  color: #fff; border-color: rgba(255,255,255,.65);
}
.btn--ghost:hover { background: rgba(255,255,255,.1); border-color: #fff; color: #fff; }

/* Home hero only — strip the ghost button back to an editorial-link style:
   no border, no fill on hover, just an underline on the text plus a chevron
   that slides in from the left. Scoped to `.hero` so /corsi, /studio, etc.
   heros keep their standard ghost button. */
.hero .btn--ghost {
  border: 0;
  background: transparent;
  padding: 15px 0;
  transition: color var(--tr-fast);
}
.hero .btn--ghost:hover {
  background: transparent;
  color: #fff;
}
/* Underline the label text only — the button contains the WhatsApp icon as a
   sibling flex item, and `text-decoration` on the parent would render awkwardly
   across the icon gap. Scoping to the <span> keeps the underline crisp. */
.hero .btn--ghost span {
  transition: text-decoration-color var(--tr-fast);
}
.hero .btn--ghost:hover span {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
}
/* Chevron reveals on hover with a small slide — feels like a link opening. */
.hero .btn--ghost::after {
  content: '›';
  font-size: 1.35em;
  line-height: 1;
  margin-left: 6px;
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity var(--tr-fast), transform var(--tr-fast);
}
.hero .btn--ghost:hover::after {
  opacity: 1;
  transform: translateX(0);
}
/* Inverted heros (cream bg in dark theme) need a ghost button with ink
   text/border — the base white-on-white is invisible there. Light theme flips
   the heros back to dark, and its own override (bottom of file) drops this
   rule so the base white-ghost styles apply again. */
.corsi-hero .btn--ghost,
.studio-hero .btn--ghost,
.contatti-hero .btn--ghost,
.policy-hero .btn--ghost {
  color: var(--c-ink);
  border-color: rgba(30,26,22,.45);
}
.corsi-hero .btn--ghost:hover,
.studio-hero .btn--ghost:hover,
.contatti-hero .btn--ghost:hover,
.policy-hero .btn--ghost:hover {
  background: rgba(30,26,22,.08); border-color: var(--c-ink); color: var(--c-ink);
}

/* ---------- Section wrappers ---------- */
.section {
  padding: clamp(80px, 10vw, 140px) clamp(20px, 4vw, 48px);
}
/* Home /#corsi sits right below the hero — the shared `.section` top of
   140px on wide screens (80px on mobile) reads as too much dead space
   between the hero image and the "I nostri corsi" heading. Tighten it. */
#corsi { padding-top: clamp(48px, 6vw, 80px); }
.section--dark {
  background: var(--c-ink); color: var(--c-cream);
  /* Own stacking context so the decorative pseudo below stays behind children
     regardless of what z-index the section's content declares. */
  position: relative;
  isolation: isolate;
}
/* Warm decorative linework layered inside every dark body section. Two
   theme-specific assets share the same composition (near-black bg + gold
   lines for dark; cream bg + dark-brown lines for light), and the blend
   mode inverts to match:
   - dark theme:  `lighten` — image's black drops out (ink is lighter),
                   only the light gold survives over ink.
   - light theme: `darken`  — image's cream drops out (cream-2 is darker
                   or equal), only the dark brown lines survive over cream.
   Both give a true "keep only the ink; kill the bg" effect without the
   additive brightening `screen` would produce. */
.section--dark::before {
  content: "";
  position: absolute; inset: 0;
  background-image: url('../images/deco/decorative-elements-dark.webp');
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  mix-blend-mode: lighten;
  /* Dark theme baseline — light theme overrides this to .1 (deco reads
     stronger on the dark ink bg than on cream, so it needs less opacity
     there). */
  opacity: .2;
  z-index: -1;
  pointer-events: none;
}
/* Desktop only: pin the bg to the viewport so stacked dark sections all reveal
   the same image at the same position — the section boundary becomes invisible
   because there's no per-section image to seam. Excluded from touch devices
   because iOS Safari falls back to `scroll` silently and Android scroll perf
   suffers with fixed backgrounds. */
@media (hover: hover) and (pointer: fine) {
  .section--dark::before { background-attachment: fixed; }
}
.section__head {
  max-width: 1440px; margin: 0 auto clamp(48px, 6vw, 80px);
  text-align: center;
}
.eyebrow {
  margin: 0 0 20px;
  font-size: 12px; letter-spacing: .32em; text-transform: uppercase;
  color: var(--c-sand);
}
/* Heros carry an inverted bg vs the theme (cream on dark theme, ink on light).
   Scope the eyebrow color per hero so it always contrasts its own bg — not
   the theme — otherwise sand-on-cream would be washed out on the dark-theme
   heros. Light-theme override further below flips this back to sand. */
.corsi-hero .eyebrow,
.studio-hero .eyebrow,
.contatti-hero .eyebrow,
.policy-hero .eyebrow,
.blog-hero .eyebrow,
.rec-hero .eyebrow { color: var(--c-wood-dk); }
.section__title {
  font-size: clamp(34px, 4.4vw, 56px);
  line-height: 1.08;
  margin: 0 auto 20px;
}
.section__lead {
  max-width: 62ch;
  margin: 0 auto;
  color: rgba(246,239,226,.72);
  font-size: 16.5px;
}

/* ---------- Courses grid ---------- */
.courses {
  /* 1920 − 2×48 (the section's max horizontal padding). Keeps the grid at the
     minimum 48px gutter up to a 1920 viewport; only beyond that does the
     wrapper cap kick in, so 1280–1920 all share the same tight side padding
     rather than accumulating dead space on wider monitors. */
  max-width: 1824px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 28px;
}
/* Lone card on the last row → span both cols and center at half-width.
   Scoped to the desktop 2-col grid; on mobile the grid is a single column,
   so the "half-width centered" treatment doesn't apply. */
@media (min-width: 901px) {
  .courses .course:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    justify-self: center;
    width: calc(50% - 14px);   /* half of container minus half of the 28px gap */
  }
}
.course {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--c-ink-2);
}
.course__link {
  display: block; width: 100%; height: 100%;
  color: #fff;
  position: relative;
}
/* Frame is a passthrough on desktop (display:contents leaves the box tree
   untouched so the existing absolute wrap is still positioned by .course__link).
   On mobile the frame becomes the fixed visible image area (see media query),
   giving the wrap a positioning parent + overflow-clip in the flex column layout. */
.course__img-frame { display: contents; }

/* Outer wrapper — receives the JS parallax translate. NO transition on
   transform, so the shift is direct-linked to scroll (no catch-up glide). */
.course__img-wrap {
  position: absolute; inset: -6% -0 -0 -0;   /* extra top overflow room for parallax */
  height: 112%;
  overflow: hidden;
  transform: translate3d(0, 0, 0);
  will-change: transform;
}
/* Inner element — carries the hover scale/filter, which DOES ease smoothly. */
.course__img {
  position: absolute; inset: 0;
  background-size: cover;
  background-position: center;
  transform: scale(1.02);
  transition: transform var(--tr-slow), filter var(--tr-slow);
  will-change: transform;
  filter: saturate(.95) contrast(1.02);
}
.course__scrim {
  position: absolute; inset: 0;
  /* Prev (kept for quick revert):
     background:
       linear-gradient(180deg,
         rgba(18,16,14,.10) 0%,
         rgba(18,16,14,.30) 45%,
         rgba(18,16,14,.85) 100%);
  */
  background:
    linear-gradient(180deg,
      rgba(18,16,14,0)   0%,
      rgba(18,16,14,.19) 45%,
      rgba(0,0,0,.59)   100%);
}
/* Darker overlay cross-faded on hover — animating gradient shorthands via
   `transition: background` is unreliable (browsers may snap between the two).
   A stacked pseudo-element with opacity 0 → 1 is guaranteed to interpolate. */
.course__scrim::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      rgba(18,16,14,.40) 0%,
      rgba(18,16,14,.65) 40%,
      rgba(18,16,14,.95) 100%);
  opacity: 0;
  transition: opacity var(--tr-med);
  pointer-events: none;
}
/* ------------------------------------------------------------------
   Card body layout (in-flow flex column, justify-end).
   Idle order (bottom-up):  META · TITLE
   Hover order (bottom-up): CTA · META · REVEAL(tagline+desc) · TITLE
   REVEAL and CTA-WRAP collapse to 0 height when idle and animate their
   height + opacity in unison, so the title rises and the meta rises,
   both smoothly, at the same time.

   --- PREVIOUS APPROACH (kept as reference for easy revert) ---
   Before this rewrite the panel (tagline + desc + meta + cta) was
   ONE absolute-positioned block at bottom translated 100% out of view,
   and .course__title used `transform: translateY(-var(--panel-h))`
   measured in JS. Duration/max/level were only visible on hover.
   ---------------------------------------------------------------- */
.course__body {
  position: absolute; inset: 0;
  padding: clamp(28px, 3.4vw, 48px);
  display: flex; flex-direction: column; justify-content: flex-end;
  align-items: center; text-align: center;
  /* On hover the padding-bottom grows so meta is pushed up in lockstep
     with the CTA sliding up from below the card. */
  transition: padding-bottom var(--tr-med);
}
.course:hover .course__body,
.course:focus-within .course__body {
  padding-bottom: calc(clamp(28px, 3.4vw, 48px) + 62px);
}
.course__title {
  font-family: var(--f-serif);
  font-size: clamp(28px, 3.2vw, 42px);
  line-height: 1.1;
  font-weight: 500;
  letter-spacing: .01em;
  margin: 0;
}

/* REVEAL — collapsed idle, expands on hover pushing the title upward.
   Uses the grid-rows trick: outer sets grid-template-rows: 0fr → 1fr, inner
   is overflow:hidden. This animates to the ACTUAL content height (unlike
   max-height, which reaches the content-height limit almost immediately if
   the max is set higher than the content). */
.course__reveal {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition:
    grid-template-rows var(--tr-med),
    opacity            var(--tr-med);
}
.course__reveal-inner {
  overflow: hidden;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  min-height: 0;
  padding-top: 0; padding-bottom: 0;
  transition: padding-top var(--tr-med), padding-bottom var(--tr-med);
}
.course__tagline {
  font-size: 12.5px; letter-spacing: .24em; text-transform: uppercase;
  /* prev: var(--c-sand) — too muted on the dark scrim. Warm off-white reads much better. */
  color: #e8d9bf;
}
.course__desc {
  font-size: 15px; line-height: 1.55;
  color: rgba(255,255,255,.9);
  max-width: 64ch;   /* prev: 52ch */
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}

/* META — always visible; sits above the CTA row */
.course__meta {
  display: flex; gap: 18px; flex-wrap: wrap; justify-content: center;
  padding-top: 16px; margin-top: 14px;
  border-top: 1px solid rgba(255,255,255,.18);
  align-self: stretch;
}
.course__meta-item {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; letter-spacing: .06em;
  color: rgba(255,255,255,.9);
}
.course__meta-item svg { color: var(--c-sand); }
.course__meta-item--level {
  padding: 4px 10px;
  border: 1px solid rgba(255,255,255,.35);
  font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase;
  color: rgba(255,255,255,.85);
}
/* Hide the "livello" badge on every public surface — home cards, /corsi rows,
   and the course-detail overlay. The admin's corso edit form still exposes it
   as a `<select name="level">` for internal record-keeping. `!important`
   because the base `.cdet__meta-item` (line ~794) and `.corso-row__meta-item`
   (line ~1142) rules declare `display: inline-flex` LATER in the file with
   equal specificity, so they otherwise win the cascade tiebreaker. */
.course__meta-item--level,
.corso-row__meta-item--level,
.cdet__meta-item--level { display: none !important; }

/* CTA slot — absolute-positioned at the bottom of the card, translated
   fully below the card edge at rest. The card's overflow:hidden clips it.
   On hover it translates to 0, entering from BELOW the card edge in one
   continuous motion — no clip-line reveal, no "last-moment border" effect. */
.course__cta-slot {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 22px clamp(28px, 3.4vw, 48px) clamp(28px, 3.4vw, 48px);
  display: flex; justify-content: center;
  transform: translateY(100%);
  transition: transform var(--tr-med);
  z-index: 3;   /* above scrim/scrim::after */
}
.course:hover .course__cta-slot,
.course:focus-within .course__cta-slot {
  transform: translateY(0);
}
.course__cta {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 12px 22px;
  /* Faint white wash so the CTA reads as a filled button, not a border-only
     ghost — the level badge next to it uses the same outlined-white style
     and the two were competing visually. */
  background: rgba(255,255,255,.25);
  border: 1px solid rgba(255,255,255,.7);
  font-size: 12px; letter-spacing: .22em; text-transform: uppercase;
  color: #fff;
  transition:
    background   var(--tr-fast),
    color        var(--tr-fast),
    border-color var(--tr-fast);
}
.course__cta:hover { background: #fff; color: var(--c-ink); border-color: #fff; }

/* Hover / focus reveal */
/* Hover zoom on image disabled for now — image stays static on hover.
   To restore, uncomment the block below (was: scale(1.06) + saturate/contrast bump).
.course:hover .course__img,
.course:focus-within .course__img {
  transform: scale(1.06); filter: saturate(1.05) contrast(1.03);
}
*/
.course:hover .course__scrim::after,
.course:focus-within .course__scrim::after {
  opacity: 1;
}
.course:hover .course__reveal,
.course:focus-within .course__reveal {
  grid-template-rows: 1fr;
  opacity: 1;
}
.course:hover .course__reveal-inner,
.course:focus-within .course__reveal-inner {
  padding-top: 14px;
  padding-bottom: 18px;
}
.course:hover .course__cta-wrap,
.course:focus-within .course__cta-wrap {
  grid-template-rows: 1fr;
  opacity: 1;
}
.course:hover .course__cta-inner,
.course:focus-within .course__cta-inner {
  padding-top: 18px;
}
.course__link:focus-visible { outline: 2px solid var(--c-sand); outline-offset: -4px; }

/* =================================================================
   Course-detail overlay (fullscreen, FLIP transition from card)
   ================================================================= */
body.cdet-open { overflow: hidden; }
/* body scroll lock while the mobile burger menu is open (see site.js toggle) */
body.nav-open  { overflow: hidden; }

.cdet {
  position: fixed; inset: 0; z-index: 100;
  overflow: hidden;
  color: #fff;
  isolation: isolate;
  /* Closing fades the entire overlay as one unit — no reverse FLIP,
     no per-element unmount choreography. Elegant and impossible to botch. */
  transition: opacity 350ms ease;
}
.cdet.is-closing {
  opacity: 0;
  pointer-events: none;
}
.cdet[hidden] { display: none !important; }

/* Backdrop that FLIPs from the card's screen rect out to full viewport.
   The FLIP is driven by the Web Animations API from JS (see openDetail); we
   set transform-origin dynamically per-open so the expansion always emanates
   from the viewport corner nearest the card center.
   NOTE: no `transition: transform` here anymore — CSS transitions on this
   property were unreliable ("stops working after a few opens"). WAAPI is
   deterministic and cancels/replays cleanly. */
.cdet__bg {
  position: absolute; inset: 0;
  background-color: var(--c-ink);
  background-size: cover;
  background-position: center;
  transform-origin: 0 0;
  will-change: transform;
}
/* Darkening scrim over the image so left-side text stays legible */
.cdet__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(90deg,
      rgba(18,16,14,.88) 0%,
      rgba(18,16,14,.62) 42%,
      rgba(18,16,14,.32) 62%,
      rgba(18,16,14,.55) 100%),
    linear-gradient(180deg, rgba(18,16,14,.35) 0%, rgba(18,16,14,.5) 100%);
  opacity: 0;
  transition: opacity 500ms ease 250ms;
}
.cdet.is-open .cdet__scrim { opacity: 1; }

/* Big X close button, top-right */
.cdet__close {
  position: absolute; top: 24px; right: 24px; z-index: 4;
  width: 56px; height: 56px;
  background: rgba(18,16,14,.35);
  color: #fff;
  border: 1px solid rgba(255,255,255,.5);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  opacity: 0; transform: scale(.9);
  transition:
    opacity        400ms ease 450ms,
    transform      400ms cubic-bezier(.22,.7,.2,1) 450ms,
    background     var(--tr-fast),
    border-color   var(--tr-fast);
}
.cdet.is-open .cdet__close { opacity: 1; transform: scale(1); }
.cdet__close:hover { background: rgba(255,255,255,.14); border-color: #fff; }

/* Two-column content grid */
.cdet__content {
  position: absolute; inset: 0; z-index: 3;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 72px);
  padding: clamp(80px, 10vh, 120px) clamp(32px, 5vw, 88px) clamp(48px, 6vh, 72px);
  pointer-events: none;   /* let child sections own pointer-events */
}
.cdet__left,
.cdet__right { pointer-events: auto; min-width: 0; }

.cdet__left {
  display: flex; flex-direction: column;
  align-items: flex-start; text-align: left;
  gap: 22px;
  align-self: start;
  opacity: 0; transform: translateY(24px);
  transition:
    opacity   500ms ease 400ms,
    transform 600ms cubic-bezier(.22,.7,.2,1) 400ms;
}
.cdet.is-open .cdet__left { opacity: 1; transform: none; }

.cdet__tag {
  margin: 0;
  font-size: 12.5px; letter-spacing: .32em; text-transform: uppercase;
  color: #e8d9bf;
  display: inline-flex; align-items: center; gap: 14px;
}
.cdet__tag::before {
  content: ""; width: 42px; height: 1px; background: currentColor;
}
.cdet__tag:empty { display: none; }

.cdet__title {
  margin: 0;
  font-family: var(--f-serif);
  font-size: clamp(40px, 5.4vw, 76px);
  line-height: 1.02;
  letter-spacing: -.01em;
  font-weight: 500;
}

.cdet__meta {
  display: flex; flex-wrap: wrap; gap: 12px 22px;
  padding-top: 6px;
}
.cdet__meta-item {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13.5px; letter-spacing: .06em;
  color: rgba(255,255,255,.9);
}
.cdet__meta-item svg { color: #e8d9bf; }
.cdet__meta-item--level {
  padding: 4px 12px;
  border: 1px solid rgba(255,255,255,.4);
  font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase;
}

.cdet__desc {
  margin: 8px 0 0;
  font-size: 17px; line-height: 1.65;
  color: rgba(255,255,255,.9);
  max-width: 60ch;
}

/* Weekly schedule (under description) */
.cdet__sched { margin-top: 8px; align-self: stretch; }
.cdet__sched[hidden] { display: none; }
.cdet__sched-sep {
  height: 1px;
  background: linear-gradient(90deg, rgba(255,255,255,.28), rgba(255,255,255,0));
  margin: 4px 0 18px;
  max-width: 320px;
}
.cdet__sched-title {
  margin: 0 0 14px;
  font-family: var(--f-sans);
  font-size: 12px; letter-spacing: .28em; text-transform: uppercase;
  color: #e8d9bf;
  font-weight: 500;
}
.cdet__sched-list { margin: 0; padding: 0; display: grid; row-gap: 6px; max-width: 62ch; }
.cdet__sched-row {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) 2.4fr;
  align-items: baseline;
  padding: 6px 0;
  border-bottom: 1px solid rgba(255,255,255,.08);
  font-size: 15px;
}
.cdet__sched-row dt {
  color: rgba(255,255,255,.7);
  letter-spacing: .04em;
  font-family: var(--f-sans);
}
.cdet__sched-row dd {
  margin: 0;
  color: rgba(255,255,255,.95);
  font-variant-numeric: tabular-nums;
}
/* Slot rendering — dots between slots come from CSS so the mobile 2-per-row
   grid can suppress them at end-of-row without any JS layout math. */
.cdet__slot { display: inline-block; }
.cdet__slot:not(:last-child)::after {
  content: '·';
  margin: 0 .6em;
  color: rgba(255,255,255,.35);
}

/* Right column — scrollable equipment list */
.cdet__right {
  overflow-y: auto;
  padding-right: 6px;
  opacity: 0; transform: translateX(28px);
  transition:
    opacity   500ms ease 520ms,
    transform 600ms cubic-bezier(.22,.7,.2,1) 520ms;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.35) transparent;
}
.cdet.is-open .cdet__right { opacity: 1; transform: none; }
.cdet__right::-webkit-scrollbar { width: 8px; }
.cdet__right::-webkit-scrollbar-thumb { background: rgba(255,255,255,.28); }
.cdet__right::-webkit-scrollbar-track { background: transparent; }

.cdet__equip-title {
  margin: 0 0 22px;
  font-family: var(--f-serif);
  font-size: clamp(24px, 2.4vw, 34px);
  font-weight: 500;
  letter-spacing: -.005em;
}
.cdet__equip-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}
.cdet__equip {
  background: rgba(18,16,14,.55);
  border: 1px solid rgba(255,255,255,.12);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex; flex-direction: column;
}
.cdet__equip-img {
  display: block;
  width: 100%; aspect-ratio: 3 / 2;
  background-size: cover; background-position: center;
}
.cdet__equip-body { padding: 14px 16px 18px; }
.cdet__equip-name {
  margin: 0 0 6px;
  font-family: var(--f-serif); font-size: 19px; font-weight: 500; letter-spacing: .005em;
}
.cdet__equip-desc {
  margin: 0;
  font-size: 13px; line-height: 1.55;
  color: rgba(255,255,255,.78);
}

/* Responsive */
@media (max-width: 900px) {
  .cdet__content {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr;
    padding: 72px 20px 24px;
    gap: 24px;
    overflow-y: auto;
  }
  .cdet__left { align-self: auto; }
  .cdet__right { overflow-y: visible; transform: translateY(20px); }
  .cdet__equip-grid { grid-template-columns: 1fr; }
  .cdet__close { top: 12px; right: 12px; width: 46px; height: 46px; }
}

@media (prefers-reduced-motion: reduce) {
  .cdet, .cdet__bg, .cdet__scrim, .cdet__close, .cdet__left, .cdet__right {
    transition: none !important;
  }
}

/* =================================================================
   /corsi page — weekly grid + course list
   ================================================================= */
.corsi-hero {
  padding: calc(var(--nav-h) + 60px) clamp(20px, 4vw, 48px) 20px;
  /* Inverted vs the site body: dark theme shows a CREAM hero for high contrast
     against the dark body below; light theme flips (below) to a dark hero. */
  background: var(--c-cream);
  color: var(--c-ink);
}
.corsi-hero__inner { max-width: 1200px; margin: 0 auto; text-align: center; }
.corsi-hero__title {
  font-family: var(--f-serif);
  font-size: clamp(38px, 5vw, 66px);
  line-height: 1.05;
  font-weight: 500;
  margin: 0 auto 20px;
  max-width: 22ch;
}
.corsi-hero__lead {
  max-width: 62ch; margin: 0 auto;
  color: rgba(30,26,22,.68);
  font-size: 16.5px;
}

.weekgrid-wrap {
  max-width: 1400px;
  margin: 0 auto;
}
.weekgrid-scroll {
  overflow-x: auto;
  border: 1px solid var(--c-line);
}
.weekgrid {
  width: 100%;
  border-collapse: collapse;
  color: var(--c-cream);
  font-family: var(--f-sans);
  font-size: 14px;
  min-width: 780px;
  table-layout: fixed;
}
.weekgrid thead th {
  padding: 16px 10px;
  font-size: 12px; letter-spacing: .22em; text-transform: uppercase;
  color: #e8d9bf;
  font-weight: 500;
  background: rgba(255,255,255,.03);
  border-bottom: 1px solid var(--c-line);
  text-align: center;
}
.weekgrid__time-h { width: 84px; }
.weekgrid tbody th.weekgrid__time {
  padding: 14px 10px;
  font-family: var(--f-serif);
  font-size: 15px;
  font-weight: 500;
  color: rgba(246,239,226,.85);
  border-right: 1px solid var(--c-line);
  border-bottom: 1px solid var(--c-line);
  background: rgba(255,255,255,.02);
  vertical-align: middle;
  text-align: center;
}
.weekgrid tbody td {
  padding: 8px 6px;
  border-right: 1px solid var(--c-line);
  border-bottom: 1px solid var(--c-line);
  vertical-align: top;
  min-height: 68px;
  height: 68px;
}
.weekgrid tbody td:last-child { border-right: 0; }
.weekgrid__slot {
  display: flex; flex-direction: column; gap: 3px;
  padding: 10px 10px;
  background: color-mix(in oklab, var(--slot-color) 24%, transparent);
  border-left: 2px solid var(--slot-color);
  color: var(--c-cream);
  border-bottom: 1px solid transparent;
  transition: background var(--tr-fast), transform var(--tr-fast);
}
.weekgrid__slot:hover {
  background: color-mix(in oklab, var(--slot-color) 42%, transparent);
  transform: translateY(-1px);
}
.weekgrid__slot-name {
  font-family: var(--f-serif);
  font-size: 14.5px; line-height: 1.15;
  letter-spacing: .005em;
}
.weekgrid__slot-time {
  font-size: 11px; letter-spacing: .06em;
  color: rgba(246,239,226,.72);
  font-variant-numeric: tabular-nums;
}

.weekgrid-actions {
  display: flex; justify-content: center;
  padding: 40px 0 0;
}

/* Weekgrid section — snug against the hero and the list below it.
   Overrides .section's clamp(80,10vw,140) top/bottom padding on /corsi. */
.corsi-grid-section {
  padding-top: 40px;
  padding-bottom: 32px;
}

/* Vertical course list below the grid — small top gap so it reads as
   part of the same page, not a whole new section. */
/* Editorial "Cos'è il Pilates" block below the /corsi list. Reuses .section
   --dark so the deco pseudo lands automatically. Centered narrow reading
   column — long-form typography, not a card grid.
   Zero top padding: the previous .section's bottom padding already provides
   the vertical breathing room; stacking both was creating a huge gap. */
.corsi-intro { padding-top: 0; }
.corsi-intro__inner {
  max-width: 780px; margin: 0 auto;
  text-align: left;
}
.corsi-intro .eyebrow,
.corsi-intro .section__title { text-align: center; }
.corsi-intro .section__title { margin-bottom: 28px; }
.corsi-intro__lead {
  font-size: clamp(16px, 1.35vw, 18px);
  line-height: 1.7;
  color: rgba(246,239,226,.86);
  margin: 0 0 32px;
}
.corsi-intro__h {
  font-family: var(--f-serif);
  font-size: clamp(22px, 2.4vw, 28px);
  font-weight: 500;
  margin: 0 0 16px;
  color: var(--c-cream);
}
.corsi-intro__list {
  margin: 0 0 28px;
  padding-left: 1.4em;
  color: rgba(246,239,226,.82);
  font-size: 16px; line-height: 1.65;
}
.corsi-intro__list li { margin: 0 0 10px; }
.corsi-intro__list strong { color: var(--c-cream); font-weight: 600; }
.corsi-intro__outro {
  font-style: italic;
  color: rgba(246,239,226,.72);
  font-size: 16px;
  margin: 0;
}
/* Light-theme text colors — matches the other .section--dark overrides. */
:root[data-theme="light"] .corsi-intro__lead,
:root[data-theme="light"] .corsi-intro__list { color: rgba(30,26,22,.78); }
:root[data-theme="light"] .corsi-intro__h,
:root[data-theme="light"] .corsi-intro__list strong { color: var(--c-ink); }
:root[data-theme="light"] .corsi-intro__outro { color: rgba(30,26,22,.66); }

.corsi-list-section {
  padding-top: 48px;
  padding-bottom: clamp(64px, 7vw, 100px);
}
.corsi-list-section .section__head { margin-bottom: clamp(32px, 4vw, 56px); }
.corsi-list {
  max-width: 1200px; margin: 0 auto;
  display: flex; flex-direction: column;
  gap: 28px;
}
.corso-row {
  display: grid;
  grid-template-columns: minmax(220px, 340px) 1fr;
  gap: clamp(24px, 3.5vw, 56px);
  align-items: start;
  padding: 24px 0;
  border-top: 1px solid var(--c-line);
  /* Anchor scroll (weekgrid slot → #slug) stops with room for the fixed nav
     and a little breathing space above the row. */
  scroll-margin-top: calc(var(--nav-h) + 24px);
}
.corso-row:first-child { border-top: 0; padding-top: 0; }
.corso-row__cover {
  display: block;
  aspect-ratio: 4 / 3;
  background-size: cover;
  background-position: center;
  background-color: var(--c-ink-2);
  transition: transform var(--tr-fast), filter var(--tr-fast);
}
.corso-row__cover:hover { filter: brightness(1.20) saturate(1.10); }
.corso-row__body { min-width: 0; padding-top: 4px; }
.corso-row__tag {
  margin: 0 0 10px;
  font-size: 12px; letter-spacing: .28em; text-transform: uppercase;
  color: #e8d9bf;
}
.corso-row__title {
  margin: 0 0 14px;
  font-family: var(--f-serif);
  font-size: clamp(26px, 3vw, 40px);
  line-height: 1.08;
  font-weight: 500;
  /* Clickable via a JS listener on .corso-row__title (see site.js) — mirror
     the cover's affordance so users see it's actionable. */
  cursor: pointer;
  transition: color var(--tr-fast);
}
.corso-row__title:hover { color: var(--c-sand); }
.corso-row__desc {
  margin: 0 0 18px;
  font-size: 16px; line-height: 1.6;
  color: rgba(246,239,226,.82);
  max-width: 60ch;
}
.corso-row__meta { display: flex; flex-wrap: wrap; gap: 14px 22px; }
.corso-row__meta-item {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13.5px; letter-spacing: .06em;
  color: rgba(246,239,226,.85);
}
.corso-row__meta-item svg { color: #e8d9bf; }
.corso-row__meta-item--level {
  padding: 4px 10px;
  border: 1px solid rgba(255,255,255,.35);
  font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase;
}

@media (max-width: 720px) {
  .corso-row { grid-template-columns: 1fr; gap: 18px; }
}

/* =================================================================
   /studio page — brief intro + two galleries (Studio + Formazione)
   ================================================================= */
.studio-hero {
  padding: calc(var(--nav-h) + 60px) clamp(20px, 4vw, 48px) 20px;
  background: var(--c-cream);
  color: var(--c-ink);
}
.studio-hero__inner { max-width: 900px; margin: 0 auto; text-align: center; }
.studio-hero__title {
  font-family: var(--f-serif);
  font-size: clamp(36px, 5vw, 60px);
  line-height: 1.05;
  font-weight: 500;
  margin: 0 auto 18px;
}
.studio-hero__lead {
  max-width: 62ch; margin: 0 auto;
  color: rgba(30,26,22,.68);
  font-size: 16.5px;
}

.studio-section { padding-top: clamp(48px, 6vw, 80px); padding-bottom: clamp(48px, 6vw, 80px); }
.studio-section + .studio-section { padding-top: 0; }
.studio-section .section__head { margin-bottom: clamp(32px, 4vw, 48px); }

/* Full-bleed panorama between the lead and the gallery grid. The parent
   .section has clamp(20px..48px) side padding, so we cancel it with a
   negative left margin and stretch to 100vw. `aspect-ratio` reserves the
   space so there's no layout shift on load. Small vertical margins keep it
   visually breathing without leaking into the tiles below. */
.studio-panorama {
  margin: 0 calc(50% - 50vw) clamp(32px, 4vw, 48px);
  width: 100vw;
  aspect-ratio: 2678 / 1220;
  overflow: hidden;
  background: var(--c-ink-2);
}
.studio-panorama img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
/* Hard-cap the panorama height on very short/wide viewports so it never
   dominates the fold — a 55vh ceiling keeps at least some of the tiles
   below visible without needing a scroll. */
@media (min-aspect-ratio: 21/9) {
  .studio-panorama { aspect-ratio: auto; height: 55vh; }
}

.studio-grid {
  max-width: 1400px; margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 14px;
}
/* 3-per-row variant for the main studio photo set — bigger tiles read better
   for wide 16:9 studio shots than the auto-fill 4+ column default. Mobile
   breakpoints below drop to 2 and 1 col, same as the default variant. */
.studio-grid--3 {
  grid-template-columns: repeat(3, 1fr);
}
.studio-tile {
  margin: 0;
  padding: 0;
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--c-ink-2);
  border: 1px solid var(--c-line);
  cursor: pointer;
  color: inherit;
  font: inherit;
  display: block;
  /* Subtle white glow on hover instead of the earlier scale-in zoom.
     Two shadows: a soft outer halo + a tight inner ring. */
  transition: box-shadow var(--tr-med), border-color var(--tr-med);
}
.studio-tile:hover,
.studio-tile:focus-visible {
  border-color: rgba(255,255,255,.6);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.35),
    0 0 24px 4px rgba(255,255,255,.18);
  outline: none;
}
.studio-tile img,
.studio-tile video {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  background: var(--c-ink-2);
}
.studio-tile--vid { background: #0c0b0a; }

/* Corner badge — hints the tile is interactive. Play glyph for videos, expand
   glyph for images. Sits on a subtle scrim so it stays legible on any image. */
.studio-tile__badge {
  position: absolute;
  top: 10px; right: 10px;
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(18,16,14,.55);
  color: #f6efe2;
  pointer-events: none;
  transition: background var(--tr-fast);
}
.studio-tile:hover .studio-tile__badge { background: rgba(18,16,14,.85); }
.studio-tile__badge--vid {
  top: auto; right: auto;
  top: 50%; left: 50%;
  width: 76px; height: 76px;
  transform: translate(-50%, -50%);
  background: rgba(18,16,14,.6);
  border: 0;
  border-radius: 50%;
}
.studio-tile__badge--vid svg { width: 38px; height: 38px; margin-left: 4px; }   /* nudge triangle so it feels centered */

/* Fullscreen lightbox for gallery media */
body.lb-open { overflow: hidden; }
.lightbox {
  border: 0;
  padding: 0;
  background: transparent;
  color: #fff;
  max-width: 100vw; max-height: 100vh;
  width: 100vw; height: 100vh;
  margin: 0;
  overflow: hidden;
}
.lightbox::backdrop { background: rgba(12,11,10,.92); backdrop-filter: blur(6px); }
.lightbox__close {
  position: absolute; top: 20px; right: 20px; z-index: 3;
  width: 48px; height: 48px;
  background: rgba(255,255,255,.08);
  color: #fff;
  border: 1px solid rgba(255,255,255,.35);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background var(--tr-fast), border-color var(--tr-fast);
}
.lightbox__close:hover { background: rgba(255,255,255,.18); border-color: #fff; }
.lightbox__nav {
  position: absolute; top: 50%; z-index: 3;
  transform: translateY(-50%);
  width: 52px; height: 52px;
  background: rgba(255,255,255,.08);
  color: #fff;
  border: 1px solid rgba(255,255,255,.35);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background var(--tr-fast), border-color var(--tr-fast);
}
.lightbox__nav:hover { background: rgba(255,255,255,.18); border-color: #fff; }
.lightbox__nav[hidden] { display: none; }
.lightbox__nav--prev { left: 20px; }
.lightbox__nav--next { right: 20px; }
.lightbox__stage {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(32px, 5vw, 72px);
}
.lightbox__stage img,
.lightbox__stage video {
  max-width: 100%; max-height: 100%;
  display: block;
  object-fit: contain;
  background: #000;
}
/* Kill the browser's native pinch/pan on the image so our JS gesture handlers
   own the touch stream. Without this, iOS double-pinches: our handler AND the
   viewport pinch both fire, and the entire page scales up behind the modal.
   `touch-action: none` also prevents scroll gestures from bubbling to body. */
.lightbox__stage img { touch-action: none; transform-origin: 0 0; user-select: none; -webkit-user-select: none; }
/* Mobile chrome-off: bigger tap targets, tighter padding, close+nav at the
   viewport edges where thumbs naturally sit. */
@media (max-width: 720px) {
  .lightbox__stage { padding: 12px; }
  .lightbox__close { top: 12px; right: 12px; width: 44px; height: 44px; }
  .lightbox__nav { width: 44px; height: 44px; }
  .lightbox__nav--prev { left: 8px; }
  .lightbox__nav--next { right: 8px; }
}
/* When the lightbox is open, lock the whole page from scrolling/zooming so
   iOS Safari can't tug the layout behind. `overflow: hidden` on body handles
   most engines; `overscroll-behavior: contain` prevents rubber-band leakage. */
body.lb-open { overscroll-behavior: contain; touch-action: none; }
body.lb-open .lightbox { touch-action: manipulation; }

@media (max-width: 720px) {
  .studio-grid { grid-template-columns: 1fr 1fr; gap: 8px; }
  .studio-tile { aspect-ratio: 1 / 1; }
}
@media (max-width: 420px) {
  .studio-grid { grid-template-columns: 1fr; }
  .studio-tile { aspect-ratio: 4 / 3; }
}

/* =================================================================
   /contatti page
   ================================================================= */
.contatti-hero {
  padding: calc(var(--nav-h) + 60px) clamp(20px, 4vw, 48px) 20px;
  background: var(--c-cream);
  color: var(--c-ink);
}
.contatti-hero__inner { max-width: 900px; margin: 0 auto; text-align: center; }
.contatti-hero__title {
  font-family: var(--f-serif);
  font-size: clamp(36px, 5vw, 60px);
  line-height: 1.05;
  font-weight: 500;
  margin: 0 auto 18px;
  max-width: 20ch;
}
.contatti-hero__lead {
  max-width: 62ch; margin: 0 auto;
  color: rgba(30,26,22,.68);
  font-size: 16.5px;
}

.contatti-body { padding-top: 40px; padding-bottom: clamp(64px, 7vw, 100px); }
.contatti-grid {
  max-width: 1200px; margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(320px, 1fr) 1.4fr;
  gap: clamp(28px, 4vw, 56px);
}

.contatti-info { display: flex; flex-direction: column; gap: 32px; }
.contatti-block {
  padding: 24px 26px;
  background: var(--c-ink-2);
  border-left: 2px solid var(--c-sand);
}
.contatti-block__title {
  margin: 0 0 12px;
  font-family: var(--f-sans);
  font-size: 12px; letter-spacing: .28em; text-transform: uppercase; font-weight: 500;
  color: #e8d9bf;
}
.contatti-block__body {
  margin: 0 0 18px;
  color: rgba(246,239,226,.86);
  font-size: 16px; line-height: 1.55;
}
.contatti-cta {
  width: 100%;
}

.contatti-socials { display: flex; flex-direction: column; gap: 10px; }
.contatti-social {
  display: inline-flex; align-items: center; gap: 12px;
  color: var(--c-cream);
  padding: 8px 0;
  border-bottom: 1px solid transparent;
  transition: color var(--tr-fast), border-color var(--tr-fast);
}
.contatti-social:hover { color: var(--c-sand); border-color: var(--c-sand); }
.contatti-social .ico { width: 18px; height: 18px; color: var(--c-sand); }

.contatti-map {
  min-height: 420px;
  background: var(--c-ink-2);
  overflow: hidden;
  border: 1px solid var(--c-line);
}

/* Local-SEO copy sitting below the grid — editorial reading width, matching
   the site's serif+sans hierarchy. Sits inside .section--dark so the deco
   background applies naturally. */
.contatti-seo {
  max-width: 720px;
  margin: clamp(48px, 6vw, 80px) auto 0;
  color: rgba(246,239,226,.86);
}
.contatti-seo h2 {
  font-family: var(--f-serif);
  font-size: clamp(24px, 3vw, 34px);
  font-weight: 500;
  margin: 0 0 18px;
  color: var(--c-cream);
}
.contatti-seo h3 {
  font-family: var(--f-serif);
  font-size: clamp(18px, 2vw, 22px);
  font-weight: 500;
  margin: 28px 0 10px;
  color: var(--c-cream);
}
.contatti-seo p, .contatti-seo li {
  font-size: 16px; line-height: 1.65;
  margin: 0 0 12px;
}
.contatti-seo ul { padding-left: 1.1em; margin: 0; }
.contatti-seo strong { color: var(--c-cream); font-weight: 600; }
/* Light-theme mirror — section--dark flips to cream in light theme, so the
   SEO block's cream-on-cream text needs to flip to ink to stay readable. */
:root[data-theme="light"] .contatti-seo         { color: rgba(30,26,22,.78); }
:root[data-theme="light"] .contatti-seo h2,
:root[data-theme="light"] .contatti-seo h3,
:root[data-theme="light"] .contatti-seo strong  { color: var(--c-ink); }
.contatti-map iframe {
  display: block;
  width: 100%; height: 100%;
  min-height: 420px;
  border: 0;
  /* Satellite view has natural earth colours; leave them alone (removing the
     grayscale filter I had on the map view — it made satellite look muddy). */
}

@media (max-width: 900px) {
  .contatti-grid { grid-template-columns: 1fr; }
  .contatti-map  { min-height: 320px; }
  .contatti-map iframe { min-height: 320px; }
}

/* =================================================================
   Blog
   ================================================================= */

/* Hero — two-column intro (text + Joseph photo). Cream bg to match the
   inverted hero pattern used across inner pages (see .corsi-hero etc). */
.blog-hero {
  padding: calc(var(--nav-h) + 60px) clamp(20px, 4vw, 48px) clamp(48px, 6vw, 80px);
  background: var(--c-cream);
  color: var(--c-ink);
}
.blog-hero__inner {
  max-width: 1200px; margin: 0 auto;
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
}
.blog-hero__title {
  font-family: var(--f-serif);
  font-size: clamp(34px, 4.4vw, 56px);
  line-height: 1.05; font-weight: 500;
  margin: 0 0 20px;
}
.blog-hero__lead {
  font-size: clamp(16px, 1.35vw, 18px);
  line-height: 1.65;
  color: rgba(30,26,22,.72);
  max-width: 60ch;
  margin: 0;
}
.blog-hero__cta { margin: 24px 0 0; }
.blog-hero__cta .btn { padding: 12px 22px; }
.blog-hero__figure {
  margin: 0;
  /* Small vintage card frame around the B&W Joseph photo. */
  padding: 16px 16px 8px;
  background: #fff;
  box-shadow: 0 10px 40px rgba(30,26,22,.14);
  transform: rotate(-1.5deg);   /* subtle tilt = "pinned on the wall" */
  /* Decorative-only — behaves like part of the background. Blocks selection,
     dragging, and the browser's right-click context menu (pointer-events on
     the whole subtree = no image-specific menu items for the photo, no text
     selection for the caption). Same technique as .hero__media img. */
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}
.blog-hero__figure img {
  width: 100%; height: auto;
  display: block;
  filter: grayscale(1) contrast(1.05);   /* the source is B&W but re-affirms in case of colour cast */
}
.blog-hero__figure figcaption {
  margin-top: 10px;
  font-family: var(--f-serif); font-style: italic;
  font-size: 13.5px; color: rgba(30,26,22,.66);
  text-align: center;
}
@media (max-width: 780px) {
  .blog-hero__inner { grid-template-columns: 1fr; }
  .blog-hero__figure { max-width: 320px; margin: 0 auto; }
}

/* --- Grid list --- */
.blog-list-section { padding-top: clamp(64px, 8vw, 100px); padding-bottom: clamp(48px, 6vw, 80px); }
.blog-grid {
  max-width: 1200px; margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(24px, 3vw, 40px);
}
@media (max-width: 900px) { .blog-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .blog-grid { grid-template-columns: 1fr; } }

.blog-card {
  display: flex; flex-direction: column;
  background: var(--c-ink-2);
  transition: transform var(--tr-med), box-shadow var(--tr-med);
}
.blog-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 20px 40px rgba(0,0,0,.35);
}
.blog-card__cover {
  display: block;
  aspect-ratio: 16 / 10;
  background: var(--c-ink-2) center / cover no-repeat;
  position: relative;
  color: rgba(246,239,226,.35);
}
.blog-card__cover-fallback {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--f-serif);
  font-size: 42px;
}
.blog-card__body {
  padding: 20px 22px 24px;
  display: flex; flex-direction: column; gap: 8px;
  flex: 1;
}
.blog-card__meta {
  margin: 0;
  font-size: 12px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--c-sand);
  display: flex; flex-wrap: wrap; gap: 8px;
}
.blog-card__title {
  font-family: var(--f-serif);
  font-size: 22px; line-height: 1.15; font-weight: 500;
  margin: 4px 0 6px;
}
.blog-card__title a { color: inherit; }
.blog-card__title a:hover { color: var(--c-sand); }
.blog-card__excerpt {
  margin: 0;
  font-size: 15px; line-height: 1.55;
  color: rgba(246,239,226,.72);
}
.blog-card__more {
  margin-top: auto;
  padding-top: 12px;
  font-size: 13px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--c-sand);
}
.blog-card:hover .blog-card__more { color: var(--c-cream); }

.blog-empty {
  max-width: 600px; margin: 0 auto;
  text-align: center;
  color: rgba(246,239,226,.72);
}

/* --- Pager --- */
.blog-pager {
  max-width: 600px; margin: clamp(40px, 5vw, 64px) auto 0;
  display: flex; justify-content: center; gap: 10px;
}
.blog-pager__item {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 40px; height: 40px; padding: 0 12px;
  border: 1px solid rgba(255,255,255,.2);
  color: var(--c-cream);
  font-size: 14px;
  transition: background var(--tr-fast), border-color var(--tr-fast);
}
.blog-pager__item:hover:not(.is-current) {
  background: rgba(255,255,255,.06);
  border-color: rgba(255,255,255,.4);
}
.blog-pager__item.is-current {
  background: var(--c-cream);
  color: var(--c-ink);
  border-color: var(--c-cream);
}

/* --- FAQ accordions (native <details>/<summary>) --- */
.blog-faq-section { padding-top: clamp(48px, 6vw, 80px); padding-bottom: clamp(64px, 8vw, 100px); }
.blog-faq {
  max-width: 800px; margin: 0 auto;
  display: flex; flex-direction: column;
}
.blog-faq__item {
  border-top: 1px solid rgba(255,255,255,.12);
}
.blog-faq__item:last-child { border-bottom: 1px solid rgba(255,255,255,.12); }
.blog-faq__q {
  cursor: pointer;
  list-style: none;              /* strip the default triangle */
  padding: 20px 0;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  font-family: var(--f-serif); font-size: 1.5rem; font-weight: 500;
  line-height: 1.25;
  color: var(--c-cream);
  transition: color var(--tr-fast);
}
.blog-faq__q::-webkit-details-marker { display: none; }
.blog-faq__q:hover { color: var(--c-sand); }
/* The h3 inside <summary> should visually be part of the row — reset the
   browser's default heading font-size/weight/margin so it inherits from the
   summary's flex line instead of stacking as a separate block. */
.blog-faq__q-title { margin: 0; font: inherit; font-weight: inherit; color: inherit; }
.blog-faq__chevron {
  display: inline-flex; align-items: center; justify-content: center;
  /* Explicit box + flex-shrink:0 — without these, a long question that wraps
     to two lines squeezes the chevron span down (svg { max-width: 100% } in
     the reset lets the icon actually shrink), producing the mismatched sizes
     between short-question and long-question rows. */
  flex: 0 0 auto;
  width: 24px; height: 24px;
  transition: transform var(--tr-fast);
}
.blog-faq__chevron svg { width: 16px; height: 16px; flex: 0 0 auto; }
/* Belt-and-braces: keep the h3 from stealing every last pixel of the row. */
.blog-faq__q-title { min-width: 0; }
.blog-faq__item[open] .blog-faq__chevron { transform: rotate(180deg); }
.blog-faq__a {
  padding: 0 0 20px;
  color: rgba(246,239,226,.75);
  font-size: 16px; line-height: 1.65;
}
.blog-faq__a p { margin: 0; }

/* --- Single post --- */
.blog-single {
  padding: calc(var(--nav-h) + 40px) clamp(20px, 4vw, 48px) clamp(64px, 8vw, 100px);
  background: var(--c-ink);
  color: var(--c-cream);
}
.blog-single__cover {
  max-width: 1000px;
  margin: 0 auto clamp(32px, 4vw, 56px);
  aspect-ratio: 16 / 9;
  background: var(--c-ink-2);
  overflow: hidden;
}
.blog-single__cover img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.blog-single__header {
  max-width: 720px; margin: 0 auto clamp(32px, 4vw, 48px);
  text-align: center;
}
.blog-single__header .eyebrow a { color: inherit; border-bottom: 1px solid transparent; transition: border-color var(--tr-fast); }
.blog-single__header .eyebrow a:hover { border-color: var(--c-sand); }
.blog-single__title {
  font-family: var(--f-serif);
  font-size: clamp(30px, 4vw, 48px);
  line-height: 1.1; font-weight: 500;
  margin: 12px 0 16px;
}
.blog-single__meta {
  margin: 0 0 20px;
  font-size: 13px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--c-sand);
  display: flex; justify-content: center; gap: 8px;
}
.blog-single__excerpt {
  font-family: var(--f-serif); font-style: italic;
  font-size: clamp(17px, 1.6vw, 20px); line-height: 1.55;
  color: rgba(246,239,226,.82);
  max-width: 58ch; margin: 0 auto;
}
/* Split body + sidebar. When there's no sidebar (no related/latest data)
   the body keeps its old max-width via .blog-single__layout (no --split). */
.blog-single__layout { max-width: 720px; margin: 0 auto; }
.blog-single__layout--split {
  /* Cap at 1300 — middle ground between too-narrow reading column and
     stretched-across-4k-screen. Body column lands ~900px, sidebar 320px. */
  max-width: 1300px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
.blog-single__body {
  font-size: 17px; line-height: 1.75;
  color: rgba(246,239,226,.86);
  min-width: 0;
}
/* Sidebar stacks under body on tablet/mobile. `minmax(0, 1fr)` (not the
   bare `1fr` = `minmax(auto, 1fr)`) lets the column shrink below any child's
   intrinsic min-content — otherwise an unbreakable string, a wide inline image,
   or an embedded iframe in admin-authored body HTML blows the grid past the
   viewport width. That produced the "huge cream rectangle" bug: the sidebar
   block stretched to the widened grid, spilling out of the viewport and
   forcing a horizontal scroll on the whole page. */
@media (max-width: 900px) {
  .blog-single__layout--split { grid-template-columns: minmax(0, 1fr); }
  .blog-single__body,
  .blog-side { min-width: 0; }
  /* Belt-and-braces against admin-authored HTML overflow. */
  .blog-single__body { overflow-wrap: anywhere; word-break: break-word; }
  .blog-single__body iframe,
  .blog-single__body video,
  .blog-single__body embed,
  .blog-single__body object { max-width: 100%; }
  .blog-single__body pre { overflow-x: auto; max-width: 100%; }
}
.blog-single__body h2 {
  font-family: var(--f-serif);
  font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 500;
  margin: 48px 0 16px;
  color: var(--c-cream);
}
.blog-single__body h3 {
  font-family: var(--f-serif);
  font-size: clamp(20px, 2vw, 24px);
  font-weight: 500;
  margin: 32px 0 12px;
  color: var(--c-cream);
}
.blog-single__body p { margin: 0 0 20px; }
.blog-single__body ul,
.blog-single__body ol { margin: 0 0 20px; padding-left: 1.4em; }
.blog-single__body li { margin: 0 0 8px; }
.blog-single__body strong { color: var(--c-cream); font-weight: 600; }
.blog-single__body a {
  color: var(--c-sand);
  border-bottom: 1px solid rgba(201,177,142,.35);
  transition: color var(--tr-fast), border-color var(--tr-fast);
}
.blog-single__body a:hover { color: var(--c-cream); border-color: var(--c-cream); }
.blog-single__body img {
  width: 100%; height: auto;
  margin: 32px 0;
  background: var(--c-ink-2);
}
.blog-single__body blockquote {
  margin: 32px 0;
  padding: 4px 0 4px 24px;
  border-left: 3px solid var(--c-sand);
  font-family: var(--f-serif); font-style: italic;
  color: rgba(246,239,226,.82);
}
/* Tables — small editorial style, horizontal scroll on narrow screens. */
.blog-single__body table {
  width: 100%;
  margin: 32px 0;
  border-collapse: collapse;
  font-size: 15px;
  display: block;
  overflow-x: auto;
}
.blog-single__body th,
.blog-single__body td {
  padding: 10px 14px;
  text-align: left;
  border-bottom: 1px solid rgba(255,255,255,.12);
}
.blog-single__body th {
  font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--c-sand);
  font-weight: 500;
}
.blog-single__footer {
  max-width: 720px; margin: clamp(48px, 6vw, 80px) auto 0;
  display: flex; gap: 14px; flex-wrap: wrap; justify-content: center;
}

/* --- Blog single sidebar (related courses + latest articles) ---
   Sticky on desktop so it stays useful as the reader scrolls the article. */
.blog-side {
  display: flex; flex-direction: column; gap: 24px;
  position: sticky; top: calc(var(--nav-h) + 20px);
  align-self: start;
}
@media (max-width: 900px) {
  .blog-side { position: static; }
}
.blog-side__block {
  padding: 20px 22px;
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.10);
}
.blog-side__h {
  margin: 0 0 14px;
  font-size: 12px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--c-sand);
  font-weight: 500;
}
.blog-side__courses,
.blog-side__latest { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }

/* --- Related course card in sidebar --- */
.blog-side__course {
  display: flex; gap: 12px; align-items: center;
  padding: 8px 8px 8px 0;
  color: var(--c-cream);
  border-left: 3px solid var(--sw, var(--c-sand));
  padding-left: 12px;
  transition: background var(--tr-fast), border-left-width var(--tr-fast);
}
.blog-side__course:hover { background: rgba(255,255,255,.05); }
.blog-side__course-img {
  width: 96px; height: 62px; flex: 0 0 auto;
  background: var(--c-ink-2) center / cover no-repeat;
}
.blog-side__course-img--flat { background: var(--sw, var(--c-sand)); opacity: .45; }
.blog-side__course-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.blog-side__course-name {
  font-family: var(--f-serif); font-size: 15px; font-weight: 500;
  line-height: 1.2;
}
.blog-side__course-tag {
  font-size: 12px;
  color: rgba(246,239,226,.62);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- Latest article row in sidebar --- */
.blog-side__latest-item {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 8px 0;
  color: var(--c-cream);
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.blog-side__latest li:last-child .blog-side__latest-item { border-bottom: 0; }
.blog-side__latest-item:hover .blog-side__latest-title { color: var(--c-sand); }
.blog-side__latest-img {
  width: 56px; height: 56px; flex: 0 0 auto;
  background: var(--c-ink-2) center / cover no-repeat;
}
.blog-side__latest-txt { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.blog-side__latest-title {
  font-family: var(--f-serif); font-size: 15px; font-weight: 500;
  line-height: 1.25;
  transition: color var(--tr-fast);
  /* Cap at 3 lines so the sidebar doesn't blow up on long titles. */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.blog-side__latest-date {
  font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--c-sand);
}

/* --- Light-theme mirror (blog-single flips to cream in the earlier block) --- */
:root[data-theme="light"] .blog-side__block { background: var(--c-cream-2); border-color: rgba(30,26,22,.10); }
:root[data-theme="light"] .blog-side__h { color: var(--c-wood-dk); }
:root[data-theme="light"] .blog-side__course,
:root[data-theme="light"] .blog-side__latest-item { color: var(--c-ink); }
:root[data-theme="light"] .blog-side__course-img { background-color: var(--c-cream); }
:root[data-theme="light"] .blog-side__course-tag { color: rgba(30,26,22,.62); }
:root[data-theme="light"] .blog-side__latest-item { border-bottom-color: rgba(30,26,22,.10); }
:root[data-theme="light"] .blog-side__latest-item:hover .blog-side__latest-title { color: var(--c-wood-dk); }
:root[data-theme="light"] .blog-side__latest-img { background-color: var(--c-cream); }
:root[data-theme="light"] .blog-side__latest-date { color: var(--c-wood-dk); }
:root[data-theme="light"] .blog-side__course:hover { background: rgba(30,26,22,.05); }

/* --- Light-theme overrides — mirror the inverted-hero pattern. --- */
:root[data-theme="light"] .blog-hero { background: var(--c-ink-2); color: var(--c-cream); }
:root[data-theme="light"] .blog-hero__lead { color: rgba(246,239,226,.72); }
:root[data-theme="light"] .blog-hero__figure { background: var(--c-cream-2); }
/* Light-theme figure keeps the cream-2 (light) background, so the caption
   also stays dark like the default. Prev override forced cream-colored text
   here which was invisible against the light figure. */
:root[data-theme="light"] .blog-card,
:root[data-theme="light"] .blog-card__cover { background-color: var(--c-cream); }
:root[data-theme="light"] .blog-card__title a:hover,
:root[data-theme="light"] .blog-card__more { color: var(--c-wood-dk); }
:root[data-theme="light"] .blog-card__meta { color: var(--c-wood-dk); }
:root[data-theme="light"] .blog-card__excerpt { color: rgba(30,26,22,.72); }
:root[data-theme="light"] .blog-card__cover-fallback { color: rgba(30,26,22,.25); }
:root[data-theme="light"] .blog-pager__item { color: var(--c-ink); border-color: rgba(30,26,22,.2); }
:root[data-theme="light"] .blog-pager__item:hover:not(.is-current) { background: rgba(30,26,22,.06); border-color: rgba(30,26,22,.4); }
:root[data-theme="light"] .blog-pager__item.is-current { background: var(--c-ink); color: var(--c-cream); border-color: var(--c-ink); }
:root[data-theme="light"] .blog-faq__item { border-top-color: rgba(30,26,22,.14); }
:root[data-theme="light"] .blog-faq__item:last-child { border-bottom-color: rgba(30,26,22,.14); }
:root[data-theme="light"] .blog-faq__q { color: var(--c-ink); }
:root[data-theme="light"] .blog-faq__q:hover { color: var(--c-wood-dk); }
:root[data-theme="light"] .blog-faq__a { color: rgba(30,26,22,.72); }
:root[data-theme="light"] .blog-single { background: var(--c-cream); color: var(--c-ink); }
:root[data-theme="light"] .blog-single__meta,
:root[data-theme="light"] .blog-single__body th { color: var(--c-wood-dk); }
:root[data-theme="light"] .blog-single__excerpt { color: rgba(30,26,22,.72); }
:root[data-theme="light"] .blog-single__body { color: rgba(30,26,22,.82); }
:root[data-theme="light"] .blog-single__body strong,
:root[data-theme="light"] .blog-single__body h2,
:root[data-theme="light"] .blog-single__body h3 { color: var(--c-ink); }
/* Footer ghost button: base rule is white text on white border which vanishes
   on the cream body — invert to ink text/border in light theme. Scoped to
   blog-single so we don't fight the hero-inverted rule on other pages. */
:root[data-theme="light"] .blog-single .btn--ghost {
  color: var(--c-ink); border-color: rgba(30,26,22,.45);
}
:root[data-theme="light"] .blog-single .btn--ghost:hover {
  background: rgba(30,26,22,.08); border-color: var(--c-ink); color: var(--c-ink);
}
:root[data-theme="light"] .blog-single__body a { color: var(--c-wood-dk); border-bottom-color: rgba(122,90,59,.35); }
:root[data-theme="light"] .blog-single__body a:hover { color: var(--c-ink); border-bottom-color: var(--c-ink); }
:root[data-theme="light"] .blog-single__body blockquote { border-left-color: var(--c-wood-dk); color: rgba(30,26,22,.72); }
:root[data-theme="light"] .blog-single__body th,
:root[data-theme="light"] .blog-single__body td { border-bottom-color: rgba(30,26,22,.14); }

/* ---------- Mobile sticky action bar ----------
   Fixed to the viewport bottom on narrow screens only. Two items: WhatsApp
   CTA (left) + tap-to-call phone number (right). JS toggles `.mcta--hidden`
   when the real footer intersects the viewport, so the bar never overlaps
   the footer's own contact info. */
.mcta { display: none; }
@media (max-width: 900px) {
  .mcta {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
    padding: 10px clamp(14px, 4vw, 20px);
    /* Respect the iOS home-bar safe area on notched devices so the bar sits
       ABOVE the system indicator, not underneath it. */
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
    background: rgba(18,16,14,.94);
    color: var(--c-cream);
    border-top: 1px solid rgba(255,255,255,.14);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: transform var(--tr-med), opacity var(--tr-med);
  }
  .mcta--hidden {
    transform: translateY(100%);
    opacity: 0;
    pointer-events: none;
  }
  .mcta__item {
    display: inline-flex; align-items: center; gap: 8px;
    font-size: 13px; letter-spacing: .04em;
    padding: 6px 4px;
    color: var(--c-cream);
    min-height: 44px;                /* Apple-recommended tap target */
  }
  .mcta__item .ico { width: 18px; height: 18px; flex: 0 0 auto; }
  /* WhatsApp CTA styled as a pill button — border + rounded corners + subtle
     bg make it read as tappable, so users don't mistake it for a label
     sitting next to the phone number. */
  .mcta__item--wa {
    font-weight: 500;
    padding: 8px 14px;
    background: rgba(37,211,102,.14);      /* faint WhatsApp-green wash */
    border: 1px solid rgba(37,211,102,.55);
    border-radius: 999px;
    color: #fff;
  }
  .mcta__item--wa .ico { color: #25d366; }   /* WhatsApp green, at-a-glance recognition */
  .mcta__item--tel { color: rgba(246,239,226,.85); font-variant-numeric: tabular-nums; }
  /* NOTE — deliberately NO padding to make room for the mcta bar.
     Previously the bar's height was reserved via `body { padding-bottom }`
     (which left dead space below the footer) or `main { padding-bottom }`
     (which left dead space between main's last section and the footer).
     Both were worse than the current trade-off: the bar covers the last
     ~64px of the final section until the user scrolls into the footer,
     at which point JS hides the bar (IntersectionObserver on .footer).
     If you ever want the reservation back, put it INSIDE main's last
     child so main's own bottom touches the footer with no gap. */
}

/* ---------- Footer ---------- */
.footer {
  background: #0c0b0a; color: var(--c-cream);
  padding: 50px clamp(20px, 4vw, 48px) 0;
  border-top: 1px solid var(--c-line);
}
.footer__inner {
  max-width: 1440px; margin: 0 auto;
  display: flex;
  align-items: flex-start;
  gap: clamp(28px, 4vw, 56px);          /* between the two text columns */
  padding-bottom: 64px;
}
/* Brand pushed to the right side with extra breathing room from the columns. */
.footer__col--brand {
  margin-left: auto;
  text-align: center;
}
.footer__brand {
  display: inline-flex; flex-direction: column; align-items: center;
  color: var(--c-cream);
  border-bottom: 0 !important;
}
/* Single-file vertical logo — footer stays dark in both themes, so the
   white variant is used unconditionally. Sized on width so the intrinsic
   ~8:5 aspect keeps the height in proportion. */
.footer__logo {
  display: block;
  width: 200px; height: auto;
  flex: 0 0 auto;
}

.footer__link {
  display: inline-flex; align-items: center; gap: 10px;
  border-bottom: 1px solid transparent;
}
.footer__link .ico { width: 16px; height: 16px; flex: 0 0 auto; color: var(--c-sand); }
.footer__link:hover .ico { color: var(--c-sand); }
.footer h4 {
  font-family: var(--f-sans);
  font-size: 12px; letter-spacing: .28em; text-transform: uppercase;
  color: var(--c-sand);
  margin: 0 0 16px;
  font-weight: 500;
}
.footer p { margin: 0 0 8px; font-size: 15px; color: rgba(246,239,226,.8); }
.footer a { color: var(--c-cream); border-bottom: 1px solid transparent; transition: border-color var(--tr-fast), color var(--tr-fast); }
.footer a:hover { color: var(--c-sand); border-color: var(--c-sand); }
.footer__bar {
  max-width: 1440px; margin: 0 auto;
  padding: 22px 0;
  border-top: 1px solid var(--c-line);
  display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap;
  font-size: 12.5px; letter-spacing: .12em;
  color: rgba(246,239,226,.55);
}
/* `flex-wrap: wrap` + `justify-content: center` + `white-space: nowrap` on the
   inner items lets each label (e.g. "Cookie Policy") stay together and wrap
   as a whole to the next line on narrow viewports — otherwise the words split
   mid-phrase and the row reads as a fragmented grid. */
.footer__bar-links {
  display: inline-flex; align-items: center; gap: 10px;
  flex-wrap: wrap; justify-content: center;
}
.footer__bar-links a {
  color: rgba(246,239,226,.75);
  border-bottom: 1px solid transparent;
  transition: border-color var(--tr-fast), color var(--tr-fast);
  white-space: nowrap;
}
.footer__bar-links a:hover { color: var(--c-cream); border-color: var(--c-sand); }
.footer__bar-links > span { color: rgba(246,239,226,.35); white-space: nowrap; }

/* Subtle divider before the "web agency" credit at the far right of the bar.
   Reads as "this is a separate credit, not another site link". */
.footer__bar-credit {
  position: relative;
  padding-left: 18px;
  margin-left: 4px;
}
.footer__bar-credit::before {
  content: "";
  position: absolute; left: 0; top: 50%;
  transform: translateY(-50%);
  width: 1px; height: 14px;
  background: rgba(246,239,226,.22);
}
@media (max-width: 900px) {
  /* Bar becomes a column on mobile — swap the vertical divider for a thin
     horizontal one above the credit so it reads as a break, not a bullet. */
  .footer__bar-credit { padding-left: 0; padding-top: 10px; margin-top: 2px; text-align: center; }
  .footer__bar-credit::before {
    left: 50%; top: 0; transform: translateX(-50%);
    width: 40px; height: 1px;
  }
}

/* =================================================================
   Reviews — homepage strip + dedicated /recensioni page
   Cards inspired by the standard business-review UI pattern (circle
   avatar + name + date + stars + text). Google G icon is used as a
   source-attribution mark only, not for branding.
   ================================================================= */

/* Page hero for /recensioni — mirrors .policy-hero / .studio-hero patterns
   so it inherits the site's editorial rhythm without duplication. */
.rec-hero {
  padding: calc(var(--nav-h) + 60px) clamp(20px, 4vw, 48px) 32px;
  background: var(--c-cream);
  color: var(--c-ink);
}
.rec-hero__inner { max-width: 900px; margin: 0 auto; text-align: center; }
.rec-hero__title {
  font-family: var(--f-serif);
  font-size: clamp(36px, 5vw, 60px);
  line-height: 1.05;
  font-weight: 500;
  margin: 0 auto 18px;
}
.rec-hero__lead {
  max-width: 62ch; margin: 0 auto 28px;
  color: rgba(30,26,22,.68);
  font-size: 16.5px;
}
.rec-hero__meta {
  display: inline-flex; align-items: center; gap: 14px;
  padding: 12px 20px;
  background: rgba(30,26,22,.04);
  border: 1px solid rgba(30,26,22,.10);
  border-radius: 999px;
  margin-bottom: 24px;
}
.rec-hero__score {
  font-family: var(--f-serif); font-size: 28px; font-weight: 500;
  color: var(--c-ink);
  line-height: 1;
}
.rec-hero__stars { display: inline-flex; gap: 2px; }
.rec-hero__count { font-size: 13px; color: rgba(30,26,22,.65); }
.rec-hero__ctas { display: flex; justify-content: center; gap: 12px; flex-wrap: wrap; }
.rec-hero__ctas .btn { display: inline-flex; align-items: center; gap: 10px; }

/* Grid layout — desktop 3 cols, tablet 2, mobile 1. Masonry via CSS grid
   `masonry` value is Firefox-only for now, so use a plain grid with rows
   auto-sizing to content and cards of variable height living side by side. */
.rec-grid {
  max-width: 1300px; margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 22px;
  align-items: start;
}
@media (max-width: 900px) { .rec-grid { grid-template-columns: repeat(2, 1fr); gap: 16px; } }
@media (max-width: 560px) { .rec-grid { grid-template-columns: 1fr; } }

/* Home strip variant — inherits colors from `.section--dark` (dark bg + cream
   text in dark theme; cream-2 bg + ink text in light theme). Top padding is
   tightened because the courses grid above already ends with the same
   `clamp(80px, 10vw, 140px)` — doubling reads as dead space between the two. */
.rec-strip { padding-top: clamp(24px, 3vw, 40px); }
.rec-strip__more { margin: clamp(28px, 4vw, 40px) 0 0; text-align: center; }
/* Homepage only — courses section ends flush with the reviews strip beneath.
   Trims the shared `.section { padding-bottom }` from the courses grid so the
   two sections don't double up on breathing room. */
#corsi { padding-bottom: clamp(32px, 4vw, 56px); }
/* Wide-screen side padding: above 1280px, expand horizontal padding beyond
   the base `.section { padding: … clamp(20px, 4vw, 48px) }` so the two big
   course cards don't fill nearly the whole viewport on 1440/1920 monitors.
   Linear from 48px at 1280 → 160px at 1920, capped beyond. Below 1280 the
   base `.section` padding still applies. */
@media (min-width: 1280px) {
  #corsi {
    padding-left:  clamp(48px, calc(48px + (100vw - 1280px) * 0.175), 160px);
    padding-right: clamp(48px, calc(48px + (100vw - 1280px) * 0.175), 160px);
  }
}

/* --- Card --- */
.review {
  position: relative;
  padding: 20px 20px 16px;
  background: #fff;
  border: 1px solid rgba(30,26,22,.10);
  border-radius: 12px;
  color: var(--c-ink);
  box-shadow: 0 1px 2px rgba(30,26,22,.04);
  display: flex; flex-direction: column;
  min-width: 0;
}
.review__head {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 10px;
  padding-right: 28px;   /* room for the corner Google G */
}
.review__avatar {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
  font-family: var(--f-sans);
  font-weight: 500;
  font-size: 18px;
  letter-spacing: 0;
}
.review__id { min-width: 0; flex: 1 1 auto; }
.review__name {
  margin: 0; font-weight: 600; font-size: 15px;
  color: var(--c-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.review__date {
  margin: 2px 0 0; font-size: 12.5px;
  color: rgba(30,26,22,.55);
}
.review__source {
  position: absolute; top: 16px; right: 16px;
  width: 20px; height: 20px;
  opacity: .9;
}
.review__stars { display: inline-flex; gap: 2px; margin: 0 0 10px; color: var(--c-ink); }
.review__text {
  margin: 0;
  font-size: 14.5px; line-height: 1.55;
  color: rgba(30,26,22,.82);
  overflow-wrap: anywhere;
}

/* Line-clamp for the homepage strip — the "Leggi di più" summary flips the
   clamp off when the <details> is open. Only applied when NOT expanded. */
.review:not(.review--expanded) .review__text {
  display: -webkit-box;
  -webkit-line-clamp: 6;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.review:not(.review--expanded) .review__more[open] ~ .review__text,
.review:not(.review--expanded) .review__more[open] {}
.review__more {
  margin-top: 8px;
  font-size: 13px;
}
.review__more summary {
  cursor: pointer;
  list-style: none;
  color: var(--c-wood-dk);
  border-bottom: 1px solid transparent;
  display: inline-block;
  padding-bottom: 2px;
  transition: border-color var(--tr-fast), color var(--tr-fast);
}
.review__more summary::-webkit-details-marker { display: none; }
.review__more summary:hover { color: var(--c-ink); border-bottom-color: var(--c-wood-dk); }
.review__more[open] summary { color: rgba(30,26,22,.5); }
/* When the details is open, un-clamp the text sibling. We use the parent
   selector `.review:has()` for the toggle to work purely in CSS. Falls back
   silently on older engines — text stays clamped there. */
.review:has(.review__more[open]) .review__text {
  -webkit-line-clamp: unset;
  overflow: visible;
  display: block;
}
.review:has(.review__more[open]) .review__more summary::before { content: 'Chiudi'; }
.review:has(.review__more[open]) .review__more summary { font-size: 0; }
.review:has(.review__more[open]) .review__more summary::before { font-size: 13px; }

/* --- Dark section variant — cards on dark bg (e.g. /recensioni grid section)
     use lighter fills so they still read as cards against the ink background. */
.section--dark .review {
  background: rgba(255,255,255,.05);
  border-color: rgba(255,255,255,.12);
  color: var(--c-cream);
  box-shadow: none;
}
.section--dark .review__name { color: var(--c-cream); }
.section--dark .review__date { color: rgba(246,239,226,.55); }
.section--dark .review__text { color: rgba(246,239,226,.85); }
.section--dark .review__stars { color: rgba(255,255,255,.25); }
.section--dark .review__more summary { color: var(--c-sand); }
.section--dark .review__more summary:hover { color: var(--c-cream); border-bottom-color: var(--c-sand); }
/* Google G icon is a multi-color asset; on dark bg it still reads fine but
   a subtle whitening makes it feel less "sticker-slapped-on". */
.section--dark .review__source { opacity: .95; }

/* --- Light theme — cards go DARK on the cream body so they don't melt into
     the surface. Applies to both `.rec-strip` and `.rec-list-section` since
     `.section--dark` flips to cream-2 in light theme (see the light-theme
     mirror block below), and translucent-white-on-cream is invisible. */
:root[data-theme="light"] .review,
:root[data-theme="light"] .section--dark .review {
  background: rgba(0,0,0,.88);
  border-color: rgba(0,0,0,.10);
  color: var(--c-cream);
  box-shadow: 0 1px 2px rgba(30,26,22,.06);
}
:root[data-theme="light"] .review__name { color: var(--c-cream); }
:root[data-theme="light"] .review__date { color: rgba(246,239,226,.55); }
:root[data-theme="light"] .review__text { color: rgba(246,239,226,.86); }
:root[data-theme="light"] .review__stars { color: rgba(255,255,255,.25); }
:root[data-theme="light"] .review__more summary { color: var(--c-sand); }
:root[data-theme="light"] .review__more summary:hover { color: var(--c-cream); border-bottom-color: var(--c-sand); }

/* =================================================================
   Policy pages (Privacy Policy + Cookie Policy)
   ================================================================= */
.policy-hero {
  padding: calc(var(--nav-h) + 56px) clamp(20px, 4vw, 48px) 20px;
  background: var(--c-cream);
  color: var(--c-ink);
}
.policy-hero__inner { max-width: 900px; margin: 0 auto; text-align: center; }
.policy-hero__title {
  font-family: var(--f-serif);
  font-size: clamp(34px, 4.4vw, 52px);
  line-height: 1.05;
  font-weight: 500;
  margin: 0 auto 14px;
}
.policy-hero__lead {
  max-width: 60ch; margin: 0 auto;
  color: rgba(30,26,22,.68);
  font-size: 16px;
}
.policy { padding-top: 40px; padding-bottom: clamp(48px, 6vw, 80px); }
.policy__body {
  max-width: 780px; margin: 0 auto;
  font-size: 16px; line-height: 1.65;
}
.policy__body h2 {
  margin: 32px 0 12px;
  font-family: var(--f-serif); font-size: 24px; font-weight: 500;
  color: var(--c-cream);
}
.policy__body h2:first-child { margin-top: 0; }
.policy__body p, .policy__body ul { margin: 0 0 14px; color: rgba(246,239,226,.86); }
.policy__body ul { padding-left: 22px; }
.policy__body ul li { margin-bottom: 4px; }
.policy__body a { color: var(--c-sand); border-bottom: 1px solid rgba(201,177,142,.35); }
.policy__body a:hover { color: var(--c-cream); border-color: var(--c-cream); }
.policy__updated { margin-top: 32px; color: rgba(246,239,226,.5); font-size: 13px; letter-spacing: .04em; }

/* light-theme adjustments for policy pages */
:root[data-theme="light"] .policy-hero { background: var(--c-ink-2); color: var(--c-cream); }
:root[data-theme="light"] .policy-hero__lead { color: rgba(246,239,226,.72); }
:root[data-theme="light"] .policy__body h2 { color: var(--c-ink); }
:root[data-theme="light"] .policy__body p,
:root[data-theme="light"] .policy__body ul { color: rgba(30,26,22,.82); }
:root[data-theme="light"] .policy__body a { color: var(--c-wood-dk); border-color: rgba(122,90,59,.35); }
:root[data-theme="light"] .policy__body a:hover { color: var(--c-ink); border-color: var(--c-ink); }
:root[data-theme="light"] .policy__updated { color: rgba(30,26,22,.55); }

/* =================================================================
   Cookie consent banner (bottom-right)
   ================================================================= */
.cookie-banner {
  position: fixed;
  bottom: 20px; right: 20px; left: 20px;
  z-index: 90;                          /* below the cdet overlay (100) */
  max-width: 560px;
  margin-left: auto;
  background: var(--c-ink);
  color: var(--c-cream);
  border: 1px solid rgba(255,255,255,.14);
  box-shadow: 0 20px 60px rgba(0,0,0,.4);
  padding: 20px 22px;
}
.cookie-banner[hidden] { display: none; }
.cookie-banner__text {
  margin: 0 0 14px;
  font-size: 14px;
  line-height: 1.55;
  color: rgba(246,239,226,.9);
}
.cookie-banner__text a { color: var(--c-sand); border-bottom: 1px solid rgba(201,177,142,.4); }
.cookie-banner__text a:hover { color: var(--c-cream); border-color: var(--c-cream); }
.cookie-banner__actions { display: flex; justify-content: flex-end; gap: 10px; }
.cookie-banner__actions .btn { padding: 10px 20px; font-size: 12px; }
/* Primary button on dark banner: cream body, ink text — same as hero .btn--primary.
   Repeated under [data-theme="light"] with matching specificity so the global
   light-theme .btn--primary rule (which flips to ink bg for cream sections)
   doesn't reach into the banner (which stays dark in both themes). */
.cookie-banner__actions .btn--primary,
:root[data-theme="light"] .cookie-banner__actions .btn--primary {
  background: var(--c-cream); color: var(--c-ink); border-color: var(--c-cream);
}
.cookie-banner__actions .btn--primary:hover,
:root[data-theme="light"] .cookie-banner__actions .btn--primary:hover {
  background: var(--c-wood); color: var(--c-cream); border-color: var(--c-wood);
}
/* Explicit `background: transparent` — otherwise the browser default
   `<button>` grey (#f0f0f0) leaked through against the dark banner. */
.cookie-banner__actions .btn--ghost       { background: transparent; color: var(--c-cream); border-color: rgba(255,255,255,.35); }
.cookie-banner__actions .btn--ghost:hover { background: rgba(255,255,255,.1); border-color: #fff; }

@media (max-width: 720px) {
  .cookie-banner {
    left: 12px; right: 12px; bottom: 12px;
    padding: 16px;
  }
  .cookie-banner__actions .btn { flex: 1; }
}

/* ---------- Responsive ---------- */
@media (max-width: 900px) {
  .courses { grid-template-columns: 1fr; gap: 22px; }

  /* ---- Homepage cards: portrait/vertical on mobile ----
     Same overall pattern as desktop — full-cover image with text overlaid,
     absolute .course__body, absolute .course__cta-slot — just re-proportioned
     for a tall-portrait card. Reveal (tagline+desc) is expanded at rest and
     the CTA is pinned in view because touch has no hover state. */
  .course { aspect-ratio: 4 / 5; }
  /* Smooth the scroll-driven parallax on mobile — see the JS note; mobile
     browsers batch scroll events during inertial deceleration, so a direct
     scroll→transform link snaps. A short CSS ease interpolates between the
     batches. Desktop keeps the un-transitioned, scroll-linked feel. */
  .course__img-wrap { transition: transform 260ms cubic-bezier(.22, .7, .2, 1); }
  .course__reveal    { grid-template-rows: 1fr; opacity: 1; }
  .course__reveal-inner { padding-top: 10px; padding-bottom: 8px; }
  .course__desc      { display: none; }
  /* Deeper bottom-only gradient — bigger dark band under the title/meta area
     so the white text stays legible over any image, and darker at the very
     bottom so the pill CTA reads confidently. */
  .course__scrim {
    background:
      linear-gradient(180deg,
        rgba(18,16,14,0)     0%,
        rgba(18,16,14,.36)  35%,
        rgba(0,0,0,.55)     70%,
        rgba(0,0,0,.90)    100%);
  }
  .course__scrim::after { display: none; }   /* no hover-darken on touch */

  /* Kill the global `a:hover { color: var(--c-wood) }` inheritance on the
     course link — on mobile there's no image-darken-on-hover to make the
     warm-tone shift feel intentional; the title just looks like it blends
     into the image. Keep everything white on hover/focus/active. */
  .course .course__link,
  .course .course__link:hover,
  .course .course__link:focus,
  .course .course__link:active,
  .course .course__link:hover .course__title,
  .course .course__link:focus .course__title { color: #fff; }

  /* Hero on mobile — hide the primary/whatsapp CTAs (redundant: the mcta
     sticky bar carries the WhatsApp CTA already, and "I nostri corsi" is
     one thumb-flick below the hero). Also shrink the hero so it exactly
     fits the visible viewport ABOVE the sticky mcta bar — otherwise the
     scroll-down arrow sits behind the bar. mcta height ≈ 64px + iOS
     safe-area inset. */
  .hero__ctas { display: none; }
  /* Lead's bottom margin only paid for the gap before the CTAs — now that
     those are hidden, drop it so the hero text ends cleanly at the padding. */
  .hero__lead { margin-bottom: 0; }
  .hero {
    min-height: calc(100vh  - 64px - env(safe-area-inset-bottom, 0px));
    min-height: calc(100svh - 64px - env(safe-area-inset-bottom, 0px));
  }
  /* CTA sits inline at the bottom, centered, with generous breathing room from
     the card edge. Overrides the desktop translate-off-screen rule. */
  .course__cta-slot {
    transform: translateY(0);
    padding: 18px clamp(20px, 4vw, 32px) 24px;
    justify-content: center;
  }
  .course__cta {
    padding: 12px 24px;
    font-size: 12px; letter-spacing: .2em;
  }
  /* Reserve enough padding-bottom on the body so meta + title clear the CTA
     comfortably (CTA is ~62px tall including its own padding). */
  .course__body,
  .course:hover .course__body,
  .course:focus-within .course__body {
    padding: clamp(28px, 5vw, 40px) clamp(22px, 4vw, 32px);
    padding-bottom: calc(clamp(22px, 4vw, 32px) + 78px);
  }
  .course__meta { justify-content: center; gap: 16px; }

  /* Course-detail overlay — schedule slots laid out 2-per-row on mobile.
     Columns are sized to content (`max-content`) and packed to the start —
     `1fr 1fr` stretched each cell to half the row width and left dead space
     after the text. Dots come from CSS on `.cdet__slot:not(:last-child)`;
     suppress the dot on every 2nd slot so no dot floats at end-of-row. */
  .cdet__sched-row dd {
    display: grid;
    grid-template-columns: max-content max-content;
    justify-content: start;
    /* NO column-gap here — the dot pseudo-element already provides symmetric
       .6em margins on both sides. Adding a column-gap would double the space
       after the dot (margin + gap) but leave the pre-dot side untouched. */
    column-gap: 0;
    row-gap: 4px;
  }
  .cdet__sched-row dd .cdet__slot:nth-child(2n)::after { content: none; }

  /* ---- Nav ---- */
  .nav__links { display: none; }
  .nav__cta { display: none; }
  .nav__theme { display: none; }   /* moved into the burger menu on mobile */
  .nav__burger { display: inline-flex; margin-left: auto; }
  /* Full-height dropdown so the menu covers the viewport (blank space below
     the links is intentional — no distracting page content peeking through). */
  .nav.is-open .nav__links {
    display: flex; flex-direction: column;
    position: fixed; top: var(--nav-h); left: 0; right: 0;
    height: calc(100vh - var(--nav-h));
    height: calc(100dvh - var(--nav-h));
    background: rgba(18,16,14,.98);
    padding: 32px clamp(20px, 4vw, 48px);
    gap: 20px;
    align-items: stretch;
    overflow-y: auto;
  }
  .nav.is-open .nav__links a { font-size: 18px; padding: 10px 0; }
  .nav.is-open .nav__burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav.is-open .nav__burger span:nth-child(2) { opacity: 0; }
  .nav.is-open .nav__burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  /* Mobile theme toggle — pill switch pinned to the bottom of the menu.
     `margin-top: auto` shoves it to the end of the flex column regardless of
     how many links exist. Visible only inside the open menu. */
  .nav__theme-mobile {
    margin-top: auto;
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px;
    padding: 16px 4px 8px;
    background: transparent;
    border: 0;
    border-top: 1px solid rgba(255,255,255,.12);
    color: #fff;
    cursor: pointer;
    font: inherit;
  }
  .nav__theme-mobile-label {
    font-size: 13px; letter-spacing: .22em; text-transform: uppercase;
    color: rgba(255,255,255,.7);
  }
  .nav__theme-mobile-switch {
    position: relative;
    display: inline-flex; align-items: center; justify-content: space-between;
    width: 68px; height: 30px;
    padding: 0 6px;
    background: rgba(255,255,255,.10);
    border: 1px solid rgba(255,255,255,.20);
    border-radius: 999px;
  }
  .nav__theme-mobile-ico {
    display: inline-flex; align-items: center; justify-content: center;
    width: 16px; height: 16px;
    color: rgba(255,255,255,.6);
    z-index: 1;
  }
  .nav__theme-mobile-knob {
    position: absolute; top: 3px; left: 3px;
    width: 22px; height: 22px;
    background: var(--c-sand);
    border-radius: 50%;
    transition: transform var(--tr-fast);
  }
  /* Knob indicates the CURRENT theme (the icon the knob covers).
     Default (dark, or no attribute yet) → knob on RIGHT over the moon.
     Light theme                          → knob on LEFT  over the sun.
     Match icon color under the knob to ink (readable on sand knob);
     the un-covered icon stays muted white. */
  .nav__theme-mobile-knob { transform: translateX(38px); }               /* default: dark → moon side */
  .nav__theme-mobile-ico--moon { color: var(--c-ink); }
  :root[data-theme="light"] .nav__theme-mobile-knob { transform: translateX(0); }
  :root[data-theme="light"] .nav__theme-mobile-ico--moon { color: rgba(255,255,255,.6); }
  :root[data-theme="light"] .nav__theme-mobile-ico--sun  { color: var(--c-ink); }

  /* NOTE — the light-theme override for open-menu text colors lives further
     down in the file (after the `.nav.nav--solid` / `.nav.is-scrolled` /
     `body.cdet-open .nav` light-theme block), because those rules paint the
     top-bar links ink-dark and match this rule's specificity. Placing the
     override after them in source order is what actually makes it win. */

  /* Mobile: brand first (top-center), text columns beneath, both left-aligned. */
  .footer__inner {
    flex-direction: column;
    align-items: stretch;
    gap: 28px;
  }
  .footer__col--brand {
    order: -1;
    margin-left: 0;
    align-self: center;
    margin-bottom: 16px;    /* extra breathing room before "Dove siamo" */
  }
  .footer__bar { flex-direction: column; gap: 8px; }

}

/* ---------- Tablet tier (portrait tablets, ~600–900px) ----------
   Full mobile treatment stays in effect (burger nav, portrait cards with
   always-visible CTA, mcta bar) — those all read fine at tablet size. The
   ONE thing that doesn't is the 1-per-row homepage courses grid: a 4:5
   portrait card at ~800px viewport width is ~1000px tall, filling more
   than the visible viewport. Restore 2 columns here so cards stay a
   comfortable size, and give the footer text columns 2-up instead of
   the phone-style stack so the tablet doesn't feel like a giant phone. */
@media (min-width: 601px) and (max-width: 900px) {
  .courses { grid-template-columns: repeat(2, 1fr); gap: 20px; }

  /* Footer text columns 2-up on tablet; brand stays centered above them. */
  .footer__inner {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 32px 40px;
  }
  .footer__col--brand {
    grid-column: 1 / -1;   /* full width, sits above the 2-col text block */
    order: -1;
  }
}

/* Hide the mobile theme toggle on desktop — it lives inside .nav__links,
   which desktop shows inline, so without this the pill switch would sit
   alongside the top-bar nav links. */
@media (min-width: 901px) {
  .nav__theme-mobile { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  .course__img, .hero__media { transform: none !important; }
}

/* =================================================================
   LIGHT THEME — applied when <html data-theme="light">.
   Home hero photo, course cards, and course-detail overlay stay dark
   on purpose (they're photo-first surfaces that need dark scrims).
   The mobile burger menu also stays dark for readability.
   ================================================================= */
:root[data-theme="light"] body {
  background: var(--c-cream);
  color: var(--c-ink);
}

/* All the "dark section" containers flip to a slightly darker beige than
   the body — gives sections a subtle "panel" boundary in light mode. */
:root[data-theme="light"] .section--dark {
  background: var(--c-cream-2);
  color: var(--c-ink);
}
/* Swap in the light-bg deco + `darken` blend so only the dark-brown lines
   survive over the cream section bg (mirror of the dark-theme setup above).
   Half the opacity of the dark theme — dark lines on cream read stronger
   per-pixel than gold lines on ink, so they need less presence to feel equal. */
:root[data-theme="light"] .section--dark::before {
  background-image: url('../images/deco/decorative-elements-light.webp');
  mix-blend-mode: darken;
  opacity: .1;
}
:root[data-theme="light"] .section__lead   { color: rgba(30, 26, 22, .68); }
:root[data-theme="light"] .section__title  { color: var(--c-ink); }
:root[data-theme="light"] .eyebrow         { color: var(--c-wood-dk); }
/* Light-theme heros flip to dark bg — wood-dk on ink would be invisible,
   so restore sand there (mirror of the default override for cream heros). */
:root[data-theme="light"] .corsi-hero .eyebrow,
:root[data-theme="light"] .studio-hero .eyebrow,
:root[data-theme="light"] .contatti-hero .eyebrow,
:root[data-theme="light"] .rec-hero .eyebrow,
:root[data-theme="light"] .policy-hero .eyebrow,
:root[data-theme="light"] .blog-hero .eyebrow { color: var(--c-sand); }

/* Nav — solid state uses cream bg + ink text. Applies to any of the three
   triggers (`is-scrolled`, `nav--solid` for non-home pages, or `cdet-open`).
   The transparent state (over the dark home hero photo) keeps white text. */
:root[data-theme="light"] .nav.is-scrolled,
:root[data-theme="light"] .nav.nav--solid,
:root[data-theme="light"] body.cdet-open .nav {
  background: rgba(246,239,226,.94);
  border-bottom-color: rgba(30,26,22,.14);
  backdrop-filter: blur(10px);
}
/* `body.cdet-open .nav` also has to match every child-color rule below.
   When the FLIP overlay opens, lockBody() sets `body { position: fixed }` and
   window.scrollY becomes 0, which triggers the scroll listener to remove
   `.is-scrolled`. On the home page there's no `.nav--solid` either, so
   without this selector the light-theme text falls back to the base white on
   the cream cdet-open bg — invisible.
   /corsi has `.nav--solid` server-side, so it never hit this bug. */
:root[data-theme="light"] .nav.is-scrolled .nav__brand,
:root[data-theme="light"] .nav.is-scrolled .nav__links a,
:root[data-theme="light"] .nav.is-scrolled .nav__theme,
:root[data-theme="light"] .nav.is-scrolled .nav__cta,
:root[data-theme="light"] .nav.nav--solid .nav__brand,
:root[data-theme="light"] .nav.nav--solid .nav__links a,
:root[data-theme="light"] .nav.nav--solid .nav__theme,
:root[data-theme="light"] .nav.nav--solid .nav__cta,
:root[data-theme="light"] body.cdet-open .nav .nav__brand,
:root[data-theme="light"] body.cdet-open .nav .nav__links a,
:root[data-theme="light"] body.cdet-open .nav .nav__theme,
:root[data-theme="light"] body.cdet-open .nav .nav__cta {
  color: var(--c-ink);
}
:root[data-theme="light"] .nav.is-scrolled .nav__brand-sep,
:root[data-theme="light"] .nav.nav--solid .nav__brand-sep,
:root[data-theme="light"] body.cdet-open .nav .nav__brand-sep { color: var(--c-wood-dk); }
:root[data-theme="light"] .nav.is-scrolled .nav__links a::after,
:root[data-theme="light"] .nav.nav--solid .nav__links a::after,
:root[data-theme="light"] body.cdet-open .nav .nav__links a::after { background: var(--c-wood-dk); }
:root[data-theme="light"] .nav.is-scrolled .nav__links a:hover,
:root[data-theme="light"] .nav.is-scrolled .nav__links a.is-active,
:root[data-theme="light"] .nav.nav--solid .nav__links a:hover,
:root[data-theme="light"] .nav.nav--solid .nav__links a.is-active,
:root[data-theme="light"] body.cdet-open .nav .nav__links a:hover,
:root[data-theme="light"] body.cdet-open .nav .nav__links a.is-active { color: var(--c-wood-dk); }
/* CTA + theme toggle are borderless now (base rule). Light-theme still needs
   the hover-fill inverted so the CTA reads on cream. Theme toggle gets a
   subtle ink tint on hover. */
:root[data-theme="light"] .nav.is-scrolled .nav__cta:hover,
:root[data-theme="light"] .nav.nav--solid .nav__cta:hover,
:root[data-theme="light"] body.cdet-open .nav .nav__cta:hover {
  background: var(--c-ink); color: var(--c-cream);
}
:root[data-theme="light"] .nav.is-scrolled .nav__theme:hover,
:root[data-theme="light"] .nav.nav--solid .nav__theme:hover,
:root[data-theme="light"] body.cdet-open .nav .nav__theme:hover {
  background: rgba(30,26,22,.08);
}
:root[data-theme="light"] .nav.is-scrolled .nav__burger span,
:root[data-theme="light"] .nav.nav--solid .nav__burger span,
:root[data-theme="light"] body.cdet-open .nav .nav__burger span { background: var(--c-ink); }

/* Mobile burger dropdown ALWAYS has a dark backdrop (see the mobile @media
   block above). Override the light-theme `.nav.is-scrolled` / `.nav--solid` /
   `body.cdet-open` rules that would paint the dropdown's links + toggle
   ink-dark and make them vanish against the dark bg. Placed here in source
   order so it wins the specificity tie with those earlier rules. Wrapped in
   the mobile media query because the dropdown only exists at that width. */
@media (max-width: 900px) {
  :root[data-theme="light"] .nav.is-open .nav__links a,
  :root[data-theme="light"] .nav.is-open .nav__links a.is-active,
  :root[data-theme="light"] .nav.is-open .nav__theme-mobile {
    color: #fff;
  }
  :root[data-theme="light"] .nav.is-open .nav__theme-mobile-label {
    color: rgba(255,255,255,.7);
  }
}

/* Swap brand SVGs to the black variants on cream nav backgrounds. Same
   `cdet-open` fix as the text-color rules above — the FLIP animation zeros
   scrollY and removes .is-scrolled, so without cdet-open here the white
   variants would flash back on the cream cdet-open nav. */
/* Light-theme + solid nav bg (scrolled, nav--solid on non-home pages, or the
   cdet-open flash): swap WHITE logo → BLACK logo. Same three-trigger list
   the rest of the light-theme nav rules use. */
:root[data-theme="light"] .nav.is-scrolled .nav__logo--white,
:root[data-theme="light"] .nav.nav--solid .nav__logo--white,
:root[data-theme="light"] body.cdet-open .nav .nav__logo--white { display: none; }
:root[data-theme="light"] .nav.is-scrolled .nav__logo--black,
:root[data-theme="light"] .nav.nav--solid .nav__logo--black,
:root[data-theme="light"] body.cdet-open .nav .nav__logo--black { display: block; }

/* --- /corsi weekly grid + course list --- */
:root[data-theme="light"] .corsi-hero { background: var(--c-ink-2); color: var(--c-cream); }
:root[data-theme="light"] .corsi-hero__lead { color: rgba(246,239,226,.72); }
:root[data-theme="light"] .weekgrid-scroll { border-color: rgba(30,26,22,.15); }
:root[data-theme="light"] .weekgrid { color: var(--c-ink); }
:root[data-theme="light"] .weekgrid thead th {
  background: var(--c-cream-2);
  color: var(--c-wood-dk);
  border-bottom-color: rgba(30,26,22,.2);
}
:root[data-theme="light"] .weekgrid tbody th.weekgrid__time {
  background: rgba(0,0,0,.03);
  color: var(--c-ink);
  border-right-color: rgba(30,26,22,.12);
  border-bottom-color: rgba(30,26,22,.12);
}
:root[data-theme="light"] .weekgrid tbody td {
  border-right-color: rgba(30,26,22,.12);
  border-bottom-color: rgba(30,26,22,.12);
}
/* Slot chips read best with DARK text on their pastel-tinted backgrounds in
   light mode. The base rule already uses `color-mix(var(--slot-color) 24%,
   transparent)` so on cream-2 that becomes a pastel wash — dark ink text
   has plenty of contrast on it. */
:root[data-theme="light"] .weekgrid__slot,
:root[data-theme="light"] .weekgrid__slot:hover {
  color: var(--c-ink);
}
:root[data-theme="light"] .weekgrid__slot-time { color: rgba(30,26,22,.65); }
:root[data-theme="light"] .corso-row       { border-top-color: rgba(30,26,22,.12); }
:root[data-theme="light"] .corso-row__tag  { color: var(--c-wood-dk); }
:root[data-theme="light"] .corso-row__desc { color: rgba(30,26,22,.75); }
:root[data-theme="light"] .corso-row__meta-item { color: rgba(30,26,22,.82); }
:root[data-theme="light"] .corso-row__meta-item svg { color: var(--c-wood-dk); }
:root[data-theme="light"] .corso-row__meta-item--level {
  border-color: rgba(30,26,22,.35); color: var(--c-ink);
}

/* --- /studio --- */
:root[data-theme="light"] .studio-hero { background: var(--c-ink-2); color: var(--c-cream); }
:root[data-theme="light"] .studio-hero__lead { color: rgba(246,239,226,.72); }
/* Reviews hero — inverts to dark on light theme, same pattern as studio/blog heros */
:root[data-theme="light"] .rec-hero { background: var(--c-ink-2); color: var(--c-cream); }
:root[data-theme="light"] .rec-hero__title { color: var(--c-cream); }
:root[data-theme="light"] .rec-hero__lead { color: rgba(246,239,226,.72); }
:root[data-theme="light"] .rec-hero__score { color: var(--c-cream); }
:root[data-theme="light"] .rec-hero__count { color: rgba(246,239,226,.7); }
:root[data-theme="light"] .rec-hero__meta {
  background: rgba(255,255,255,.08);
  border-color: rgba(255,255,255,.14);
}
:root[data-theme="light"] .studio-tile {
  background: var(--c-cream-2);
  border-color: rgba(30,26,22,.15);
}
:root[data-theme="light"] .studio-tile--vid { background: #2a2420; }
:root[data-theme="light"] .studio-tile:hover,
:root[data-theme="light"] .studio-tile:focus-visible {
  border-color: rgba(30,26,22,.55);
  box-shadow:
    0 0 0 1px rgba(30,26,22,.35),
    0 0 24px 4px rgba(30,26,22,.14);
}
:root[data-theme="light"] .studio-tile__badge { background: rgba(30,26,22,.55); color: var(--c-cream); }

/* --- /contatti --- */
:root[data-theme="light"] .contatti-hero { background: var(--c-ink-2); color: var(--c-cream); }
:root[data-theme="light"] .contatti-hero__lead { color: rgba(246,239,226,.72); }
:root[data-theme="light"] .contatti-block {
  background: var(--c-cream);
  border-left-color: var(--c-wood-dk);
}
:root[data-theme="light"] .contatti-block__title { color: var(--c-wood-dk); }
:root[data-theme="light"] .contatti-block__body  { color: rgba(30,26,22,.82); }
:root[data-theme="light"] .contatti-social       { color: var(--c-ink); }
:root[data-theme="light"] .contatti-social .ico  { color: var(--c-wood-dk); }
:root[data-theme="light"] .contatti-social:hover { color: var(--c-wood-dk); border-color: var(--c-wood-dk); }
:root[data-theme="light"] .contatti-map          { background: var(--c-cream-2); border-color: rgba(30,26,22,.15); }

/* --- Buttons — ghost style needs inverting on light bg --- */
:root[data-theme="light"] .btn--primary        { background: var(--c-ink);   color: var(--c-cream); border-color: var(--c-ink); }
:root[data-theme="light"] .btn--primary:hover  { background: var(--c-wood-dk); border-color: var(--c-wood-dk); }
/* Hero sits on a dark photo regardless of theme — keep the primary CTA cream
   there so it stays visible against the image. Same treatment for the other
   dark-in-light-theme heros (blog-hero, rec-hero) — they'd otherwise inherit
   the site-wide ink-on-cream primary button, which reads as dark-on-dark. */
:root[data-theme="light"] .hero .btn--primary,
:root[data-theme="light"] .blog-hero .btn--primary,
:root[data-theme="light"] .rec-hero .btn--primary        { background: var(--c-cream); color: var(--c-ink); border-color: var(--c-cream); }
:root[data-theme="light"] .hero .btn--primary:hover,
:root[data-theme="light"] .blog-hero .btn--primary:hover,
:root[data-theme="light"] .rec-hero .btn--primary:hover  { background: var(--c-wood); color: var(--c-cream); border-color: var(--c-wood); }
/* .section--dark stays cream(-2) in light mode, so its ghost button still
   needs ink text/border. Heros are handled separately below: in light theme
   they flip back to dark, so we reset the default ink override to base cream. */
:root[data-theme="light"] .section--dark .btn--ghost {
  color: var(--c-ink);
  border-color: rgba(30,26,22,.45);
}
:root[data-theme="light"] .section--dark .btn--ghost:hover {
  background: rgba(30,26,22,.08); border-color: var(--c-ink); color: var(--c-ink);
}
/* Light-theme heros are DARK — undo the default ink override on ghost buttons
   inside them so the base cream .btn--ghost styles apply again. */
:root[data-theme="light"] .corsi-hero .btn--ghost,
:root[data-theme="light"] .studio-hero .btn--ghost,
:root[data-theme="light"] .contatti-hero .btn--ghost,
:root[data-theme="light"] .policy-hero .btn--ghost {
  color: #fff; border-color: rgba(255,255,255,.65);
}
:root[data-theme="light"] .corsi-hero .btn--ghost:hover,
:root[data-theme="light"] .studio-hero .btn--ghost:hover,
:root[data-theme="light"] .contatti-hero .btn--ghost:hover,
:root[data-theme="light"] .policy-hero .btn--ghost:hover {
  background: rgba(255,255,255,.1); border-color: #fff; color: #fff;
}

/* Selection color feels natural in either theme */
:root[data-theme="light"] ::selection { background: var(--c-wood-dk); color: var(--c-cream); }
