/* ============================================================================
   e-karta — public site
   ----------------------------------------------------------------------------
   The first shared stylesheet the public pages have ever had. Before this,
   every marketing page carried its own 200-450 line <style> dump, which is why
   the site had five container widths, three mobile breakpoints, and three pages
   with no media query at all.

   Everything here is expressed in tokens and reads the per-page accent from
   --nav-accent / --nav-gradient, which site/_navbar.html injects from
   app/site/page_colors.py. Pages must not redeclare accent colours.
   ========================================================================== */

:root {
    /* --- layout ------------------------------------------------------------
       One container width. One mobile breakpoint (900px), mirrored in
       static/js/site-sequence.js — change both together. */
    --site-max: 1200px;
    --gutter: clamp(20px, 5vw, 56px);

    /* --- space (4px base) --- */
    --s1: 4px;
    --s2: 8px;
    --s3: 12px;
    --s4: 16px;
    --s5: 24px;
    --s6: 32px;
    --s7: 48px;
    --s8: 64px;
    --s9: 96px;
    --s10: 140px;

    /* --- type ---
       Wide scale contrast plus tight display tracking is what makes this read
       as typeset rather than as a template. */
    --t-display: clamp(38px, 7vw, 82px);
    --t-title: clamp(26px, 3.6vw, 44px);
    --t-sub: clamp(20px, 2.4vw, 28px);
    --t-lead: clamp(17px, 1.5vw, 20px);
    --t-body: 15px;
    --t-small: 13px;
    --t-micro: 11px;

    /* --- ink & ground --- */
    --ink: #f4f4f5;
    --ink-2: rgba(244, 244, 245, .66);
    --ink-3: rgba(244, 244, 245, .40);
    --ground: #383c46;
    --ground-2: #444955;
    --line: rgba(255, 255, 255, .14);
    --line-2: rgba(255, 255, 255, .08);

    /* --- form ---
       Deliberately tight. The old pages used 20-28px radii on everything,
       which is most of what read as "generic AI landing page". */
    --r: 3px;
    --r-lg: 6px;

    --ease: cubic-bezier(.22, .61, .36, 1);
}

/* ---------------------------------------------------------------- reset ---
   Scoped to html.site, which a page opts into with {% block html_class %}site
   {% endblock %}. Nothing here can reach a page that hasn't opted in, so the
   pages outside this redesign are untouched.

   The ground goes on <html> and the body stays transparent on purpose: that is
   what lets the fixed particle canvas (z-index:-1, _base.html:19) show
   through. Bootstrap is still loaded in _base.html for the legacy CMS output,
   so these only need to cover what it leaves alone. */

.site {
    background: var(--ground);
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: var(--ink);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    /* No CSS scroll-behavior on purpose: Lenis owns smooth scrolling on these
       pages (see _base.html), and the two running together animate every
       programmatic scroll twice. In-page links go through Lenis too —
       site-sequence.js routes them. */
}

.site body {
    background: transparent;
    /* Bootstrap sets `color` on body itself, which beats inheritance from
       html.site — without this the whole page renders in Bootstrap's dark
       body colour on a dark ground. */
    color: var(--ink);
    margin: 0;
    overflow-x: hidden;
}

.site h1,
.site h2,
.site h3,
.site h4,
.site p {
    margin: 0;
}

.site img {
    max-width: 100%;
    display: block;
}

/* -------------------------------------------------------------- helpers --- */

