/* ============================================================
   Back Garden - Base Site Stylesheet
   ============================================================
   CSS custom properties are dynamically overridden by /api/style
   which reads values from the D1 database (Ufficio Stile).
   ============================================================ */

/* ── Custom Properties (defaults) ────────────────────────── */
:root {
  /* Page padding */
  --page-padding-top: 16px;
  --page-padding-right: 16px;
  --page-padding-bottom: 16px;
  --page-padding-left: 16px;

  /* Header / Footer padding (default: inherit page padding) */
  --header-padding-top: 16px;
  --header-padding-right: 16px;
  --header-padding-bottom: 16px;
  --header-padding-left: 16px;
  --footer-padding-top: 16px;
  --footer-padding-right: 16px;
  --footer-padding-bottom: 16px;
  --footer-padding-left: 16px;

  /* Element spacing */
  --el-gap: 16px;
  --el-padding-top: 0px;
  --el-padding-right: 0px;
  --el-padding-bottom: 0px;
  --el-padding-left: 0px;

  /* Background */
  --bg-color: #ffffff;

  /* H1 */
  --h1-font-family: 'Times New Roman', Times, serif;
  --h1-font-size: 40px;
  --h1-font-weight: 700;
  --h1-font-style: normal;
  --h1-line-height: 48px;
  --h1-letter-spacing: 0px;
  --h1-color: #000000;
  --h1-text-align: left;
  --h1-text-decoration: none;
  --h1-text-indent: 0px;
  --h1-text-transform: none;
  --h1-hover-color: inherit;
  --h1-hover-decoration: inherit;

  /* H2 */
  --h2-font-family: 'Times New Roman', Times, serif;
  --h2-font-size: 28px;
  --h2-font-weight: 600;
  --h2-font-style: normal;
  --h2-line-height: 36px;
  --h2-letter-spacing: 0px;
  --h2-color: #000000;
  --h2-text-align: left;
  --h2-text-decoration: none;
  --h2-text-indent: 0px;
  --h2-text-transform: none;
  --h2-hover-color: inherit;
  --h2-hover-decoration: inherit;

  /* Body text */
  --body-font-family: 'Times New Roman', Times, serif;
  --body-font-size: 16px;
  --body-font-weight: 400;
  --body-font-style: normal;
  --body-line-height: 24px;
  --body-letter-spacing: 0px;
  --body-color: #000000;
  --body-text-align: left;
  --body-text-decoration: none;
  --body-text-indent: 0px;
  --body-text-transform: none;
  --body-hover-color: inherit;
  --body-hover-decoration: inherit;

  /* Caption */
  --caption-font-family: 'Times New Roman', Times, serif;
  --caption-font-size: 14px;
  --caption-font-weight: 400;
  --caption-font-style: normal;
  --caption-line-height: 20px;
  --caption-letter-spacing: 0px;
  --caption-color: #666666;
  --caption-text-align: left;
  --caption-text-decoration: none;
  --caption-text-indent: 0px;
  --caption-text-transform: none;
  --caption-hover-color: inherit;
  --caption-hover-decoration: inherit;

  /* Link */
  --link-font-family: 'Times New Roman', Times, serif;
  --link-font-size: 16px;
  --link-font-weight: 400;
  --link-font-style: normal;
  --link-line-height: 24px;
  --link-letter-spacing: 0px;
  --link-color: #000000;
  --link-text-align: left;
  --link-text-decoration: underline;
  --link-text-indent: 0px;
  --link-text-transform: none;
  --link-hover-color: #555555;
  --link-hover-decoration: none;

  /* Button */
  --button-font-family: 'Times New Roman', Times, serif;
  --button-font-size: 16px;
  --button-font-weight: 500;
  --button-font-style: normal;
  --button-line-height: 22px;
  --button-letter-spacing: 0px;
  --button-color: #ffffff;
  --button-bg-color: #000000;
  --button-text-align: center;
  --button-text-decoration: none;
  --button-hover-color: #ffffff;
  --button-hover-bg-color: #333333;
  --button-text-transform: none;
  --button-hover-decoration: none;
}

/* ── Reset ───────────────────────────────────────────────── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

/* ── Base ────────────────────────────────────────────────── */
html { font-size: 16px; -webkit-text-size-adjust: 100%; }

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  font-family: var(--body-font-family), system-ui, -apple-system, sans-serif;
  font-size: var(--body-font-size);
  font-weight: var(--body-font-weight);
  line-height: var(--body-line-height);
  letter-spacing: var(--body-letter-spacing);
  color: var(--body-color);
  text-align: var(--body-text-align);
  text-decoration: var(--body-text-decoration);
  text-indent: var(--body-text-indent);
  background-color: var(--bg-color);
}

img, video { max-width: 100%; height: auto; display: block; }

/* ── Background media/YouTube ────────────────────────────── */
/* #siteBg is a direct child of body, position: fixed, z-index: 0.
   .page gets z-index: 1 → page content sits above the video.
   Header/footer (z:10) use .bg-reveal clones with clip: rect()
   to show the same video in their stacking contexts.
   For <video> clones, captureStream() pipes the exact same decoded
   frames → zero drift. For YouTube iframes the clone plays in sync. */
.site-bg {
  position: fixed; inset: 0; z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.site-bg-media {
  width: 100%; height: 100%;
  object-fit: cover;
  border: none;
}
.site-bg iframe.site-bg-media {
  width: 115%; height: 115%;
  margin-left: -7.5%; margin-top: -7.5%;
  pointer-events: none;
  border: none;
}

/* Background reveal inside sticky header/footer */
.bg-reveal {
  position: absolute; inset: 0;
  z-index: -1;
  pointer-events: none;
  clip: rect(auto, auto, auto, auto);
}
.bg-reveal .site-bg-media {
  position: fixed; top: 0; left: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  border: none;
}
.bg-reveal iframe.site-bg-media {
  width: 115%; height: 115%;
  margin-left: -7.5%; margin-top: -7.5%;
  border: none;
}

/* ── Site Header / Footer ────────────────────────────────── */
.site-header {
  position: sticky; top: 0; z-index: 10;
  display: flex; flex-direction: column; gap: var(--el-gap);
  padding: var(--header-padding-top) var(--header-padding-right) var(--header-padding-bottom) var(--header-padding-left);
  background-color: var(--bg-color);
}
.site-header[hidden], .site-footer[hidden] { display: none; }
.site-footer {
  position: sticky; bottom: 0; z-index: 10;
  display: flex; flex-direction: column; gap: var(--el-gap);
  padding: var(--footer-padding-top) var(--footer-padding-right) var(--footer-padding-bottom) var(--footer-padding-left);
  background-color: var(--bg-color);
}
/* Fixed mode: page has no top/bottom padding adjacent to sticky header/footer */
.site-header:not([hidden]) + .page { padding-top: 0; }
.page:has(+ .site-footer:not([hidden])) { padding-bottom: 0; }
/* Static mode: flows normally in the document */
.site-header.pos-static { position: static; }
.site-header.pos-static:not([hidden]) + .page { padding-top: revert; }
.site-footer.pos-static { position: static; }
.page:has(+ .site-footer.pos-static:not([hidden])) { padding-bottom: revert; }
/* Auto-hide mode: sticky with slide transition */
.site-header.pos-autohide { transition: transform .3s ease; }
.site-header.pos-autohide.hf-hidden { transform: translateY(-100%); }
.site-footer.pos-autohide { transition: transform .3s ease; }
.site-footer.pos-autohide.hf-hidden { transform: translateY(100%); }

/* ── Page Layout ─────────────────────────────────────────── */
.page {
  position: relative; z-index: 1;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--el-gap);
  padding: var(--page-padding-top) var(--page-padding-right) var(--page-padding-bottom) var(--page-padding-left);
}