.site-wrap {
    max-width: var(--site-max);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

/* Micro label: uppercase, wide tracking, accent, hairline lead-in. Used
   instead of the old emoji pill badges. */
.site-eyebrow {
    display: flex;
    align-items: center;
    /* La distanza dal filetto la dà il margine del ::before, non il gap: il
       gap non vale sugli occhielli che alcune pagine rendono inline-block. */
    gap: 0;
    font-size: var(--t-micro);
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--nav-accent, #0A84FF);
}

.site-eyebrow::before {
    content: "";
    /* Senza un display proprio resta inline, e su un inline non sostituito
       width/height non si applicano: il filetto collassava a zero e spariva
       dove l'occhiello e' inline-block (Servizi, Cataloghi). Nel contesto
       flex delle altre pagine funzionava solo perche' il flex lo blockifica. */
    display: inline-block;
    vertical-align: middle;
    width: 28px;
    height: 1px;
    margin-right: var(--s3);
    background: currentColor;
    opacity: .7;
}

.site-rule {
    height: 1px;
    background: var(--line-2);
    border: 0;
    margin: 0;
}

/* Text link with an accent underline that grows on hover — no pill buttons. */
.site-link {
    display: inline-flex;
    align-items: center;
    gap: var(--s2);
    color: var(--ink);
    text-decoration: none;
    font-size: var(--t-small);
    font-weight: 600;
    letter-spacing: .02em;
    padding-bottom: 3px;
    border-bottom: 1px solid var(--nav-accent, #0A84FF);
    transition: gap .3s var(--ease), color .3s var(--ease);
}

.site-link:hover {
    color: var(--nav-accent, #0A84FF);
    gap: var(--s3);
}

.site-btn {
    display: inline-block;
    padding: var(--s4) var(--s6);
    border: 1px solid var(--nav-accent, #0A84FF);
    border-radius: var(--r);
    color: var(--ink);
    background: transparent;
    text-decoration: none;
    font-size: var(--t-small);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    transition: background .3s var(--ease), color .3s var(--ease);
}

.site-btn:hover {
    background: var(--nav-accent, #0A84FF);
    color: #000;
}

/* ----------------------------------------------------------------- hero --- */

.site-hero {
    max-width: var(--site-max);
    margin-inline: auto;
    padding: calc(var(--s10) + 44px) var(--gutter) var(--s8);
}

.site-hero__title {
    font-size: var(--t-display);
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -.035em;
    margin-top: var(--s5);
    /* Measured, not hard-wrapped: a <br> that reads well at 1440px strands a
       single word on its own line at 1100px. */
    max-width: 15ch;
}

/* One accent word per hero, coloured flat — not a gradient fill. */
.site-hero__title em {
    font-style: normal;
    color: var(--nav-accent, #0A84FF);
}

.site-hero__lede {
    font-size: var(--t-lead);
    line-height: 1.55;
    color: var(--ink-2);
    max-width: 46ch;
    margin-top: var(--s5);
}

.site-hero__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s6);
    margin-top: var(--s7);
    padding-top: var(--s5);
    border-top: 1px solid var(--line-2);
}

.site-hero__stat {
    font-size: var(--t-small);
    color: var(--ink-3);
}

.site-hero__stat b {
    display: block;
    font-size: var(--t-sub);
    font-weight: 600;
    color: var(--ink);
    letter-spacing: -.02em;
    margin-bottom: 2px;
}

/* Two doors out of the hero: into the configurator the page exists to show,
   and to the quote. Without them the hero was a dead end of numbers. */
.site-hero__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s5);
    margin-top: var(--s7);
}

/* ------------------------------------------------------------- sequence ---
   The scroll-driven product sequence. One sticky canvas, one WebGL context;
   the track below it is what the page actually scrolls through, and
   static/js/site-sequence.js maps that scroll offset onto camera, mesh,
   light and print. Nothing here is draggable on purpose. */

.seq {
    position: relative;
}

/* Each half opens with its own heading before the sticky canvas takes over,
   so the two sections read as two chapters rather than one long scroll. */
.seq__intro {
    position: sticky;
    top: 0;
    z-index: 2;
    max-width: var(--site-max);
    margin-inline: auto;
    padding: max(64px, calc(25vh - 160px)) var(--gutter) 0;
    pointer-events: none;
    transition: opacity .45s var(--ease), transform .45s var(--ease);
}

.seq__intro-grid {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: var(--s6);
    pointer-events: none;
}

.seq__intro-copy {
    flex: 1;
    max-width: 56ch;
}

.seq__intro-action {
    flex-shrink: 0;
    pointer-events: auto;
    margin-bottom: 4px;
}

.seq__catalog-btn {
    pointer-events: auto;
    white-space: nowrap;
}

.seq.is-leaving .seq__intro {
    opacity: 0;
    transform: translateY(-20px);
    pointer-events: none;
}

.seq__title {
    font-size: var(--t-title);
    font-weight: 700;
    letter-spacing: -.03em;
    margin-top: var(--s4);
}

.seq__lede {
    font-size: var(--t-lead);
    line-height: 1.55;
    color: var(--ink-2);
    margin-top: var(--s4);
}

@media (max-width: 900px) {
    .seq__intro-grid {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--s4);
    }
    .seq__intro-action {
        margin-top: 0;
        margin-bottom: 0;
    }
}

/* The canvas holder. Sticky rather than fixed so it releases naturally at the
   end of the track instead of needing a scroll listener to unpin it. */
.seq__stage {
    position: sticky;
    top: 25vh;
    /* Above .seq__track. Both are positioned with z-index auto, and the track
       comes later in the document, so without this it paints on top of the
       stage — five screenfuls of transparent div swallowing every click meant
       for the picker inside. */
    z-index: 1;
    height: 75vh;
    /* svh is the viewport WITHOUT the mobile browser's collapsible chrome.
       With plain vh the bottom of the stage — where the picker lives — sits
       under the URL bar on a phone until the user scrolls. */
    height: 75svh;
    width: 100%;
    overflow: hidden;
}

.seq__stage canvas {
    display: block;
    width: 100%;
    height: 100%;
}

/* Tinted wash behind the product, retinted per step via --seq-bg. */
.seq__glow {
    position: absolute;
    inset: 0;
    pointer-events: none;
    /* Alone dietro i prodotti rimosso: era una macchia scura che conteneva
       tutti gli oggetti, e su mobile si notava soprattutto sopra il
       personalizzatore. Il gradiente resta qui, basta rialzare l'opacita'
       per riaverlo. */
    background: radial-gradient(circle at 50% 52%, var(--seq-bg, transparent) 0%, transparent 62%);
    opacity: 0;
    transition: background 1.2s var(--ease);
}

/* Beat navigation: one dot per bag, one for the line-up. site-sequence.js
   lights the dot of the beat in play and scrolls the page on click — the
   models stay scroll-only, the rail only moves the scroll. It tells a
   first-time visitor how much section is left, which a pinned stage never
   otherwise shows. */
.seq__rail {
    position: absolute;
    right: clamp(10px, 2.2vw, 28px);
    top: 50%;
    translate: 0 -50%;
    z-index: 2;
    display: flex;
    flex-direction: column;
    gap: var(--s3);
}

.seq__rail-dot {
    font: inherit;
    width: 10px;
    height: 10px;
    padding: 0;
    border: 0;
    border-radius: 5px;
    background: var(--ink-3);
    cursor: pointer;
    transition: height .35s var(--ease), background .35s var(--ease);
    position: relative;
}

/* Not a bigger dot but a short bar: the active beat reads at a glance, and
   the rail stays a hairline rather than a row of buttons. */
.seq__rail-dot.is-on {
    height: 26px;
    background: var(--nav-accent, #0A84FF);
}

.seq__rail-dot:hover,
.seq__rail-dot:focus-visible {
    background: var(--ink);
    outline: none;
}

/* The bag's name, out to the left of its dot, on hover and on focus — the
   rail names what it jumps to before the jump. */
.seq__rail-dot::after {
    content: attr(data-name);
    position: absolute;
    right: 18px;
    top: 50%;
    translate: 0 -50%;
    white-space: nowrap;
    font-size: var(--t-micro);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-2);
    background: var(--ground);
    border: 1px solid var(--line-2);
    border-radius: var(--r);
    padding: 3px 8px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s var(--ease);
}

.seq__rail-dot:hover::after,
.seq__rail-dot:focus-visible::after {
    opacity: 1;
}

/* The scroll cue: sits over the opening rest pose of a half and leaves with
   the first beat. Above the picker band, dead centre — it is the one thing
   on the stage before anything moves. */
.seq__cue {
    position: absolute;
    left: 50%;
    bottom: clamp(100px, 16vh, 170px);
    translate: -50% 0;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: var(--s2);
    margin: 0;
    font-size: var(--t-micro);
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-3);
    pointer-events: none;
    opacity: 0;
    transition: opacity .5s var(--ease);
}

.seq__cue.is-on {
    opacity: 1;
}

.seq__cue svg {
    animation: seq-cue-dip 1.6s var(--ease) infinite;
}

@keyframes seq-cue-dip {
    0%, 100% { transform: translateY(-2px); opacity: .5; }
    50% { transform: translateY(2px); opacity: 1; }
}

/* A plain overlay across the stage: the captions inside it are positioned
   individually from their own bag's projected screen position, so this element
   only has to not get in the way. */
.seq__copy {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
}

/* One caption per bag, moved every frame by site-sequence.js:placeLabel. The
   transform is the anchor point on the bag, so the offset that turns "at the
   bag's edge" into "beside the bag" lives on an inner margin instead — that
   way JS writes only translate3d and never fights the layout. */
.seq__step {
    position: absolute;
    top: 0;
    left: 0;
    width: min(20rem, 42vw);
    /* No margin at all, in either mode: placeLabel writes the box's TOP-LEFT
       corner after checking that corner against the bag and against the bands
       reserved at the top and bottom of the stage. A margin here would move
       the box after the check had already passed, which is how a caption that
       "fitted" still ended up on the bag. */
    margin: 0;
    opacity: 0;
    will-change: transform;
    transition: opacity .35s var(--ease);
}

.seq__step.is-below {
    width: min(200px, 28vw);
    max-width: 200px;
    text-align: center;
    pointer-events: none;
}

.seq__step.is-on {
    opacity: 1;
}

.seq__step.is-below .seq__idx {
    font-size: var(--t-micro);
    color: var(--nav-accent, #0A84FF);
    font-weight: 700;
    letter-spacing: .08em;
    margin-bottom: 2px;
}

.seq__step.is-below .seq__name {
    font-size: clamp(13px, 1.2vw, 16px);
    font-weight: 700;
    letter-spacing: -.02em;
    margin: 2px 0 4px;
    line-height: 1.15;
    white-space: normal;
}

.seq__step.is-below .seq__claim {
    font-size: clamp(10.5px, 0.85vw, 12px);
    line-height: 1.35;
    color: var(--ink-2);
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.seq__idx {
    font-size: var(--t-micro);
    font-weight: 600;
    letter-spacing: .18em;
    color: var(--ink-3);
    font-variant-numeric: tabular-nums;
}

.seq__name {
    font-size: clamp(32px, 4.6vw, 58px);
    font-weight: 700;
    letter-spacing: -.03em;
    line-height: 1.04;
    margin: var(--s3) 0 var(--s4);
}

.seq__claim {
    font-size: var(--t-lead);
    line-height: 1.5;
    color: var(--ink-2);
}

.seq__track {
    /* Deliberately NOT positioned: it is only a spacer that gives the scroll
       its length, and as a positioned sibling after the sticky stage it
       painted over the stage's own controls. */
}

.seq__status {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--t-micro);
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-3);
    transition: opacity .4s linear;
}

.seq__status.is-hidden {
    opacity: 0;
}

/* Compact real-rendered view: when the sequence finishes,
   virtual 600vh spacer tracks are removed and stages become normal relative
   blocks (~75vh). The page height becomes the REAL height of what is rendered (~3,800px). */
body.page-is-compact .seq,
.seq.is-compact-view {
    position: relative;
    padding-bottom: var(--s8);
}

body.page-is-compact .seq .seq__stage,
.seq.is-compact-view .seq__stage {
    position: relative !important;
    top: auto !important;
    height: 75vh !important;
    height: 75svh !important;
}