.element {
  padding: var(--el-padding-top) var(--el-padding-right) var(--el-padding-bottom) var(--el-padding-left);
}

/* ── Line block (v0.9.11) ────────────────────────────────────
   Inline SVG line in all 4 orientations. Wrapper dimensions per direction:
     - Orizzontale → width 100% × height = --line-thickness (set inline by JS)
     - Verticale   → width = --line-thickness × height 100vh
     - Diagonali   → width 100% × height 100px
   Box dimensions are overridable via CSS Blocchi → Orientamento (width/height).
   See public/js/site.js renderLine() for the SVG details (stroke position,
   dash patterns, opacity). */
.line-block {
  display: block;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: 0;
}
.line-block--horizontal {
  width: 100%;
  height: var(--line-thickness, 1px);
}
.line-block--vertical {
  width: var(--line-thickness, 1px);
  height: 100vh;
}
.line-block--diagonal-up,
.line-block--diagonal-down {
  width: 100%;
  height: 100px;
}

/* ── Typography ──────────────────────────────────────────── */
h1 {
  font-family: var(--h1-font-family);
  font-size: var(--h1-font-size);
  font-weight: var(--h1-font-weight);
  font-style: var(--h1-font-style);
  line-height: var(--h1-line-height);
  letter-spacing: var(--h1-letter-spacing);
  color: var(--h1-color);
  text-align: var(--h1-text-align);
  text-decoration: var(--h1-text-decoration);
  text-indent: var(--h1-text-indent);
  text-transform: var(--h1-text-transform);
}

h2 {
  font-family: var(--h2-font-family);
  font-size: var(--h2-font-size);
  font-weight: var(--h2-font-weight);
  font-style: var(--h2-font-style);
  line-height: var(--h2-line-height);
  letter-spacing: var(--h2-letter-spacing);
  color: var(--h2-color);
  text-align: var(--h2-text-align);
  text-decoration: var(--h2-text-decoration);
  text-indent: var(--h2-text-indent);
  text-transform: var(--h2-text-transform);
}

p, li, blockquote, .text-style-body {
  font-family: var(--body-font-family);
  font-size: var(--body-font-size);
  font-weight: var(--body-font-weight);
  font-style: var(--body-font-style);
  line-height: var(--body-line-height);
  letter-spacing: var(--body-letter-spacing);
  color: var(--body-color);
  text-align: var(--body-text-align);
  text-decoration: var(--body-text-decoration);
  text-indent: var(--body-text-indent);
  text-transform: var(--body-text-transform);
}

.caption, figcaption {
  font-family: var(--caption-font-family);
  font-size: var(--caption-font-size);
  font-weight: var(--caption-font-weight);
  font-style: var(--caption-font-style);
  line-height: var(--caption-line-height);
  letter-spacing: var(--caption-letter-spacing);
  color: var(--caption-color);
  text-align: var(--caption-text-align);
  text-decoration: var(--caption-text-decoration);
  text-indent: var(--caption-text-indent);
  text-transform: var(--caption-text-transform);
}

/* v0.12.12: esplicito anche :link/:visited per coerenza cross-browser.
   Su iOS Safari il default user-agent può applicare text-decoration: underline
   ai link visitati ignorando la regola base `a`. Replicando per :visited e
   con fallback `none` ci si assicura che la decorazione corrisponda sempre a
   quanto impostato nell'Ufficio Stile. */
a, a:link, a:visited {
  font-family: var(--link-font-family);
  color: var(--link-color);
  text-decoration: var(--link-text-decoration, none);
  text-transform: var(--link-text-transform);
  transition: color 150ms ease, text-decoration 150ms ease;
}

/* Row block */
.row-block {
  display: flex;
  align-items: center;
}
.row-cell {
  min-width: 0;
}

/* Image link wrapper: inherit caption style, not link style */
.image-block a, .video-block a {
  font-family: inherit; color: inherit;
  text-decoration: none;
}
.image-block a:hover, .video-block a:hover {
  color: inherit; text-decoration: none;
}

/* Index block: list of pages pulled from a source page in the tree.
   Minimal default styling — site author personalizes via custom.css. */
.index-block .index-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--el-gap, 1rem);
}
.index-block .index-item a {
  display: flex;
  align-items: flex-start;
  /* gap is handled by per-element margin so the marker→content space
     can be controlled independently of the cover→body space. */
  gap: 0;
  text-decoration: none;
  color: inherit;
  font-family: inherit;
}
.index-block .index-item a:hover {
  color: inherit;
  text-decoration: none;
}
.index-block .index-cover {
  flex: 0 0 auto;
  margin: 0 1rem 0 0;       /* right margin = cover→body spacing (was flex gap) */
  width: 120px;
}
.index-block .index-cover img,
.index-block .index-cover video {
  display: block;
  width: 100%;
  height: auto;
}
.index-block .index-body {
  flex: 1 1 auto;
  min-width: 0;
  /* Stack title / subtitle / date with explicit gap. text-box-trim
     (Taglia ascendenti/discendenti nel pannello Style) collassa
     l'altezza dei box al solo glifo, quindi senza un gap esplicito
     gli elementi consecutivi si sovrapporrebbero. */
  display: flex;
  flex-direction: column;
  gap: 0.4em;
}
.index-block .index-title,
.index-block .index-field {
  margin: 0;
}
/* Marker (puntato/numerato) — sits to the left of cover/body and inherits the
   index title's text style by default (set by JS via class "text-style-{key}").
   `flex: 0 0 auto` keeps it from stretching; `min-width: 1.5em` stops the
   layout from shifting around as siblings get longer numbers (1 → 10 → 100).
   `--index-marker-gap` is set inline by renderIndex (default 0 so the
   no-marker layout is unaffected). */
.index-block .index-marker {
  flex: 0 0 auto;
  min-width: 1.5em;
  white-space: nowrap;
  margin-right: var(--index-marker-gap, 0px);
}

/* ── Index block: dropdown mode ──────────────────────────────
   The block is wrapped as <div class="index-block index-block--dropdown"
   data-position="inline|floating" data-state="open|closed">. The header
   is always rendered; the panel is hidden via the [hidden] attribute (set
   by the runtime) and shown when state="open".
*/
.index-block--dropdown { position: relative; }
.index-dropdown-header {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  cursor: pointer;
}
.index-dropdown-title {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-decoration: none;
  cursor: inherit;
}
button.index-dropdown-title { line-height: inherit; }
.index-dropdown-arrow {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  line-height: 1;
  transition: transform .2s ease;
}
.index-block--dropdown[data-state="open"] .index-dropdown-arrow {
  transform: rotate(180deg);
}
.index-dropdown-panel {
  /* Common: a small fade/slide on open. The native [hidden] attr toggles
     display, so the transition only kicks in when the panel goes from
     hidden → shown; when it gets re-hidden it just disappears. */
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity .18s ease, transform .18s ease;
}
.index-block--dropdown[data-state="open"] .index-dropdown-panel {
  opacity: 1;
  transform: translateY(0);
}
/* Floating mode: panel pops over the content below. */
.index-block--dropdown[data-position="floating"] .index-dropdown-panel {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 50;
  min-width: 100%;
  max-width: 90vw;
  background: var(--bg-color, transparent);
  /* If the site has no opaque background, the panel inherits transparent;
     authors can override .index-dropdown-panel from custom.css. */
  padding-top: .5em;
}
/* Inline mode: panel pushes content below. Add a small top spacing so the
   first item doesn't touch the header line. */
.index-block--dropdown[data-position="inline"] .index-dropdown-panel {
  margin-top: .5em;
}

button, .btn {
  font-family: var(--button-font-family);
  font-size: var(--button-font-size);
  font-weight: var(--button-font-weight);
  font-style: var(--button-font-style);
  line-height: var(--button-line-height);
  letter-spacing: var(--button-letter-spacing);
  color: var(--button-color);
  background-color: var(--button-bg-color);
  text-align: var(--button-text-align);
  text-decoration: var(--button-text-decoration);
  text-transform: var(--button-text-transform);
  border: none;
  padding: 0.6rem 1.2rem;
  cursor: pointer;
  transition: color 150ms ease, background-color 150ms ease;
}
button:hover, .btn:hover {
  background-color: var(--button-hover-bg-color);
}

/* ── Inline Text Styles (rich editor spans) ─────────────── */
.text-style-h1 {
  font-family: var(--h1-font-family);
  font-size: var(--h1-font-size);
  font-weight: var(--h1-font-weight);
  font-style: var(--h1-font-style);
  line-height: var(--h1-line-height);
  letter-spacing: var(--h1-letter-spacing);
  color: var(--h1-color);
  text-decoration: var(--h1-text-decoration);
}
.text-style-h2 {
  font-family: var(--h2-font-family);
  font-size: var(--h2-font-size);
  font-weight: var(--h2-font-weight);
  font-style: var(--h2-font-style);
  line-height: var(--h2-line-height);
  letter-spacing: var(--h2-letter-spacing);
  color: var(--h2-color);
  text-decoration: var(--h2-text-decoration);
}
.text-style-caption {
  font-family: var(--caption-font-family);
  font-size: var(--caption-font-size);
  font-weight: var(--caption-font-weight);
  font-style: var(--caption-font-style);
  line-height: var(--caption-line-height);
  letter-spacing: var(--caption-letter-spacing);
  color: var(--caption-color);
  text-decoration: var(--caption-text-decoration);
}

/* Link style class for <a> created by the rich editor */
a.text-style-link,
a.text-style-link:link,
a.text-style-link:visited {
  font-family: var(--link-font-family);
  color: var(--link-color);
  text-decoration: var(--link-text-decoration, none);
}

/* ── Gallery Carousel ───────────────────────────────────── */
.gallery-carousel {
  position: relative;
  margin: 0;
}

.gallery-viewport {
  position: relative;
  overflow: hidden;
  line-height: 0;
}

.gallery-img {
  width: 100%;
  height: auto;
  display: block;
}

/* Fade transition for auto-play (v0.5.7). Double-buffer: the "main" <img>
   stays in flow (viewport keeps its natural height); a second
   .gallery-img--overlay is absolutely positioned on top and fades in/out.
   site.js handles the choreography (load → fade → swap underlying src). */
.gallery-carousel--fade .gallery-viewport {
  position: relative;
}
.gallery-carousel--fade .gallery-img--overlay {
  position: absolute;
  inset: 0;
  opacity: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  transition: opacity var(--gallery-anim-dur, 0.35s) ease;
}
.gallery-carousel--fade .gallery-img--overlay.is-visible { opacity: 1; }
/* While the JS swaps the underlying <img> we momentarily disable the
   transition on the overlay so it snaps back to opacity:0 invisibly
   instead of fading out a stale image. */
.gallery-carousel--fade .gallery-img--overlay.is-instant {
  transition: none;
}

/* Slide transitions (v0.9.0). Same double-buffer as fade but animated with
   transform instead of opacity. Both imgB (incoming) and img (outgoing) move —
   transform doesn't affect layout so the viewport height stays stable.
   Transition timing is driven entirely by JS inline styles. */
.gallery-carousel--slide-left  .gallery-img--overlay,
.gallery-carousel--slide-right .gallery-img--overlay,
.gallery-carousel--slide-up    .gallery-img--overlay,
.gallery-carousel--slide-down  .gallery-img--overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

/* 3D cube transition (v0.12.6, fixed v0.12.9). A `.gallery-cube` container
   lives inside the viewport with two image faces (front + next). At rest the
   cube sits at rotateY(0), so only the front face is visible — visually
   identical to a flat photo. On advance, JS rotates the cube 90° to bring the
   next face forward, then snaps back to 0° and swaps the front image.
   translateZ for each face equals half the viewport's W (for Y-axis) or H
   (for X-axis), recomputed by site.js via ResizeObserver.
   IMPORTANT: `.gallery-viewport` is `overflow: hidden` by default; the cube
   needs `overflow: visible` so the rotating faces poke past the viewport
   rect during the animation (otherwise the rotation looks like a hard mask
   crop). Same for the .gallery-carousel and .gallery-block wrappers — any
   ancestor that clips will eat the 3D effect. */
.gallery-carousel--cube,
.gallery-carousel--cube .gallery-viewport {
  overflow: visible;
}
.gallery-carousel--cube .gallery-viewport {
  /* v0.12.12: bumped from 1200px to 2400px to soften the fish-eye projection.
     The front face sits at translateZ(W/2); with perspective P the visual
     scale factor is P/(P-W/2). At P=1200, W=600 → 1.33× (face sporge fino
     a 100px oltre il viewport e copre il counter sotto). At P=2400, W=600
     → 1.143× — sporgenza ridotta a ~43px, counter resta sotto al face. */
  perspective: 2400px;
}
/* v0.12.12: counter e caption devono stare sopra il cubo. Il front face è a
   translateZ(W/2) (in avanti, verso la camera) quindi nella composizione 3D
   "copre" qualunque sibling 2D che venga dopo nel flow (counter, caption).
   Z-index esplicito li mantiene visibili anche con cubo grande su desktop. */