body.page-is-compact .seq .seq__track,
body.page-is-compact .seq .seq__rail,
body.page-is-compact .seq .seq__cue,
.seq.is-compact-view .seq__track,
.seq.is-compact-view .seq__rail,
.seq.is-compact-view .seq__cue {
    display: none !important;
}

body.page-is-compact .seq .pick,
.seq.is-compact-view .pick {
    opacity: 1 !important;
    transform: none !important;
    pointer-events: auto !important;
}

body.page-is-compact .seq__intro,
.seq.is-compact-view .seq__intro,
.seq.is-static .seq__intro {
    position: relative !important;
    top: auto !important;
    opacity: 1 !important;
    transform: none !important;
    pointer-events: auto !important;
    padding: var(--s8) var(--gutter) var(--s4) !important;
}

body.page-is-compact .reveal {
    opacity: 1 !important;
    transform: none !important;
}

/* Fallback: below 900px and under prefers-reduced-motion the sequence is not
   built at all (site-sequence.js adds .is-static), and these stills stand in
   for it. Six live meshes is not a phone payload, and a pinned scroll on a
   phone is the fastest way to make a page unusable. */
.seq__fallback {
    display: none;
}

.seq.is-static .seq__stage,
.seq.is-static .seq__track {
    display: none;
}

/* With no sequence to ride on, the picker becomes a normal block under the
   stills — it must still work, it just has nothing to pin to. */
.seq.is-static .pick {
    position: static;
    opacity: 1;
    transform: none;
    pointer-events: auto;
    background: none;
    padding: 0;
}

.seq.is-static .seq__fallback {
    display: grid;
    gap: var(--s6);
    max-width: var(--site-max);
    margin-inline: auto;
    padding: var(--s8) var(--gutter);
}

.seq__card {
    border: 1px solid var(--line-2);
    border-radius: var(--r-lg);
    overflow: hidden;
    background: var(--ground-2);
}

.seq__card img {
    width: 100%;
    /* height:auto is load-bearing, not tidiness: the markup carries
       width="900" height="675" (so the box is reserved before the image
       lands), and without this the used height stays 675px whatever
       aspect-ratio says — the card renders 348x675 instead of 348x261. */
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

.seq__card div {
    padding: var(--s5);
}

/* "…e molto altro" — the closing line of each Promozionale tier, sitting
   after the scroll track with the seamless integrated catalogue transition section. */
.seq__more {
    max-width: var(--site-max);
    margin-inline: auto;
    padding: var(--s9) var(--gutter) var(--s10);
    border-top: 1px solid var(--line-2);
    position: relative;
    z-index: 10;
    clear: both;
}

.seq__more-inner {
    max-width: 54ch;
}

.seq__more-title {
    font-size: var(--t-title);
    font-weight: 700;
    letter-spacing: -.03em;
    margin-top: var(--s4);
}

.seq__more-desc {
    font-size: var(--t-lead);
    line-height: 1.55;
    color: var(--ink-2);
    margin-top: var(--s4);
}

.seq__more-actions {
    margin-top: var(--s6);
    display: flex;
    flex-wrap: wrap;
    gap: var(--s5);
    align-items: center;
}

/* The catalogue-not-live-yet stand-in for a .site-btn: same shape, no
   interaction. */
.site-btn--soon {
    border-color: var(--line);
    color: var(--ink-3);
    cursor: default;
}

.site-btn--soon:hover {
    background: transparent;
    color: var(--ink-3);
}


/* ----------------------------------------------------------- picker ------
   Material and colour swatches: the one thing the visitor drives directly.
   Hover previews on the model, click commits — see site-sequence.js. */

/* Pinned to the bottom of its own section's stage and revealed on the line-up
   beat (site-sequence.js toggles .is-on), so the papers being chosen and the
   three bags they repaint are on screen at the same time. */
.pick {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 3;
    /* Compatto e appoggiato al fondo: le didascalie del carosello occupano
       la fascia sopra, e il pannello deve stare tutto sotto di loro. */
    padding: var(--s6) 0 var(--s5);
    background: linear-gradient(to top, var(--ground) 55%, transparent);
    opacity: 0;
    transform: translateY(18px);
    pointer-events: none;
    transition: opacity .5s var(--ease), transform .5s var(--ease);
}

.pick__inner {
    max-width: var(--site-max);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

.pick.is-on {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

/* Hint on the left, the way back to the catalogue papers on the right: the
   reset is a tertiary action, not a peer of the chips. */
.pick__head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s3) var(--s5);
    /* Il pannello e' ancorato al fondo: stringendo qui la pila si accorcia
       verso il basso, e l'intestazione scende sotto la fascia delle
       didascalie del carosello invece di leggersi sulla loro stessa riga. */
    margin-bottom: var(--s3);
    padding-bottom: 0;
    /* Niente filetto: il pannello sta sotto le didascalie del carosello e la
       riga tagliava orizzontalmente il testo dei prodotti. */
}

/* Stessa voce di .pick__legend e .pick__reset: dentro un pannello di
   etichette tecniche una frase discorsiva in grigio stonava. */
.pick__hint {
    font-size: var(--t-micro);
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.pick__reset {
    font: inherit;
    font-size: var(--t-micro);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    transition: color .25s var(--ease);
}

.pick__reset:hover,
.pick__reset:focus-visible {
    color: var(--nav-accent, #0A84FF);
    outline: none;
}

.pick__group + .pick__group {
    margin-top: var(--s4);
}

.pick__legend {
    font-size: var(--t-micro);
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--ink-3);
    margin-bottom: var(--s4);
}

.pick__row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s3);
}