.gallery-carousel--cube .gallery-counter,
.gallery-carousel--cube .gallery-caption {
  position: relative;
  z-index: 1;
}
.gallery-cube {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  /* JS drives the transition timing (animMs) inline. */
}
.gallery-cube .gallery-cube-face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  display: block;
  object-fit: var(--gallery-item-fit, cover);
  /* No backface-visibility:hidden — leaving it on caused flicker during
     rotation when each face's normal crossed 90° from camera. */
}

/* Invisible click zones: left 50% / right 50% */
.gallery-zone {
  position: absolute;
  top: 0; bottom: 0;
  width: 50%;
  cursor: pointer;
  z-index: 1;
}
.gallery-zone-left { left: 0; }
.gallery-zone-right { right: 0; }

/* Optional hover hint */
.gallery-zone-left:hover { cursor: w-resize; }
.gallery-zone-right:hover { cursor: e-resize; }

/* Vertical zones for slide-up / slide-down */
.gallery-zone-top,
.gallery-zone-bottom {
  width: 100%;
  height: 50%;
}
.gallery-zone-top    { top: 0;    bottom: auto; }
.gallery-zone-bottom { bottom: 0; top: auto;    }
.gallery-zone-top:hover    { cursor: n-resize; }
.gallery-zone-bottom:hover { cursor: s-resize; }

.gallery-caption {
  margin-top: 0.4em;
  min-height: 1.2em;
}

/* ── Search block (v0.6.1) ───────────────────────────────────
   Default styling is intentionally minimal — sites are expected to
   override most of this from custom.css or the block's CSS Blocchi
   (the Search block ships only with a sensible bare layout). */
.search-block {
  display: flex; flex-direction: column;
  gap: .75rem;
  margin: 0;
}
.search-bar {
  display: flex;
}
.search-input {
  flex: 1;
  padding: .6rem .8rem;
  font: inherit;
  color: inherit;
  background: transparent;
  border: 1px solid currentColor;
  border-radius: 0;
  outline: none;
}
.search-input::placeholder { opacity: .5; }
/* Facets row */
.search-facets {
  display: flex; flex-wrap: wrap; gap: .35rem;
}
.search-facet {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .15rem .55rem;
  font: inherit; color: inherit;
  background: transparent;
  border: 1px solid currentColor;
  border-radius: 999px;
  cursor: pointer;
  font-size: .8em;
  opacity: .7;
  transition: opacity .12s ease;
}
.search-facet:hover { opacity: 1; }
.search-facet.is-selected { opacity: 1; background: currentColor; }
.search-facet.is-selected .search-facet-name,
.search-facet.is-selected .search-facet-count { color: var(--bg-color, #fff); }
.search-facet-count {
  font-size: .8em; opacity: .65;
  font-variant-numeric: tabular-nums;
}
/* Results list */
.search-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column;
  gap: var(--el-gap, 1rem);
}
.search-list.is-loading { opacity: .7; }
.search-item a {
  display: flex; align-items: flex-start; gap: 0;
  text-decoration: none; color: inherit; font-family: inherit;
}
.search-item a:hover { color: inherit; text-decoration: none; }
.search-cover {
  flex: 0 0 auto; width: 120px;
  margin: 0 1rem 0 0;
}
.search-cover img,
.search-cover video {
  display: block; width: 100%; height: auto;
}
.search-body {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column;
  gap: .4em;
}
.search-title { margin: 0; }
.search-result-tags {
  display: flex; flex-wrap: wrap; gap: .35em;
  margin: 0;
}
.search-tag-pill {
  display: inline-block;
  padding: .05em .5em;
  border: 1px solid currentColor;
  border-radius: 999px;
  opacity: .7;
}
.search-empty,
.search-error {
  list-style: none;
  padding: .5rem 0;
  opacity: .6;
  font-style: italic;
}

/* v0.20.0: Ricerca "Cerca immagini nel sito" — griglia risultati foto.
   Colonne/gap/aspect arrivano da CSS vars inline (--search-img-*). */
.search-img-grid {
  display: grid;
  grid-template-columns: repeat(var(--search-img-cols, 4), 1fr);
  gap: var(--search-img-gap, 12px);
}
.search-img-item {
  display: flex; flex-direction: column;
  text-decoration: none; color: inherit; font-family: inherit;
}
.search-img-item:hover { color: inherit; text-decoration: none; }
.search-img-item img {
  display: block; width: 100%;
  aspect-ratio: var(--search-img-aspect, 1 / 1);
  object-fit: cover;
}
.search-img-caption { display: block; margin-top: .3em; }
.search-block--images-site .search-empty { grid-column: 1 / -1; }

/* Carousel counter (e.g. "1/12") — opt-in via CSS Blocchi → Layout galleria.
   Inherits the caption text style (text-style-caption); positioning above
   or below the viewport is decided by JS (mounted as previous/next sibling
   of .gallery-viewport). The wrapper class controls horizontal alignment. */
.gallery-counter {
  display: block;
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.gallery-counter--align-left   { text-align: left; }
.gallery-counter--align-center { text-align: center; }
.gallery-counter--align-right  { text-align: right; }
/* When mounted before the viewport, give it bottom margin so it doesn't
   touch the image. After the viewport, top margin. */
.gallery-counter:not(:last-child)  { margin-bottom: 0.4em; }
.gallery-counter:not(:first-child) { margin-top: 0.4em; }

/* ── Gallery non-carousel layouts (v0.5.5) ───────────────────
   Driven by inline CSS vars set by site.js (--gallery-cols, --gallery-gap,
   --gallery-item-aspect). Switching the mode in CSS Blocchi swaps the
   modifier class on the wrapper; the rendering JS is otherwise the same
   (every image rendered, no preload-on-demand, no click zones). */
.gallery-block--grid {
  display: grid;
  grid-template-columns: repeat(var(--gallery-cols, 3), 1fr);
  gap: var(--gallery-gap, var(--el-gap, 12px));
  margin: 0;
}
.gallery-block--grid .gallery-item {
  display: flex; flex-direction: column;
  min-width: 0;
}
.gallery-block--grid .gallery-item img,
.gallery-block--grid .gallery-item video {
  width: 100%;
  height: auto;
  display: block;
}
/* When the admin sets a fixed item aspect-ratio, crop to fit. */
.gallery-block--grid .gallery-item:has(img):not([style*="--gallery-item-aspect"]) > img,
.gallery-block--grid .gallery-item img,
.gallery-block--grid .gallery-item video {
  /* Vars cascade from the wrapper: if --gallery-item-aspect is set we
     enforce it; otherwise the image keeps its natural ratio. */
  aspect-ratio: var(--gallery-item-aspect, auto);
  object-fit: var(--gallery-item-fit, cover);
}

/* Masonry: CSS columns variant. Items flow naturally with their own height. */
.gallery-block--masonry {
  column-count: var(--gallery-cols, 3);
  column-gap: var(--gallery-gap, var(--el-gap, 12px));
  margin: 0;
}
.gallery-block--masonry .gallery-item {
  break-inside: avoid;
  margin-bottom: var(--gallery-gap, var(--el-gap, 12px));
  display: block;
}
.gallery-block--masonry .gallery-item img,
.gallery-block--masonry .gallery-item video {
  width: 100%;
  height: auto;
  display: block;
}

/* ── Scroll orizzontale / striscia (v0.12.14) ────────────────
   Native horizontal scroll: a single non-wrapping flex row, scrolled by
   trackpad/swipe (no JS). Default = fixed height, natural width; if the
   admin sets an aspect ratio it wins (cover-crop). Snap is optional. */
.gallery-block--scroll {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  gap: var(--gallery-gap, var(--el-gap, 12px));
  margin: 0;
  -webkit-overflow-scrolling: touch;
}
.gallery-block--scroll .gallery-item {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.gallery-block--scroll .gallery-item img,
.gallery-block--scroll .gallery-item video {
  height: var(--gallery-scroll-height, 60vh);
  width: auto;
  display: block;
  aspect-ratio: var(--gallery-item-aspect, auto);
  object-fit: var(--gallery-item-fit, cover);
}
/* Optional snap: each image aligns to the start edge while scrolling. */
.gallery-block--scroll.gallery-block--snap {
  scroll-snap-type: x mandatory;
}
.gallery-block--scroll.gallery-block--snap .gallery-item {
  scroll-snap-align: start;
}

/* ── Hover immagini (v0.12.22) ───────────────────────────────
   Wrapper `.bg-img-hover` emesso da site.js attorno a un media (img/video)
   quando l'immagine ha un link, un testo-hover, o il blocco ha un effetto
   hover impostato in CSS Blocchi. Contiene gli overlay `.bg-img-tint`
   (tinta colore) e `.bg-img-text` (testo per-immagine).
   Qui solo le basi: contesto di posizionamento, opacity 0→1, layout flex
   del testo. L'effetto specifico (filter/opacity/blend), la posizione del
   testo (9 punti) e il suo look sono emessi PER-BLOCCO da
   /api/block-styles → composeImageHoverForBlock. */
.bg-img-hover {
  position: relative;
  display: block;
  line-height: 0;
}
.bg-img-hover img,
.bg-img-hover video {
  display: block;
}
/* In scroll orizzontale il media ha altezza fissa e larghezza naturale:
   il wrapper deve restringersi al media (no width:100% del flex item). */
.gallery-block--scroll .gallery-item .bg-img-hover {
  display: inline-block;
}
.bg-img-tint {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
}
.bg-img-text {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  box-sizing: border-box;
  pointer-events: none;
  opacity: 0;
  transition: opacity 300ms ease;
  line-height: normal;
}
.bg-img-hover:hover .bg-img-text {
  opacity: 1;
}
.bg-img-text-inner {
  max-width: 100%;
}

/* (v0.5.7) "list" mode removed — equivalent to grid with N=1 columns. */

/* ── Index block: grid mode ──────────────────────────────────
   Driven by inline CSS vars set by site.js (--index-cols, --index-gap,
   --index-item-aspect). Set from CSS Blocchi → Layout index. */
.index-block--grid .index-list {
  display: grid;
  grid-template-columns: repeat(var(--index-cols, 3), 1fr);
  gap: var(--index-gap, var(--el-gap, 12px));
}
/* v0.12.13: grid items use CSS grid (not flex column) so the marker and the
   title can sit on the same row by default, while a cover (if present) spans
   the full width on top. DOM order is marker, cover, body — explicit grid
   areas place them independently of source order. */
.index-block--grid .index-item a {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  column-gap: var(--index-marker-gap, .35em);
  row-gap: .5rem;
}
/* No cover: marker auto-places in col 1, body in col 2 → same row. */
.index-block--grid .index-marker { margin-right: 0; }
/* With cover: full-width cover on top, then marker + body row beneath. */
.index-block--grid .index-item--with-preview a {
  grid-template-areas:
    "cover  cover"
    "marker body";
}
.index-block--grid .index-item--with-preview .index-cover  { grid-area: cover; }
.index-block--grid .index-item--with-preview .index-marker { grid-area: marker; }
.index-block--grid .index-item--with-preview .index-body   { grid-area: body; }
.index-block--grid .index-cover {
  width: 100%;
  margin: 0;
  aspect-ratio: var(--index-item-aspect, auto);
  overflow: hidden;
}
.index-block--grid .index-cover img,
.index-block--grid .index-cover video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ── Index block: "Numero a capo" (marker stacked) ───────────
   Opt-in toggle (CSS Blocchi → Layout index). Sends the title to a new
   line below the marker, in both list and grid. Without it the marker and
   title share a line (the default since v0.12.13). */
.index-block--marker-stacked:not(.index-block--grid) .index-item a {
  flex-direction: column;
  align-items: flex-start;
  row-gap: .2em;
}
.index-block--marker-stacked.index-block--grid .index-item a {
  grid-template-columns: 1fr;
}
.index-block--marker-stacked.index-block--grid .index-item--with-preview a {
  grid-template-areas:
    "cover"
    "marker"
    "body";
}

/* ── Index: anteprima cover al passaggio del mouse (v0.12.16) ──
   Elemento singleton flottante, posizionato via JS (position:fixed). Non
   intercetta il mouse (pointer-events:none) così non "ruba" l'hover alla
   voce. Larghezza/aspect-ratio impostati inline da site.js. */
.index-hover-preview {
  position: fixed;
  top: 0; left: 0;
  z-index: 9999;
  pointer-events: none;
  overflow: hidden;
  max-width: 92vw;
  max-height: 92vh;
  background: transparent;
}
.index-hover-preview img,
.index-hover-preview video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ── Search block: grid mode ─────────────────────────────────
   Driven by inline CSS vars set by site.js (--search-cols, --search-gap,
   --search-item-aspect). Set from CSS Blocchi → Layout ricerca. */
.search-block--grid .search-list {
  display: grid;
  grid-template-columns: repeat(var(--search-cols, 3), 1fr);
  gap: var(--search-gap, var(--el-gap, 12px));
}
.search-block--grid .search-item a {
  flex-direction: column;
  gap: .5rem;
}
.search-block--grid .search-cover {
  width: 100%;
  margin: 0;
  aspect-ratio: var(--search-item-aspect, auto);
  overflow: hidden;
}
.search-block--grid .search-cover img,
.search-block--grid .search-cover video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}


/* ── Documenti legali (v0.11.5 + v0.11.6) ──────────────────────
   I 3 documenti legali (privacy/cookie/terms) sono renderizzati come
   block text con HTML interno avvolto in <div class="legal-document">.
   v0.11.5: TUTTO il contenuto usa stile Body (text-style-body) per
   uniformità totale. Le distinzioni visive si ottengono tramite classi
   semantiche aggiuntive (legal-title-main / legal-title-section /
   legal-bullet / legal-hr / legal-disclaimer) che modulano SOLO il
   margine — niente font-size/weight diversi.

   Gerarchia visiva:
   - Titolo principale: MAIUSCOLO + spazio sotto
   - Titoli sezione: spazio sopra (separa dal paragrafo precedente)
   - Paragrafi interni e liste: compatti, flow continuo dentro la sezione

   v0.11.6: rimossi i default di "layout di lettura" (max-width 720px,
   margin auto centrato, padding interno, line-height fisso 1.7). Il
   documento ora eredita dalle impostazioni di pagina (Padding pagina di
   Ufficio Stile) e dallo stile Body. L'admin formatta a piacere senza
   doversi scontrare con override CSS hardcoded.
*/
/* Span text-style-body dentro .legal-document → block-level compatto.
   v0.11.7: disabilito text-box-trim (= Ufficio Stile → Padding pagina →
   "Taglia ascendenti"/"Taglia discendenti"). Senza questo override, ogni
   paragrafo di 1 riga ha il box visivo collassato al solo glifo, quindi
   line-height alto in Ufficio Stile non si vede tra paragrafi consecutivi.
   Coerente con "no formattazioni forzate" nei documenti legali. */
.legal-document .text-style-body {
  display: block;
  margin: 0;
  text-box: normal;
  text-box-trim: none;
  text-box-edge: auto;
}
/* Titolo principale (era <h1>): maiuscolo + spazio sotto */
.legal-document .text-style-body.legal-title-main {
  margin: 0 0 1.5em;
}
/* Titoli di sezione (era <h2>): spazio sopra per separare dal paragrafo precedente */
.legal-document .text-style-body.legal-title-section {
  margin: 1.5em 0 0;
}
/* Disclaimer finale (era <small>): mantiene spazio sopra per stacco */
.legal-document .text-style-body.legal-disclaimer {
  margin: 1.5em 0 0;
}
/* Liste puntate / numerate: compatte, hanging indent per il bullet/numero a sx */
.legal-document .text-style-body.legal-bullet {
  padding-left: 1.5em;
  text-indent: -1.5em;
  margin: 0;
}
/* Separatore <hr>: linea sottile divisoria */
.legal-document .text-style-body.legal-hr {
  display: block;
  margin: 1.5em 0;
  height: 1px;
  background: rgba(0, 0, 0, .15);
}
.legal-document a.text-style-link {
  display: inline;
  margin: 0;
}
/* Primo elemento: rimuovi margine top per non creare doppio spazio iniziale */
.legal-document > .text-style-body:first-child {
  margin-top: 0;
}

/* ── Container block (v0.9.27) ─────────────────────────────────
   Block che può contenere altri block. Default minimal — l'utente
   sovrascrive padding/bg/border/ecc. dal CSS Blocchi del singolo container. */
.block-container {
  display: flex;
  flex-direction: column;
  gap: var(--el-gap, 16px);
}

/* ── Container multi-colonna (v0.14.0) ─────────────────────────────
   Quando il container ha layout.columns.length > 1, site.js gli mette
   la classe .block-container--cols e crea N wrapper .bg-col, uno per
   colonna. Le larghezze arrivano come flex shorthand in --bg-flex
   (desktop) / --bg-flex-m (mobile); il gutter in --bg-col-gap(-m).
   La classe .bg-mobile è togglata via JS (applyResponsiveColumns) quando
   innerWidth <= data-bp; data-stack="breakpoint" forza l'impilamento. */
.block-container--cols {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--bg-col-gap, 16px);
}
.block-container--cols > .bg-col {
  display: flex;
  flex-direction: column;
  gap: var(--el-gap, 16px);
  flex: var(--bg-flex, 1 1 0);
  min-width: 0;
}
/* Mobile: usa le larghezze mobile e il gutter mobile. */
.block-container--cols.bg-mobile {
  gap: var(--bg-col-gap-m, var(--bg-col-gap, 16px));
}
.block-container--cols.bg-mobile > .bg-col {
  flex: var(--bg-flex-m, var(--bg-flex, 1 1 0));
}
/* Mobile + stacking esplicito: una colonna per riga. */
.block-container--cols.bg-mobile[data-stack="breakpoint"] > .bg-col {
  flex: 1 1 100%;
}

/* ── Scroll indipendente per colonna (v0.16.0) ────────────────────
   Una colonna con data-scroll diventa un pannello ad altezza fissa
   (--bg-col-scroll-h) con overflow verticale: scorre da sola.
   Se l'altezza è in '%', site.js aggiunge .bg-cols-vph al container così
   il '%' si risolve rispetto all'altezza schermo (height:100vh). */
.block-container--cols.bg-cols-vph {
  height: 100vh;
}
.block-container--cols > .bg-col[data-scroll] {
  height: var(--bg-col-scroll-h, 100vh);
  overflow-y: auto;
}
/* Su mobile con impilamento esplicito i pannelli tornano a scorrimento
   normale: niente altezza fissa, le colonne si impilano e crescono. */
.block-container--cols.bg-mobile[data-stack="breakpoint"] {
  height: auto;
}
.block-container--cols.bg-mobile[data-stack="breakpoint"] > .bg-col[data-scroll] {
  height: auto;
  overflow: visible;
}

/* ── Cookie banner (v0.9.23) ───────────────────────────────────
   In v0.9.23 il banner è una pagina speciale `_cookie` editabile da
   Contents (testi/struttura) + CSS Blocchi (stili dei singoli block).
   Il CSS per block viene applicato automaticamente via [data-block-id].
   Qui mantiene solo i fondamentali del container popup + i fallback
   minimali per i nuovi block type cookie_category / cookie_button. */
/* v0.9.32/v0.9.34: container del banner ridotto al minimo. Solo
   position + bg bianco. Niente font/size hardcoded così lo stile Body
   dell'Ufficio Stile si applica naturalmente (vedi STYLE_SELECTORS.body
   in functions/api/style.js, che ora include [data-cookie-role="banner_root"]).
   Niente padding/radius/shadow di default. L'utente customizza da CSS Blocchi. */
[data-cookie-role="banner_root"] {
  position: fixed;
  bottom: 1rem;
  left: 1rem;
  z-index: 10000;
  background: #fff;
  gap: 0;
}
/* Backdrop scurito per posizione 'center'. */
.bg-cookie-backdrop {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(0, 0, 0, .5);
}
/* Block cookie_category (default look — totalmente sovrascrivibile da CSS Blocchi). */
.bg-cookie-cat {
  display: flex; gap: .55rem; align-items: flex-start;
  cursor: pointer; font-size: .92em;
}
.bg-cookie-cat input { margin-top: .15rem; flex: 0 0 auto; }
.bg-cookie-cat small { color: rgba(0, 0, 0, .6); display: block; margin-top: .15rem; }
/* v0.9.32/v0.9.34: bottoni cookie senza overrides di font/color, così lo
   stile Button dell'Ufficio Stile (STYLE_SELECTORS.button) si applica
   automaticamente (font-family, size, weight, color, bg-color, ecc.).
   Restano solo border 1px e cursor — le proprietà "comportamentali" del
   bottone non legate al testo. L'utente customizza per-block da CSS Blocchi. */
.bg-cookie-btn {
  border: 1px solid currentColor;
  cursor: pointer;
}

/* Link "Gestisci cookie" (v0.9.22, conservato). Inserito a mano dall'utente
   come <a data-bg-cookie-prefs>. Style ereditato dal sito (nessuna var). */
a[data-bg-cookie-prefs] { cursor: pointer; text-decoration: underline; }

/* Dark color scheme fallback. */
@media (prefers-color-scheme: dark) {
  [data-cookie-role="banner_root"] { background: #1a1a1a; color: #f0f0f0; }
  .bg-cookie-btn--accept { background: #f0f0f0; color: #111; border-color: #f0f0f0; }
  .bg-cookie-cat small { color: rgba(255, 255, 255, .6); }
}

/* v0.9.29: niente regola responsive hardcoded. Su mobile l'utente
   imposta width/max-width come crede dal CSS Blocchi del block. */

/* ── Lightbox / Ingrandimento immagine (v0.12.23) ────────────
   Overlay montato su <body> da site.js → openLightbox() quando un media
   (immagine block o item gallery) ha "Al click: ingrandisci". Qui solo le
   basi: overlay fullscreen, centratura del media, dimensioni di sicurezza.
   Sfondo (colore + opacità + blur), larghezza e allineamento sono emessi
   PER-BLOCCO dal server (/api/block-styles → composeLightboxForBlock) come
   `.bg-lightbox[data-block-id="N"]` (selettore sull'overlay stesso, perché è
   fuori dal wrapper del blocco). */
.bg-lightbox {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  /* v0.12.29: nessun padding di default, così l'immagine può davvero toccare
     i bordi quando la si allinea (es. in basso al centro). */
  padding: 0;
  box-sizing: border-box;
  cursor: pointer; /* v0.12.27: manina (click per chiudere), mai la lente */
  /* Default neutro: sfondo scuro semi-trasparente, sovrascrivibile per-blocco. */
  background: rgba(0, 0, 0, .82);
}
.bg-lightbox-media {
  display: block;
  /* v0.12.29: max 100vw/100vh → niente margine forzato verso i bordi schermo.
     width/height per-blocco li sovrascrive. */
  max-width: 100vw;
  max-height: 100vh;
  width: auto;
  height: auto;
  object-fit: contain;
}
/* Blocca lo scroll della pagina mentre il lightbox è aperto. */
body.bg-lightbox-open {
  overflow: hidden;
}

/* ── v0.12.25 — Block Audio ─────────────────────────────────────────
   Tre componenti posizionabili indipendentemente (libertà totale) tramite
   grid-area: .audio-cover / .audio-player / .audio-tracklist. Il default è
   un'impilatura verticale (cover, player, lista). CSS Blocchi sovrascrive
   grid-template-areas/columns e i colori/dimensioni via /api/block-styles. */
.audio-block {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas: "cover" "player" "tracklist";
  gap: 1rem;
  align-items: start;
}
.audio-cover { grid-area: cover; width: 200px; max-width: 100%; }
.audio-player { grid-area: player; }
.audio-tracklist { grid-area: tracklist; }
.audio-hidden { display: none !important; }

.audio-cover-img { display: block; width: 100%; height: auto; }

.audio-player {
  background: #111;
  color: #fff;
  border-radius: 8px;
  padding: .75rem 1rem;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.audio-now-title { font-weight: 600; line-height: 1.2; }
.audio-now-artist { opacity: .75; font-size: .85em; }
.audio-controls { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; justify-content: center; }
.audio-btn {
  background: none;
  border: 0;
  color: inherit;
  cursor: pointer;
  font-size: 1.2rem;
  line-height: 1;
  padding: .2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.audio-btn img { width: 1.2rem; height: 1.2rem; object-fit: contain; display: block; }
.audio-btn-play { font-size: 1.5rem; }
.audio-speed {
  margin-left: auto;
  background: #000;
  color: #fff;
  border: 1px solid rgba(255, 255, 255, .3);
  border-radius: 4px;
  padding: .1rem .35rem;
  font-size: .8rem;
  cursor: pointer;
}
.audio-timeline { display: flex; align-items: center; gap: .5rem; }
.audio-seek { flex: 1; min-width: 0; accent-color: #fff; }
.audio-time { font-size: .75rem; opacity: .8; font-variant-numeric: tabular-nums; }

.audio-tracklist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .25rem; }
.audio-tle { display: flex; align-items: center; gap: .6rem; padding: .4rem .5rem; border-radius: 6px; cursor: pointer; }
.audio-tle:hover { background: rgba(0, 0, 0, .05); }
.audio-tle--playing { background: #eee; font-weight: 600; }
.audio-tle-cover { flex: 0 0 auto; width: 36px; height: 36px; }
.audio-tle-cover img { width: 100%; height: 100%; object-fit: cover; border-radius: 4px; display: block; }
.audio-tle-meta { display: flex; flex-direction: column; min-width: 0; }
.audio-tle-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.audio-tle-artist { font-size: .8em; opacity: .7; }

/* Modalità sottofondo: player nascosto, ma il tasto Play di fallback compare
   se il browser blocca l'avvio automatico. */
.audio-block--background .audio-cover,
.audio-block--background .audio-player,
.audio-block--background .audio-tracklist { display: none; }
.audio-bg-play {
  background: #111;
  color: #fff;
  border-radius: 50%;
  width: 3rem;
  height: 3rem;
  font-size: 1.4rem;
}

/* ── Sito protetto da password (v0.17.0 / v0.18.0) ────────────────────
   La schermata _gate è standalone (niente header/footer) ed è spacchettata
   in 3 sotto-blocchi (campo password, bottone, messaggio d'errore), avvolti
   da un unico <form> generato a runtime. Formattazione MINIMA di default: ogni
   elemento eredita la tipografia dall'Ufficio Stile (text-style-*) e si stila/
   posiziona liberamente dai CSS Blocchi. Centriamo il contenuto per una login
   pulita "out of the box". */
.page-gate {
  min-height: 100vh;
  justify-content: center;
  align-items: center;
  text-align: center;
}
.gate-page-form {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .6rem;
  width: 100%;
  max-width: 22rem;
  margin: 0 auto;
}
/* Campo password: solo testo, nessun bordo/sfondo (l'utente li aggiunge dai
   CSS Blocchi se vuole). La tipografia arriva da text-style-caption. */
.gate-input {
  border: 0;
  background: transparent;
  padding: 0;
  color: inherit;
  text-align: inherit;
  width: 100%;
}
.gate-input:focus { outline: none; }
/* Il bottone è un <button> nudo: eredita lo stile "Button" dall'Ufficio Stile.
   Niente chrome hardcoded qui. */
.gate-btn { cursor: pointer; }
/* Messaggio d'errore: tipografia da text-style-body, nessun colore imposto. */
.gate-error { margin: 0; }

/* ── Hamburger menù (v0.31.0) ──────────────────────────────────
   Container con un toggle che si trasforma (☰↔✕) + un pannello overlay che
   NON sposta mai i contenuti (position fixed/absolute). Modalità via
   [data-hm-mode]; stato aperto via .is-open. Aspetto (colori, dimensioni,
   posizione fine) sovrascrivibile dal CSS Blocchi del singolo blocco. */
.hamburger-menu { position: relative; }
/* v0.31.2: toggle = icona "spoglia" di default (azzera la cornice nativa del
   <button> e lo stile bottone). Specificità (0,1,0) → ristilabile da CSS Blocchi. */
.hm-toggle {
  cursor: pointer; position: relative; z-index: 1002;
  appearance: none; -webkit-appearance: none;
  background: none; border: none; box-shadow: none;
  padding: .25rem; line-height: 1; color: inherit;
}
/* Icona-immagine del toggle (caricata dalla Library): dimensione di default
   sovrascrivibile da CSS Blocchi (es. width/height sul blocco toggle). */
.hm-toggle .hm-icon-img { display: block; width: 32px; height: auto; }

/* Morph del toggle: "open" (☰/Menù) da chiuso, "close" (✕/Chiudi) da aperto. */
.hamburger-menu:not(.is-open) .hm-toggle-close { display: none; }
.hamburger-menu.is-open .hm-toggle-open { display: none; }

/* Pannello: SEMPRE presente e posizionato (overlay → mai nel flusso, non
   sposta i contenuti), ma nascosto via opacity/visibility così apertura e
   chiusura sono ANIMABILI. Aspetto (sfondo, padding, dimensioni) sovrascrivibile
   da CSS Blocchi. Durata/easing arrivano da --hm-dur / --hm-ease (set da site.js). */
.hm-panel {
  display: flex;
  flex-direction: column;
  gap: var(--el-gap, 16px);
  background: #fff;
  padding: 16px;
  z-index: 1000;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--hm-dur, 200ms) var(--hm-ease, ease),
              transform var(--hm-dur, 200ms) var(--hm-ease, ease),
              visibility var(--hm-dur, 200ms) var(--hm-ease, ease);
}
.hamburger-menu.is-open .hm-panel {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none !important;   /* annulla il transform di partenza dell'anim */
}
/* Posizionamento per modalità — applicato SEMPRE (anche da chiuso) così il
   pannello non è mai nel flusso del documento. */
.hamburger-menu[data-hm-mode="dropdown"] .hm-panel {
  position: absolute; top: 100%; left: 0; z-index: 1001; min-width: 220px;
}
.hamburger-menu[data-hm-mode="fullscreen"] .hm-panel {
  position: fixed; inset: 0; overflow: auto;
}
.hamburger-menu[data-hm-mode="drawer"] .hm-panel {
  position: fixed; top: 0; bottom: 0; width: min(80vw, 320px); overflow: auto;
}
.hamburger-menu[data-hm-mode="drawer"][data-hm-drawer-side="right"] .hm-panel { right: 0; }
.hamburger-menu[data-hm-mode="drawer"][data-hm-drawer-side="left"]  .hm-panel { left: 0; }
/* v0.31.1: mega-menu — quando il PANNELLO è multi-colonna, site.js gli aggiunge
   .block-container--cols (layout a colonne). La regola .hm-panel qui sopra forza
   flex-direction:column: la annulliamo così le colonne si affiancano davvero. */
.hamburger-menu.is-open .hm-panel.block-container--cols {
  flex-direction: row;
  gap: var(--bg-col-gap, 16px);
}

/* ── Animazioni di comparsa (lo stato CHIUSO è il punto di partenza) ──
   fade = solo opacity (default) · none = nessuna transizione ·
   slide/scale impostano un transform iniziale, annullato da .is-open. */
.hamburger-menu[data-hm-anim="none"] .hm-panel,
.hamburger-menu[data-hm-anim="none"] .hm-backdrop { transition: none; }
.hamburger-menu[data-hm-anim="slide"][data-hm-mode="dropdown"]   .hm-panel { transform: translateY(-10px); }
.hamburger-menu[data-hm-anim="slide"][data-hm-mode="fullscreen"] .hm-panel { transform: translateY(-16px); }
.hamburger-menu[data-hm-anim="slide"][data-hm-mode="drawer"][data-hm-drawer-side="right"] .hm-panel { transform: translateX(100%); }
.hamburger-menu[data-hm-anim="slide"][data-hm-mode="drawer"][data-hm-drawer-side="left"]  .hm-panel { transform: translateX(-100%); }
.hamburger-menu[data-hm-anim="scale"] .hm-panel { transform: scale(.96); transform-origin: top; }

/* ── Backdrop / velo scuro (renderizzato da site.js solo se attivato) ── */
.hm-backdrop {
  position: fixed; inset: 0; z-index: 999;
  background: var(--hm-backdrop-color, #000);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--hm-dur, 200ms) var(--hm-ease, ease),
              visibility var(--hm-dur, 200ms) var(--hm-ease, ease);
  -webkit-backdrop-filter: blur(var(--hm-backdrop-blur, 0px));
  backdrop-filter: blur(var(--hm-backdrop-blur, 0px));
}
.hamburger-menu.is-open .hm-backdrop {
  opacity: var(--hm-backdrop-opacity, .5);
  visibility: visible;
  pointer-events: auto;
}

/* ── Blocco scroll pagina mentre un menu (con l'opzione attiva) è aperto ── */
body.hm-scroll-locked { overflow: hidden; }

/* ── Spotlight (v0.32.0) ───────────────────────────────────────
   Hover su una "voce" del gruppo (.spotlight-on) → le altre (.spotlight-target)
   si attenuano (opacità e/o colore), quella sotto il mouse resta/diventa in
   risalto. Soglie via CSS var dal gruppo (site.js). Opacità sempre; colore solo
   se il gruppo ha .spotlight-color. Le regole sono più specifiche del colore dei
   singoli blocchi → vincono senza !important. La voce in risalto è quella più
   "tardi" nel CSS (vince sul dim a parità di specificità). */
.spotlight-on .spotlight-target {
  transition: opacity var(--spot-dur, 150ms) ease, color var(--spot-dur, 150ms) ease;
}
/* ACTIVE (Fase B, "pagina corrente"): le altre attenuate SEMPRE, la voce attiva
   (.spotlight-active, marcata da site.js) in risalto. */
.spot-active .spotlight-target { opacity: var(--spot-dim-opacity, 1); }
.spot-active .spotlight-target.spotlight-active { opacity: var(--spot-focus-opacity, 1); }
.spot-active.spotlight-color .spotlight-target { color: var(--spot-dim-color); }
.spot-active.spotlight-color .spotlight-target.spotlight-active { color: var(--spot-focus-color); }
/* HOVER (Fase A): al passaggio sul gruppo le altre si attenuano, quella sotto il
   mouse in risalto. Definite DOPO le active → in "Entrambi" l'hover vince
   sull'elemento puntato (stessa specificità, ordine sorgente). */
.spot-hover:hover .spotlight-target { opacity: var(--spot-dim-opacity, 1); }
.spot-hover .spotlight-target:hover { opacity: var(--spot-focus-opacity, 1); }
.spot-hover.spotlight-color:hover .spotlight-target { color: var(--spot-dim-color); }
.spot-hover.spotlight-color .spotlight-target:hover { color: var(--spot-focus-color); }