.pick__chip {
    font: inherit;
    font-size: var(--t-small);
    font-weight: 600;
    color: var(--ink-2);
    background: transparent;
    border: 1px solid var(--line-2);
    border-radius: var(--r);
    padding: var(--s2) var(--s5);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--s2);
    transition: color .25s var(--ease), border-color .25s var(--ease);
}

.pick__chip::before {
    content: "";
    width: 14px;
    height: 14px;
    border-radius: 2px;
    background: var(--chip, #888);
    border: 1px solid rgba(0, 0, 0, .25);
}

.pick__chip:hover,
.pick__chip:focus-visible {
    color: var(--ink);
    border-color: var(--nav-accent, #0A84FF);
}

.pick__chip.is-active {
    color: var(--ink);
    border-color: var(--nav-accent, #0A84FF);
}

/* Reads out the hovered swatch as "material - colour", which is the whole
   point of hovering: the swatch says what it is before you commit to it. */
.pick__label {
    margin-top: var(--s5);
    min-height: 1.4em;
    font-size: var(--t-small);
    letter-spacing: .04em;
    color: var(--nav-accent, #0A84FF);
}

/* -------------------------------------------------------------- 3D stage ---
   One per page, initialised only when scrolled into view. */

.stage {
    max-width: var(--site-max);
    margin-inline: auto;
    padding: var(--s9) var(--gutter);
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--s8);
    align-items: center;
}

.stage__title {
    font-size: var(--t-title);
    font-weight: 700;
    letter-spacing: -.03em;
    margin-top: var(--s4);
}

.stage__text {
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--ink-2);
    margin-top: var(--s4);
}

.stage__actions {
    margin-top: var(--s6);
    display: flex;
    flex-wrap: wrap;
    gap: var(--s5);
    align-items: center;
}

.stage__viewport {
    position: relative;
    aspect-ratio: 1 / 1;
    border: 1px solid var(--line-2);
    border-radius: var(--r-lg);
    overflow: hidden;
    background:
        radial-gradient(circle at 50% 45%,
            rgba(255, 255, 255, .05) 0%,
            transparent 62%),
        var(--ground-2);
}

.stage__viewport canvas {
    display: block;
    width: 100%;
    height: 100%;
}

.stage__status {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--t-micro);
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-3);
    transition: opacity .4s linear;
}

.stage__status.is-hidden {
    opacity: 0;
    pointer-events: none;
}

.stage__badge {
    position: absolute;
    left: var(--s4);
    bottom: var(--s4);
    font-size: var(--t-micro);
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ink-3);
    pointer-events: none;
}

/* ------------------------------------------------------------ statement ---
   A single held claim on its own, set large. Used where the old pages had an
   emoji headline with a paragraph under it. */

.site-statement {
    max-width: var(--site-max);
    margin-inline: auto;
    padding: var(--s8) var(--gutter);
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
    gap: var(--s7);
    align-items: start;
    border-top: 1px solid var(--line-2);
}

.site-statement__body {
    font-size: var(--t-sub);
    line-height: 1.45;
    letter-spacing: -.015em;
    color: var(--ink);
    max-width: 30ch;
}

.site-statement__body span {
    color: var(--ink-3);
}

/* ------------------------------------------------------------------ cta --- */

.site-cta {
    max-width: var(--site-max);
    margin-inline: auto;
    padding: var(--s9) var(--gutter) var(--s10);
    border-top: 1px solid var(--line-2);
}

.site-cta__title {
    font-size: var(--t-title);
    font-weight: 700;
    letter-spacing: -.03em;
    max-width: 18ch;
}

.site-cta__text {
    font-size: var(--t-lead);
    color: var(--ink-2);
    margin-top: var(--s4);
    max-width: 44ch;
}

.site-cta__actions {
    margin-top: var(--s6);
    display: flex;
    flex-wrap: wrap;
    gap: var(--s5);
    align-items: center;
}

/* ----------------------------------------------------------------- where ---
   Dove trovarci — the one page with no sequence and no picker: one compact
   section with the map and the contact cards together, between the shared
   .site-hero and .site-cta. The cards follow the sequence fallback's
   language (hairline border, ground-2, --r-lg) rather than the glassy pills
   the page used to carry. */

.where {
    max-width: var(--site-max);
    margin-inline: auto;
    padding: var(--s9) var(--gutter);
    border-top: 1px solid var(--line-2);
}

.where__head {
    max-width: 56ch;
}

.where__title {
    font-size: var(--t-title);
    font-weight: 700;
    letter-spacing: -.03em;
    margin-top: var(--s4);
}

.where__lede {
    font-size: var(--t-lead);
    line-height: 1.55;
    color: var(--ink-2);
    margin-top: var(--s4);
}

.where__grid {
    display: grid;
    /* Three cards: three across on the desktop container, stacking by itself
       on narrower ones without a second breakpoint to maintain. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
    gap: var(--s5);
    margin-top: var(--s7);
}

.where-card {
    display: flex;
    flex-direction: column;
    gap: var(--s3);
    background: var(--ground-2);
    border: 1px solid var(--line-2);
    border-radius: var(--r-lg);
    padding: var(--s6);
}

.where-card__label {
    font-size: var(--t-micro);
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.where-card__value {
    font-size: var(--t-lead);
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--ink);
}

.where-card__value a {
    color: var(--ink);
    text-decoration: none;
    border-bottom: 1px solid var(--nav-accent, #0A84FF);
    padding-bottom: 2px;
    transition: color .25s var(--ease);
}

.where-card__value a:hover {
    color: var(--nav-accent, #0A84FF);
}

.where-card__note {
    font-size: var(--t-small);
    line-height: 1.55;
    color: var(--ink-2);
}

/* A card's way out ("Indicazioni stradali"), pinned to the bottom edge so
   the four cards keep one baseline however tall their copy is. */
.where-card__foot {
    margin-top: auto;
    padding-top: var(--s4);
}

.where-map__frame {
    margin-top: var(--s7);
    border: 1px solid var(--line-2);
    border-radius: var(--r-lg);
    overflow: hidden;
    background: var(--ground-2);
}

.where-map__frame iframe {
    display: block;
    width: 100%;
    height: clamp(320px, 55vh, 520px);
    border: 0;
    /* Google's embed has no dark theme. Invert + hue-rotate is the standard
       remap: what was white paper becomes the page's dark ground, and the
       roads still read as lines rather than glare. */
    filter: invert(90%) hue-rotate(180deg) saturate(.7);
}

/* --------------------------------------------------------------- footer ---
   site/_footer.html is shared with the pages outside this redesign, so its own
   look stays put; these rules only apply under html.site. Specificity beats
   the partial's own block, which is why the footer had to lose its inline
   style="" attributes first. */

.site .site-footer {
    background: transparent;
    border-top: 1px solid var(--line-2);
    padding: var(--s8) var(--gutter) var(--s7);
    color: var(--ink);
}

.site .site-footer__inner {
    max-width: var(--site-max);
}

.site .site-footer__cols {
    gap: var(--s7);
    margin-bottom: var(--s7);
}

.site .site-footer__brand-link {
    display: inline-block;
    margin-bottom: 12px;
    text-decoration: none;
}

.site .site-footer__logo {
    display: block;
    height: 28px;
    width: auto;
    max-width: 110px;
    object-fit: contain;
}

.site .site-footer__brand {
    font-size: var(--t-sub);
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--ink);
}

.site .site-footer__title {
    font-size: var(--t-micro);
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--nav-accent, #0A84FF);
    font-weight: 600;
    margin-bottom: 20px;
}

.site .site-social {
    margin-top: 16px;
    display: grid;
    gap: 12px;
}

.site .site-footer__tagline,
.site .site-footer__line,
.site .site-footer__col a {
    color: #ffffff;
    font-size: var(--t-small);
}

.site .site-footer__col a:hover {
    color: #ffffff !important;
    text-shadow: 0 0 10px rgba(255,255,255,0.4);
}

.site .site-footer__privacy {
    color: var(--nav-accent, #0A84FF) !important;
}

.site .site-footer__legal {
    border-top: 1px solid var(--line-2);
    padding-top: var(--s5);
}

.site .site-footer__legal p {
    color: #ffffff;
    font-size: var(--t-micro);
    text-align: left;
}

.site .site-social a {
    color: #ffffff;
}

.site .site-social a:hover {
    color: #ffffff;
    text-shadow: 0 0 10px rgba(255,255,255,0.4);
}

/* ------------------------------------------------------------ reveal ------
   _base.html animates .reveal with GSAP. Declaring the start state here means
   pages no longer each ship their own copy (plus a .reveal.active rule that
   nothing ever set). */

.reveal {
    opacity: 0;
    transform: translateY(24px);
}

@media (prefers-reduced-motion: reduce) {
    .reveal {
        opacity: 1;
        transform: none;
    }

    .site *,
    .site *::before,
    .site *::after {
        transition-duration: .01ms !important;
        animation-duration: .01ms !important;
    }
}

/* ----------------------------------------------------------------- 900px ---
   The single mobile breakpoint. The sequence runs on phones too (same beats,
   same line-up — see site-sequence.js, which drops pixel ratio and
   antialiasing to afford it); what changes here is how everything FITS:
   copy across the top, captions under the bags, chips scrolling sideways. */

@media (max-width: 900px) {
    .site-hero {
        padding-top: calc(var(--s9) + 48px);
    }

    /* The sequence runs on phones too. In portrait the single-bag copy
       sits in the lower half of the screen directly under the 3D model,
       ensuring clean separation and maximum legibility. */
    .seq__step {
        width: min(22rem, 86vw);
        margin: 0;
        text-align: left;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
    }

    .seq__step .seq__idx {
        display: inline-block;
        font-size: var(--t-micro);
        text-align: left;
    }

    .seq__step .seq__name {
        font-size: clamp(22px, 5.5vw, 30px);
        margin: 4px 0 6px;
        line-height: 1.15;
        text-align: left;
    }

    .seq__step .seq__claim {
        font-size: clamp(13px, 3.6vw, 15px);
        line-height: 1.45;
        color: var(--ink-2);
        max-width: 34ch;
        margin-inline: 0;
        text-align: left;
    }

    /* During lineup on mobile, hide the 3 individual bag cards so they
       do not collide or overlap with the Carta / Colore picker panel */
    .seq__step.is-below {
        display: none !important;
    }

    /* The rail hugs the right edge at thumb distance; its labels would
       overlap the bags here, so the name stays on the title attribute. */
    .seq__rail {
        right: 8px;
        gap: var(--s2);
    }

    .seq__rail-dot {
        width: 8px;
        height: 8px;
        border-radius: 4px;
    }

    .seq__rail-dot.is-on {
        height: 20px;
    }

    .seq__rail-dot::after {
        display: none;
    }

    /* The cue sits cleanly at the bottom on opening rest pose */
    .seq__cue {
        bottom: 24px;
    }

    /* Picker panel revealed on lineup stage:
       chips arranged in a clean double row (3 columns) so all customization
       options are completely visible at once with zero horizontal scrolling. */
    .pick {
        padding: var(--s4) 0 var(--s5);
        /* Sfumatura pulita verso il fondo pagina. La fermata quasi nera
           (rgba(20,20,22,.95) al 75%) disegnava una banda scura sopra il
           pannello, ben visibile su mobile. */
        background: linear-gradient(to top, var(--ground) 88%, transparent);
    }

    .pick__head {
        margin-bottom: var(--s3);
        padding-bottom: 0;
    }

    .pick__hint {
        /* In scala con .pick__legend mobile, anch'essa a 11px. */
        font-size: 11px;
    }

    .pick__reset {
        font-size: 11px;
    }

    .pick__group + .pick__group {
        margin-top: var(--s3);
    }

    .pick__legend {
        font-size: 11px;
        margin-bottom: var(--s2);
    }

    .pick__row {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 6px;
        padding-bottom: 0;
    }

    .pick__chip {
        font-size: clamp(10px, 2.7vw, 12px);
        font-weight: 500;
        padding: 5px 6px;
        display: flex;
        align-items: center;
        gap: 5px;
        min-width: 0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        border-radius: var(--r);
    }

    .pick__chip::before {
        width: 11px;
        height: 11px;
        flex-shrink: 0;
        border-radius: 2px;
    }

    .pick__label {
        margin-top: var(--s2);
        font-size: 12px;
        min-height: 1.2em;
    }

    .stage {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--s6);
    }

    .stage__viewport {
        aspect-ratio: 4 / 3;
    }

    .site-statement {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--s5);
    }

    .where__grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ------------------------------------------------- clothing dynamic features --- */

/* Techniques section styling */

/* Techniques Module */
.techniques {
    max-width: var(--site-max);
    margin-inline: auto;
    padding: var(--s10) var(--gutter);
}

.techniques__head {
    max-width: 60ch;
    margin-bottom: var(--s8);
}

.techniques__title {
    font-size: var(--t-h2);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.03em;
    margin-top: var(--s3);
}

.techniques__lede {
    font-size: var(--t-lead);
    color: var(--ink-2);
    line-height: 1.55;
    margin-top: var(--s3);
}

.techniques__nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s3);
    margin-bottom: var(--s7);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    padding-bottom: var(--s4);
}

.techniques__tab {
    padding: var(--s3) var(--s5);
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: var(--r);
    color: var(--ink-2);
    font-size: var(--t-small);
    font-weight: 600;
    letter-spacing: .02em;
    cursor: pointer;
    transition: all .25s var(--ease);
}

.techniques__tab:hover {
    color: var(--ink);
    border-color: rgba(255, 255, 255, 0.22);
}

.techniques__tab.is-active {
    background: rgba(10, 132, 255, 0.12);
    border-color: var(--nav-accent, #0A84FF);
    color: #fff;
    box-shadow: 0 0 20px rgba(10, 132, 255, 0.25);
}

.techniques__panels {
    position: relative;
}

.techniques__panel {
    display: none;
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: calc(var(--r) * 1.5);
    padding: var(--s8);
    backdrop-filter: blur(20px);
}

.techniques__panel.is-active {
    display: block;
    animation: techFade .35s var(--ease) forwards;
}

@keyframes techFade {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

.techniques__grid {
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: var(--s8);
    align-items: center;
}

.techniques__info h4 {
    font-size: var(--t-h3);
    font-weight: 700;
    letter-spacing: -.02em;
    margin-bottom: var(--s3);
}

.techniques__info p {
    font-size: var(--t-base);
    color: var(--ink-2);
    line-height: 1.6;
    margin-bottom: var(--s6);
}

.techniques__badges {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s4);
}

.techniques__badge-item {
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: var(--r);
    padding: var(--s4);
}

.techniques__badge-label {
    display: block;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-3);
    margin-bottom: 4px;
}

.techniques__badge-val {
    font-size: var(--t-small);
    font-weight: 600;
    color: var(--ink);
}

/* Lookbook Mix & Match Section */
.lookbook {
    max-width: var(--site-max);
    margin-inline: auto;
    padding: var(--s10) var(--gutter);
}

.lookbook__head {
    max-width: 60ch;
    margin-bottom: var(--s8);
}

.lookbook__title {
    font-size: var(--t-h2);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.03em;
    margin-top: var(--s3);
}

.lookbook__lede {
    font-size: var(--t-lead);
    color: var(--ink-2);
    line-height: 1.55;
    margin-top: var(--s3);
}

.lookbook__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s6);
}

.lookbook__card {
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: calc(var(--r) * 1.5);
    padding: var(--s6);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    transition: transform .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease);
}

.lookbook__card:hover {
    transform: translateY(-4px);
    border-color: rgba(255, 255, 255, 0.22);
    box-shadow: 0 16px 32px rgba(0, 0, 0, 0.4);
}

.lookbook__badge {
    display: inline-block;
    align-self: flex-start;
    padding: 3px 10px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: var(--ink-2);
    margin-bottom: var(--s4);
}

.lookbook__card:nth-child(1) .lookbook__badge { background: rgba(255, 55, 95, 0.15); color: #FF375F; }
.lookbook__card:nth-child(2) .lookbook__badge { background: rgba(10, 132, 255, 0.15); color: #0A84FF; }
.lookbook__card:nth-child(3) .lookbook__badge { background: rgba(48, 209, 88, 0.15); color: #30D158; }

.lookbook__card h3 {
    font-size: var(--t-h3);
    font-weight: 700;
    letter-spacing: -.02em;
    margin-bottom: var(--s2);
}

.lookbook__card p {
    font-size: var(--t-small);
    color: var(--ink-2);
    line-height: 1.5;
    margin-bottom: var(--s5);
}

.lookbook__items {
    list-style: none;
    padding: 0;
    margin: 0 0 var(--s6) 0;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    padding-top: var(--s4);
}

.lookbook__items li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--ink-2);
    margin-bottom: 6px;
}

.lookbook__items li::before {
    content: '✓';
    color: var(--nav-accent, #0A84FF);
    font-weight: 700;
}

.lookbook__action {
    display: inline-flex;
    align-items: center;
    gap: var(--s2);
    font-size: var(--t-small);
    font-weight: 600;
    color: var(--ink);
    text-decoration: none;
    transition: color .25s var(--ease), gap .25s var(--ease);
}

.lookbook__action:hover {
    color: var(--nav-accent, #0A84FF);
    gap: var(--s3);
}

.techniques__preview {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    max-width: 100%;
    overflow: hidden;
    padding: var(--s2) 0;
}

.techniques__preview img,
.techniques__img {
    max-width: min(300px, 100%);
    width: auto;
    height: auto;
    object-fit: contain;
    display: block;
    margin-inline: auto;
    filter: drop-shadow(0 12px 24px rgba(0,0,0,0.5));
}

@media (max-width: 960px) {
    .techniques {
        overflow: hidden;
    }
    .techniques__panel {
        padding: var(--s6) var(--s4);
        overflow: hidden;
    }
    .techniques__grid {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--s6);
        overflow: hidden;
    }
    .techniques__info {
        max-width: 100%;
    }
    .techniques__badges {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--s3);
    }
    .techniques__preview {
        width: 100%;
        max-width: 100%;
        padding: var(--s2) 0;
        overflow: hidden;
    }
    .techniques__preview img,
    .techniques__img {
        max-width: min(220px, 75%) !important;
        height: auto;
        margin-inline: auto;
    }
    .lookbook__grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 480px) {
    .techniques__badges {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ==========================================================================
   Spaziatura titolo -> descrizione

   I margini di titoli e paragrafi vanno scritti con DUE classi: il reset
   `.site h1, ... .site p { margin: 0 }` (riga 94) ha specificita' (0,1,1) e
   contro un selettore a una sola classe (0,1,0) vince lui, azzerando la
   spaziatura senza che si veda un errore. Le regole qui sotto ripristinano
   i margini con (0,2,0), usando i contenitori gia' presenti nel markup.

   L'aria vera la prende solo il titolo principale della pagina (l'hero):
   24px occhiello -> titolo, 32px titolo -> descrizione. Caroselli e sezioni
   interne stanno stretti a 10px, altrimenti ogni scheda sembra un capitolo.
   ========================================================================== */
.site-hero .site-hero__title { margin-top: var(--s5); }
.site-hero .site-hero__lede { margin-top: var(--s6); }

/* Ancorato a `.seq` e non a `.seq__intro-copy`: Abbigliamento e Shopper
   mettono il titolo direttamente dentro `.seq__intro`, senza la griglia
   interna che usano Packaging e Promozionale. */
.seq .seq__title { margin-top: 10px; }
.seq .seq__lede { margin-top: 10px; }

/* Didascalie del carosello prodotti: spazio fra nome e descrizione.
   La variante compatta `.seq__step.is-below .seq__name` (riga 520) ha
   specificita' maggiore e resta con i suoi margini piccoli, come deve. */
.seq .seq__name { margin: 10px 0; }

.where__head .where__title { margin-top: 10px; }
.where__head .where__lede { margin-top: 10px; }

.techniques__head .techniques__title { margin-top: 10px; }
.techniques__head .techniques__lede { margin-top: 10px; }

.site-cta .site-cta__text { margin-top: 10px; }

/* Stesso motivo, sui blocchi rimasti indietro: selettore a una classe su un
   tag heading/paragrafo, margine mangiato dal reset. */
.pick .pick__legend { margin-bottom: var(--s4); }
.pick .pick__label { margin-top: var(--s3); }
.site-footer .site-footer__line { margin: 0 0 8px; }
