/* ==========================================================================
   DoConure — the public site's design system.

   Four layers, in this order: tokens, base, layout, components. Anything
   added below should say which layer it belongs to, because the one thing
   that kills a system like this is a component that invents its own colour.

   THE SCOPE OF THIS FILE. It dresses the marketing site, the signup pages,
   the login page and the signer-facing pages — every surface somebody sees
   before they are a customer, plus the ones a signer sees. It does **not**
   dress either console: `/tenant/*` and `/admin/*` have their own stylesheet
   in `public/console/console.css` and share nothing with this one. Two
   products that happen to run on one server; that separation was made on
   2026-09-15 because a change to one kept being a change to the other.

   THE GREEN PROBLEM, since it explains half the palette below. The brand
   green is `#46b92d` and it has a contrast ratio of 2.55:1 on white. That is
   fine for a wordmark, a pictogram or a 48px icon, and it fails WCAG AA for
   anything that is text — including white text on a green button, which is
   exactly what a primary CTA is. So the green splits in two: `--green` is
   the identity, used on graphics, and `--green-700` (4.87:1) is the action
   colour, used wherever a green surface or a green word has to be read.
   They are the same hue; nobody notices, and the buttons pass.
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  /* --- surfaces. 75–85% of the page is one of the first three ----------- */
  --white:       #ffffff;
  --paper:       #fbfcfb;   /* a near-white that is not quite the page */
  --soft:        #f4faf3;   /* the pale green band */
  --tint:        #dcf0d6;   /* green wash: rules, bullets, illustration */

  /* --- green ------------------------------------------------------------ */
  --green:       #46b92d;   /* identity. Graphics only — see the note above */
  --green-700:   #2b8217;   /* action: buttons, links, green words. AA 4.87 */
  --green-800:   #1f6b12;   /* action hover.                       AA 6.62 */
  --green-deep:  #087a3e;   /* deep green: Document Fly.           AA 5.44 */

  /* --- accents. Controlled, never a second primary ---------------------- */
  --yellow:      #f4c915;   /* Signer Fly. Graphics only: 1.59 on white */
  --yellow-tint: #fdf7e0;   /* its icon tile */
  --yellow-line: #f4e3a8;   /* that tile's border */
  --yellow-deep: #8a6a00;   /* the same accent when it must carry text */
  --deep-tint:   #e8f4ed;   /* Document Fly's icon tile */
  --deep-line:   #c8e4d4;
  --warm:        #ee4b2f;   /* tertiary, from the feather's red */
  --warm-deep:   #c93a1f;

  /* --- ink -------------------------------------------------------------- */
  --ink:         #17232d;   /* headings, body                     AA 15.97 */
  --ink-2:       #33424e;   /* body on a coloured ground          AA 10.34 */
  --muted:       #5f6d7a;   /* secondary text                      AA 5.31 */
  /*
    There is no second grey, and that is a finding rather than an omission.
    A lighter one has to clear 4.5:1 on all three grounds to carry text, and
    the lightest value that does (#667481, which the brand guide suggests)
    lands at 4.52 on `--soft` — one hundredth above the line, and visually
    almost indistinguishable from `--muted` at 5.01. So the room for two
    grey *text* colours does not exist: there is one, and anything that
    wanted to be fainter than it is either a shape (use `--border-2`) or
    text that should not have been faint.

    The first version of this file had a second grey at #8794a0, commented
    "decorative labels only, never prose", and within a day it was carrying
    the footer's
    column headings at 3.10:1. A token whose rule lives in a comment is a
    token that will be misused; test_palette_contrast.py now holds the rule
    instead.
  */

  /* --- lines and shadows ------------------------------------------------ */
  --border:      #e4e9e6;
  --border-2:    #d3ddd7;
  --shadow-sm:   0 1px 2px rgba(23, 35, 45, .05);
  --shadow:      0 2px 4px rgba(23, 35, 45, .04),
                 0 8px 20px -8px rgba(23, 35, 45, .10);
  --shadow-lg:   0 4px 10px rgba(23, 35, 45, .05),
                 0 24px 48px -20px rgba(23, 35, 45, .18);
  --ring:        0 0 0 3px rgba(70, 185, 45, .30);

  /* --- type ------------------------------------------------------------- */
  --font-display: 'Manrope', 'Inter', -apple-system, BlinkMacSystemFont,
                  'Segoe UI', Roboto, sans-serif;
  --font:         'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
                  Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-mono:    ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
                  'Liberation Mono', monospace;

  /* --- spacing. A 4px grid, named so a gap is chosen and not guessed ---- */
  --s1: .25rem;  --s2: .5rem;   --s3: .75rem;  --s4: 1rem;
  --s5: 1.5rem;  --s6: 2rem;    --s7: 3rem;    --s8: 4rem;
  --s9: 6rem;    --s10: 8rem;

  /* --- radii ------------------------------------------------------------ */
  --r-sm: 6px;  --r: 10px;  --r-lg: 16px;  --r-xl: 22px;  --r-pill: 999px;

  /* --- motion. Fast and restrained; §13 of the brand guide -------------- */
  --t-fast: 120ms cubic-bezier(.4, 0, .2, 1);
  --t:      200ms cubic-bezier(.4, 0, .2, 1);
  --t-slow: 420ms cubic-bezier(.16, 1, .3, 1);

  /* --- layout ----------------------------------------------------------- */
  --shell:  1180px;
  --shell-narrow: 780px;
  --gutter: 16px;          /* the phone gutter the brand guide asks for */
}

@media (min-width: 640px) { :root { --gutter: 28px } }
@media (min-width: 1024px) { :root { --gutter: 40px } }

/* ==========================================================================
   2. BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    /* And no delay: a delayed entrance kept "Signer Fly" invisible for 0.22 s
       even for somebody who asked for no motion (first e2e run, 2026-10-08). */
    animation-delay: 0s !important;
    transition-delay: 0s !important;
  }
}

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.65;
  font-feature-settings: 'cv11' 1;      /* Inter's single-storey a-alternates */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--ink);
  letter-spacing: -.022em;
  line-height: 1.12;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0 }

a { color: var(--green-700); text-decoration: none }
a:hover { color: var(--green-800); text-decoration: underline }

/* A link inside running text must not differ from the words around it by
   colour alone (WCAG 1.4.1). Underline it; navigation, buttons and list
   links keep their quiet look. */
p a:not(.btn), blockquote a, dd a {
  text-decoration: underline; text-decoration-thickness: 1px;
  text-underline-offset: .15em;
}

/* One visible focus ring everywhere, and it is never removed. A keyboard is
   how some people use every page on this site, and how everyone uses the
   signing page when a trackpad is not to hand. */
:focus-visible {
  outline: 2px solid var(--green-700);
  outline-offset: 2px;
  border-radius: 4px;
}

::selection { background: var(--tint); color: var(--ink) }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--white);
  padding: var(--s3) var(--s5); border-radius: 0 0 var(--r) 0;
  font-weight: 600;
}
.skip:focus { left: 0; text-decoration: none; color: var(--white) }

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

/* ==========================================================================
   3. LAYOUT
   ========================================================================== */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.shell--narrow { max-width: var(--shell-narrow) }

/* A band is one horizontal stripe of the page. Two grounds alternate:
   white and the pale green. Nothing else is a background. */
.band { padding-block: clamp(3rem, 6vw, 5.5rem) }
.band--soft { background: var(--soft) }
.band--paper { background: var(--paper) }
.band--tight { padding-block: clamp(2rem, 4vw, var(--s7)) }

.stack > * + * { margin-top: var(--s4) }
.stack-lg > * + * { margin-top: var(--s6) }

.grid { display: grid; gap: var(--s5) }

/* Grid and flex items default to `min-width: auto`, which means "never
   narrower than my content". A <pre> of an API call has no wrap
   opportunities, so on a 360px phone that one element pushed the whole
   column — and with it the page — 16px sideways. `minmax(0, …)` is the
   same fix stated on the track; this states it on the item, so a track
   added later inherits it. */
.grid > *, .split > *, .hero__in > *, .foot__top > * { min-width: 0 }
@media (min-width: 720px) {
  .grid--2 { grid-template-columns: repeat(2, 1fr) }
  .grid--3 { grid-template-columns: repeat(3, 1fr) }
  .grid--4 { grid-template-columns: repeat(2, 1fr) }
}
@media (min-width: 1000px) {
  .grid--4 { grid-template-columns: repeat(4, 1fr) }
}

/* ==========================================================================
   4. COMPONENTS
   ========================================================================== */

/* --- 4.1 the wordmark ------------------------------------------------- */
/*
   Live text, not the supplied raster. The artwork sets the name with two
   capitals (`DocConure`) and the name is `DoConure`; a logotype that
   contradicts the sentence beside it is worse than no logotype. Text also
   scales, selects, translates and stays sharp at any pixel density.
   `Do` green, `Conure` charcoal — the split the capital letter already makes.
*/
.brand {
  display: inline-flex; align-items: center; gap: .6em;
  text-decoration: none; color: inherit;
}
.brand:hover { text-decoration: none }
.brand__mark { width: 2.1rem; height: 2.1rem; flex: none }
.brand__name {
  font-family: var(--font-display);
  font-size: 1.32rem; font-weight: 800;
  letter-spacing: -.028em; color: var(--ink);
  white-space: nowrap;
}
.brand__name b { color: var(--green); font-weight: inherit }
.brand--sm .brand__mark { width: 1.6rem; height: 1.6rem }
.brand--sm .brand__name { font-size: 1.05rem }

/* --- 4.2 buttons ------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .55em;
  font-family: var(--font); font-size: .95rem; font-weight: 600;
  line-height: 1.2; letter-spacing: -.005em;
  padding: .78em 1.35em;
  border-radius: var(--r);
  border: 1px solid transparent;
  cursor: pointer; text-decoration: none;
  transition: background var(--t), border-color var(--t), color var(--t),
              box-shadow var(--t), transform var(--t-fast);
  white-space: nowrap;
}
.btn:hover { text-decoration: none }
.btn:active { transform: translateY(1px) }

.btn--primary { background: var(--green-700); color: var(--white) }
.btn--primary:hover { background: var(--green-800); color: var(--white) }

.btn--secondary {
  background: var(--white); color: var(--ink);
  border-color: var(--border-2); box-shadow: var(--shadow-sm);
}
.btn--secondary:hover {
  border-color: var(--green); color: var(--green-700);
  box-shadow: var(--shadow);
}

.btn--quiet { background: transparent; color: var(--ink); padding-inline: .6em }
.btn--quiet:hover { color: var(--green-700) }

.btn--lg { font-size: 1.02rem; padding: .95em 1.7em; border-radius: var(--r-lg) }
/* `.btn`'s own `white-space: nowrap` is right for the short single-word
   buttons it was written for ("Verifica", "Continua"). A block button is
   full-width by definition, so it has room to wrap and no reason to force
   a line — which matters once its label is a sentence: "Non riesco a
   leggere la mia email — inviami il codice via SMS" on /admin/login is
   longer than its English original and does not fit one line under
   ~420px, and `nowrap` on a button (a flex item, whose default min-width
   is its own unwrapped content) widened the button past the viewport —
   `.panel-page`'s single-column grid then widened every full-width row
   in it, header and footer included, not only the button. Found 2026-09-21
   at 375px; see .claude/kb/50-quality/test-gaps.md GAP-T9. */
.btn--block { width: 100%; display: flex; white-space: normal }

.btn svg { width: 1.05em; height: 1.05em; flex: none }

/* --- 4.3 section headers ---------------------------------------------- */
.eyebrow {
  font-family: var(--font); font-size: .78rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted);
  display: flex; align-items: center; gap: .6em;
}
.eyebrow::before {
  content: ''; width: 1.4rem; height: 2px; border-radius: 2px;
  background: var(--green); flex: none;
}
.eyebrow--center { justify-content: center }

.section-head { max-width: 46rem }
.section-head--center { margin-inline: auto; text-align: center }
.section-head--center .eyebrow { justify-content: center }
.section-head h2 { font-size: clamp(1.8rem, 3.6vw, 2.6rem); margin-top: var(--s4) }
.section-head p { margin-top: var(--s4); color: var(--muted); font-size: 1.08rem }
.section-head--center p { max-width: 38rem; margin-inline: auto }

.lede { font-size: 1.12rem; color: var(--ink-2); line-height: 1.6 }

/* An accented word inside a heading. Uses the action green, not the identity
   green, because it is a word and words get read. */
.hl { color: var(--green-700) }

/* --- 4.4 cards --------------------------------------------------------- */
.card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--s6);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--t), border-color var(--t), transform var(--t);
}
.card--link:hover {
  box-shadow: var(--shadow); border-color: var(--border-2);
  transform: translateY(-2px);
}
.card h3 { font-size: 1.22rem }
.card p { color: var(--muted); margin-top: var(--s3) }

/* The product card. The accent is the only thing that differs between the
   three, which is the point: one brand, three members, not three brands. */
.card--product { display: flex; flex-direction: column }
.card--product .card__icon { margin-bottom: var(--s5) }
.card--product .card__more { margin-top: auto; padding-top: var(--s5) }

.card__icon {
  width: 2.9rem; height: 2.9rem; border-radius: var(--r);
  display: grid; place-items: center; flex: none;
  background: var(--soft); color: var(--green-700);
  border: 1px solid var(--tint);
}
.card__icon svg { width: 1.5rem; height: 1.5rem }

[data-accent='signer'] .card__icon {
  background: var(--yellow-tint); color: var(--yellow-deep); border-color: var(--yellow-line);
}
[data-accent='document'] .card__icon {
  background: var(--deep-tint); color: var(--green-deep); border-color: var(--deep-line);
}

.card__more {
  display: inline-flex; align-items: center; gap: .45em;
  font-weight: 600; font-size: .94rem; color: var(--green-700);
}
.card__more svg { width: .95em; height: .95em; transition: transform var(--t) }
.card--link:hover .card__more svg { transform: translateX(3px) }
[data-accent='signer'] .card__more { color: var(--yellow-deep) }
[data-accent='document'] .card__more { color: var(--green-deep) }

/* --- 4.5 feature list -------------------------------------------------- */
.features { display: grid; gap: var(--s5); margin: 0; padding: 0; list-style: none }
.feature { display: flex; gap: var(--s4); align-items: flex-start }
.feature__icon {
  width: 2.2rem; height: 2.2rem; border-radius: var(--r-sm); flex: none;
  display: grid; place-items: center;
  background: var(--soft); color: var(--green-700); border: 1px solid var(--tint);
}
.feature__icon svg { width: 1.15rem; height: 1.15rem }
.feature h3 { font-size: 1.02rem; font-family: var(--font); font-weight: 650;
              letter-spacing: -.01em; line-height: 1.4 }
.feature p { color: var(--muted); font-size: .96rem; margin-top: .2em }

/* A plain ticked list, for specification-style points. */
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3) }
.ticks li {
  position: relative; padding-left: 1.85rem;
  color: var(--ink-2); font-size: .99rem;
}
.ticks li::before {
  content: ''; position: absolute; left: 0; top: .34em;
  width: 1.15rem; height: 1.15rem; border-radius: 50%;
  background: var(--tint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232b8217' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
              center / .78rem no-repeat;
}

/* --- 4.6 badges and chips ---------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: .45em;
  font-size: .76rem; font-weight: 650; letter-spacing: .02em;
  padding: .3em .7em; border-radius: var(--r-pill);
  background: var(--soft); color: var(--green-700);
  border: 1px solid var(--tint);
}
.badge--signer { background: var(--yellow-tint); color: var(--yellow-deep); border-color: var(--yellow-line) }
.badge--document { background: var(--deep-tint); color: var(--green-deep); border-color: var(--deep-line) }
.badge--neutral { background: var(--paper); color: var(--muted); border-color: var(--border) }

.badge__dot { width: .45em; height: .45em; border-radius: 50%; background: currentColor }

.chips { display: flex; flex-wrap: wrap; gap: var(--s2) }
.chip {
  font-size: .86rem; font-weight: 550; color: var(--ink-2);
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--r-pill); padding: .35em .85em;
}

/* --- 4.7 the value row under the hero ---------------------------------- */
.values { display: grid; gap: var(--s5) }
@media (min-width: 560px) { .values { grid-template-columns: repeat(3, 1fr);
                                      gap: var(--s5) var(--s4) } }
.value { display: flex; gap: var(--s3); align-items: flex-start }
.value svg { width: 1.3rem; height: 1.3rem; color: var(--green-700); flex: none;
             margin-top: .15rem }
.value b { display: block; font-weight: 650; font-size: .95rem; line-height: 1.3 }
.value span { color: var(--muted); font-size: .9rem; line-height: 1.4 }

/* --- 4.8 the hero ------------------------------------------------------ */
.hero { position: relative; overflow: clip; padding-block: var(--s7) var(--s8) }

/* The feather, enormous and almost invisible, behind the product stage.
   §12: the feather as soft abstract background geometry, once, not as a
   parrot on every section. */
.hero__feather {
  position: absolute; pointer-events: none; user-select: none;
  right: -10%; top: -18%; width: min(46rem, 66vw);
  opacity: .09; filter: saturate(1.2);
  transform: rotate(-6deg);
  z-index: 0;
  /* Only the blades. The nib and its drop shadow are the bottom third of
     the artwork, and at 9% opacity they read as a grey thumbprint rather
     than as part of a feather. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0 40%, transparent 72%);
          mask-image: linear-gradient(to bottom, #000 0 40%, transparent 72%);
}
.hero__wash {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(60rem 34rem at 78% 14%, rgba(70, 185, 45, .10), transparent 62%),
    radial-gradient(42rem 28rem at 96% 60%, rgba(244, 201, 21, .09), transparent 60%);
}
.hero__in { position: relative; z-index: 1; display: grid; gap: var(--s8) }
@media (min-width: 980px) {
  .hero__in { grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr);
              align-items: center; gap: var(--s7) }
}
.hero h1 {
  font-size: clamp(2.2rem, 4.4vw, 3.15rem);
  margin-top: var(--s5);
  letter-spacing: -.035em;
}
.hero .lede { margin-top: var(--s5); max-width: 34rem }
.hero__cta { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s6) }
.hero .values { margin-top: var(--s7) }

/* --- 4.9 the product stage (the hero's picture of the product) --------- */
/*
   Drawn, not photographed. §12 asks for the real product experience rather
   than stock photography, and a screenshot of a real document would either
   be a customer's or be invented — so this is the interface reduced to what
   it is: a page being written, a signature going on it, and the three
   products labelling the three moments.
*/
.stage { position: relative; isolation: isolate }
.stage__screen {
  background: var(--white);
  border: 1px solid var(--border-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.stage__bar {
  display: flex; align-items: center; gap: .4rem;
  padding: .7rem .9rem;
  background: var(--paper); border-bottom: 1px solid var(--border);
}
.stage__bar i {
  width: .55rem; height: .55rem; border-radius: 50%;
  background: var(--border-2); display: block;
}
.stage__bar span {
  margin-left: auto; font-size: .72rem; color: var(--muted);
  font-family: var(--font-mono); letter-spacing: -.02em;
}
.stage__doc { padding: var(--s5) var(--s5) var(--s6) }
.stage__title {
  font-family: var(--font-display); font-size: 1rem; font-weight: 700;
  margin-bottom: var(--s4);
}
.stage__line {
  height: .5rem; border-radius: var(--r-pill);
  background: var(--border); margin-bottom: .6rem;
}
.stage__line--soft { background: #eef2ef }
.stage__sign {
  margin-top: var(--s5); padding-top: var(--s4);
  border-top: 1px dashed var(--border-2);
  display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s4);
}
.stage__sig { width: 9.5rem; color: var(--ink) }
.stage__sig svg { width: 100%; height: auto }
.stage__sig small {
  display: block; font-size: .68rem; color: var(--muted);
  border-top: 1px solid var(--border); padding-top: .3rem; margin-top: .2rem;
}

/* The three floating labels. Absolutely placed on a wide screen, and a plain
   row underneath on a narrow one — §14: floating cards must not overlap. */
.stage__tags { display: grid; gap: var(--s3); margin-top: var(--s5) }
.tag {
  display: flex; align-items: flex-start; gap: .7rem;
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--r); padding: .7rem .9rem;
  box-shadow: var(--shadow);
}
.tag__icon {
  width: 1.9rem; height: 1.9rem; border-radius: var(--r-sm); flex: none;
  display: grid; place-items: center;
  background: var(--soft); color: var(--green-700);
}
.tag__icon svg { width: 1.05rem; height: 1.05rem }
.tag--signer .tag__icon { background: var(--yellow-tint); color: var(--yellow-deep) }
.tag--document .tag__icon { background: var(--deep-tint); color: var(--green-deep) }
.tag b { display: block; font-size: .88rem; font-weight: 700; line-height: 1.3 }
.tag span { font-size: .8rem; color: var(--muted); line-height: 1.35 }

@media (min-width: 980px) {
  .stage__tags { display: block; margin-top: 0 }
  .tag { position: absolute; width: 13.5rem; z-index: 2 }
  .tag--composer { top: -1.6rem; left: -3.2rem }
  .tag--signer { top: 28%; right: -3rem }
  .tag--document { bottom: -2.2rem; left: 3% }
  /* Room under the signature for the label that hangs there. A floating
     card that covers the thing it is labelling is worse than no card. */
  .stage__doc { padding-bottom: var(--s9) }
}
@media (min-width: 1180px) {
  .tag--composer { left: -5rem }
  .tag--signer { right: -4.5rem }
}

/* Entrance: the three labels arrive along the document's own path. Fast,
   once, and switched off entirely for prefers-reduced-motion by the rule in
   the base layer. */
@keyframes lift {
  from { opacity: 0; transform: translate3d(0, 14px, 0) }
  to   { opacity: 1; transform: none }
}
.tag { animation: lift var(--t-slow) both }
.tag--composer { animation-delay: .10s }
.tag--signer   { animation-delay: .22s }
.tag--document { animation-delay: .34s }

/* --- 4.10 the workflow ------------------------------------------------- */
.flow { display: grid; gap: var(--s5); counter-reset: step }
@media (min-width: 860px) {
  .flow { grid-template-columns: repeat(4, 1fr); gap: var(--s4) }
}
.flow__step { position: relative; padding-top: var(--s6) }
.flow__step::before {
  counter-increment: step; content: counter(step, decimal-leading-zero);
  position: absolute; top: 0; left: 0;
  font-family: var(--font-mono); font-size: .8rem; font-weight: 600;
  color: var(--green-700); letter-spacing: .04em;
}
/* The dotted path between the steps: the "flight" motif, at its quietest. */
.flow__step::after {
  content: ''; position: absolute; top: .45rem; left: 2.4rem; right: -.6rem;
  border-top: 2px dotted var(--tint);
}
.flow__step:last-child::after { display: none }
@media (max-width: 859px) { .flow__step::after { display: none } }
.flow__step h3 { font-size: 1.08rem; margin-bottom: var(--s2) }
.flow__step p { color: var(--muted); font-size: .96rem }

/* --- 4.11 split section (a product, explained) -------------------------- */
.split { display: grid; gap: var(--s7); align-items: center }
@media (min-width: 940px) {
  .split { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s8) }
  .split--flip .split__media { order: -1 }
}

/* --- 4.12 code snippet -------------------------------------------------- */
.snippet {
  background: #10191f; border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg); overflow: hidden;
  border: 1px solid #1d2a33;
}
.snippet__bar {
  display: flex; align-items: center; justify-content: space-between;
  padding: .7rem 1rem; border-bottom: 1px solid #1d2a33;
  font-size: .74rem; color: #8fa3b0; font-family: var(--font-mono);
  letter-spacing: .02em;
}
.snippet__bar b { color: #d6e2ea; font-weight: 600 }
.snippet pre {
  margin: 0; padding: var(--s5) var(--s5) var(--s6);
  font-family: var(--font-mono); font-size: .8rem; line-height: 1.75;
  color: #d6e2ea; overflow-x: auto;
}
/* Three token colours and no more: a snippet is a picture of an API call,
   not a syntax-highlighting demonstration. Each is checked against the
   #10191f ground rather than against white. */
.snippet .k { color: #8fd66f }   /* keys and verbs      */
.snippet .s { color: #ffd66b }   /* strings             */
.snippet .c { color: #8ba3b3 }   /* comments and labels */

/* --- 4.13 the logo cloud ------------------------------------------------ */
/*
   Built, unused, and that is deliberate. The homepage preview shows three
   customer logos and a quotation; none of them is confirmed, and §17 of the
   brand guide forbids invented customer proof. The component waits here for
   real logos and a real quotation rather than being reinvented on the day
   they arrive.
*/
.logos { display: flex; flex-wrap: wrap; align-items: center;
         justify-content: center; gap: var(--s6) var(--s8) }
.logos img { max-height: 2.2rem; width: auto; opacity: .65;
             filter: grayscale(1); transition: opacity var(--t) }
.logos img:hover { opacity: 1 }

.quote { border-left: 3px solid var(--tint); padding-left: var(--s5) }
.quote p { font-size: 1.05rem; color: var(--ink-2); font-style: italic }
.quote cite { display: block; margin-top: var(--s3); font-style: normal;
              font-size: .88rem; color: var(--muted) }

/* --- 4.14 masthead ------------------------------------------------------ */
.masthead {
  position: sticky; top: 0; z-index: 40;
  background: rgba(255, 255, 255, .88);
  backdrop-filter: saturate(150%) blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--t), box-shadow var(--t);
}
.masthead.is-stuck { border-bottom-color: var(--border); box-shadow: var(--shadow-sm) }
.masthead__in {
  display: flex; align-items: center; gap: var(--s5);
  min-height: 4.4rem;
  position: relative;   /* the narrow-screen menu panel hangs off this */
}
.nav { display: none; align-items: center; gap: var(--s2); margin-left: var(--s5) }
.nav a {
  color: var(--ink-2); font-size: .94rem; font-weight: 550;
  padding: .45em .7em; border-radius: var(--r-sm);
  white-space: nowrap;   /* "Come funziona" on two lines is a taller bar */
  transition: color var(--t), background var(--t);
}
.nav a:hover { color: var(--green-700); background: var(--soft); text-decoration: none }
.masthead__end { display: flex; align-items: center; gap: var(--s2); margin-left: auto }
@media (min-width: 900px) { .nav { display: flex } }

/* The narrow-screen menu. A <details>, so it opens with no JavaScript at
   all — every link in it is a jump to a section of this same page, and a
   menu that needs a script to reveal a same-page anchor is a menu that can
   fail for no reason. `Accedi` stays in the bar rather than inside the
   panel: somebody who already has an account should not have to open a
   menu to say so. */
.menu { margin-left: var(--s1) }
.menu > summary {
  list-style: none; cursor: pointer;
  display: grid; place-items: center;
  width: 2.6rem; height: 2.6rem; border-radius: var(--r-sm);
  color: var(--ink);
}
.menu > summary::-webkit-details-marker { display: none }
.menu > summary:hover { background: var(--soft); color: var(--green-700) }
.menu > summary svg { width: 1.4rem; height: 1.4rem }
.menu__panel {
  position: absolute; left: 0; right: 0; top: 100%;
  background: var(--white); border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow); padding: var(--s3) 0 var(--s5);
}
.menu__panel a {
  display: block; padding: .7rem var(--gutter);
  color: var(--ink-2); font-weight: 550;
}
.menu__panel a:hover { background: var(--soft); color: var(--green-700);
                       text-decoration: none }
.menu[open] > summary { background: var(--soft); color: var(--green-700) }
/* `width: auto`, not the .btn--block 100% it inherits: 100% plus two
   gutters of margin is wider than the panel, and that is a sideways
   scrollbar on a phone. */
.menu__panel .menu__cta { margin: var(--s3) var(--gutter) 0; width: auto;
                          text-align: center }
@media (min-width: 900px) { .menu { display: none } }

/* The home page's bar has seven entries (Contatti joined in 1.2). Measured
   against the wordmark (~140px) and the two buttons (~200px), seven fit only
   once the shell is at its full width (1180px, 1100px inside the gutters),
   and then only set a little closer. Below that, from 900px, the bar keeps
   the narrow-screen menu instead of wrapping or pushing the page sideways.
   The legal pages' four-entry `.nav` keeps the 900px rule above. */
.nav--long { gap: var(--s1); margin-left: var(--s3) }
.nav--long a { padding-inline: .55em }
@media (min-width: 900px) and (max-width: 1179px) {
  .nav.nav--long { display: none }
  .menu.menu--long { display: block }
}

/* Under 560px the bar cannot hold a wordmark, two buttons and a menu
   without pushing the page sideways — and a marketing page that scrolls
   horizontally on a phone is broken, not merely tight. `Inizia ora` moves
   into the panel; the hero repeats it two screens' worth of nothing
   below, so nothing is actually lost. */
@media (max-width: 559px) {
  /* Direct child only: the panel's own CTA is also a .btn--primary,
     and it lives inside this same container. */
  .masthead__end > .btn--primary { display: none }
  .brand__name { font-size: 1.15rem }
  .brand__mark { width: 1.8rem; height: 1.8rem }
}
@media (min-width: 560px) { .menu__panel .menu__cta { display: none } }

/* --- 4.15 call to action ------------------------------------------------ */
.cta {
  background: var(--soft);
  border: 1px solid var(--tint);
  border-radius: var(--r-xl);
  padding: clamp(2rem, 5vw, var(--s8));
  text-align: center;
  position: relative; overflow: hidden;
}
.cta h2 { font-size: clamp(1.7rem, 3.4vw, 2.4rem) }
.cta p { margin-top: var(--s4); color: var(--muted); font-size: 1.06rem }
.cta__actions {
  display: flex; flex-wrap: wrap; gap: var(--s3);
  justify-content: center; margin-top: var(--s6);
}
.cta__note { margin-top: var(--s5); font-size: .88rem; color: var(--muted) }

/* --- 4.16 footer -------------------------------------------------------- */
.foot { background: var(--white); border-top: 1px solid var(--border);
        padding-block: var(--s8) var(--s6) }
.foot__top { display: grid; gap: var(--s7) }
@media (min-width: 820px) {
  .foot__top { grid-template-columns: 1.4fr repeat(3, 1fr) }
}
.foot__about p { margin-top: var(--s4); color: var(--muted); font-size: .94rem;
                 max-width: 22rem }
.foot__h {
  font-family: var(--font); font-size: .78rem; font-weight: 650;
  letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
  margin-bottom: var(--s4);
}
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3) }
.foot ul a { color: var(--ink-2); font-size: .94rem }
.foot ul a:hover { color: var(--green-700) }
.foot__rule { border-top: 1px solid var(--border); margin-block: var(--s7) var(--s5) }
.foot__bot {
  display: flex; flex-wrap: wrap; gap: var(--s4) var(--s6);
  align-items: center; justify-content: space-between;
  font-size: .86rem; color: var(--muted);
}
.foot__bot nav { display: flex; flex-wrap: wrap; gap: var(--s4) }

/* --- 4.17 the panel: a centred card on its own page --------------------- */
/*
   Signup, login, "check your mail", the signer's landing. One shape for
   every page that is a single short form on an empty ground.
*/
.panel-page {
  min-height: 100vh; min-height: 100dvh;
  display: grid; grid-template-rows: auto 1fr auto;
  /* A column no child can widen: one long word used to widen the whole page, header and
     footer included (GAP-T9 2026-09-21, again run4 2026-10-27). */
  grid-template-columns: minmax(0, 1fr);
  background: var(--soft);
}
.panel-page__bar { padding-block: var(--s5) }
.panel-page__main {
  display: grid; grid-template-columns: minmax(0, 1fr); place-items: center;
  padding: var(--s6) var(--gutter);
}
.panel-page__foot {
  padding-block: var(--s5); text-align: center;
  font-size: .84rem; color: var(--muted);
}
/* One standard width for the whole front-door family — sign in, sign up,
   forgot password, choose a password, finish signing up — so a caller
   never notices the box change shape between them, and no page gets its
   own exception. Was 27rem, then 30rem, then 36rem — each still read as
   cramped on an actual desktop screen (owner feedback, 2026-09-21,
   against a real signup_complete.html render): a lone email field looked
   fine but the two-fieldset form did not, and the fix is not a second
   width, it is a wider one. `width: 100%` plus a `max-width` (never a
   fixed width) is what already makes every one of these pages phone- and
   tablet-safe without a media query of its own — widening the standard
   costs nothing there. `.panel--wide` (used to be a separate,
   narrower-by-design exception for the "you're in" page's scrolling code
   blocks) is gone: at this width it bought nothing `.panel` didn't
   already have. */
.panel {
  width: 100%; max-width: 42rem;
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--r-xl); box-shadow: var(--shadow);
  padding: clamp(1.75rem, 5vw, var(--s7));
}
.panel__head { text-align: center; margin-bottom: var(--s6) }
.panel__head h1 { font-size: 1.5rem; margin-top: var(--s5) }
.panel__head p { margin-top: var(--s3); color: var(--muted); font-size: .95rem }
.panel__key {
  font-family: var(--font-mono); font-size: .85rem; word-break: break-all;
  background: var(--paper); border: 1px solid var(--border-2);
  border-radius: var(--r); padding: var(--s4); margin-block: var(--s4);
}
/* The quick-start command on the "you're in" page. Scrolls rather than
   wraps: a cURL with backslash continuations is copied whole, and a soft
   wrap in the middle of one is the difference between a command that runs
   and a command that looks like it should. */
.panel__code {
  font-family: var(--font-mono); font-size: .76rem; line-height: 1.55;
  background: var(--paper); border: 1px solid var(--border-2);
  border-radius: var(--r); padding: var(--s4); margin-block: var(--s3);
  overflow-x: auto; white-space: pre; -webkit-overflow-scrolling: touch;
}
/* Language tabs over the quick-start snippets, built out of radio inputs
   rather than JavaScript. Deliberate, and the same reasoning as the signing
   wizard: this page shows an API key that will never be shown again, so it
   has to be readable and copyable in a browser with scripting off, on a
   corporate laptop, in a webview. Without CSS or without the radios it
   degrades to every snippet stacked — ugly, and every one of them still
   correct and still copyable.

   One `:checked` rule per language, generated in the page rather than
   written out here: the list of languages lives in `composer.quickstart`
   and a hand-written stylesheet would be a second copy of it. */
.snips { margin-block: var(--s4) }
.snips__radio { position: absolute; opacity: 0; pointer-events: none }
.snips__tabs {
  display: flex; flex-wrap: wrap; gap: var(--s2);
  border-bottom: 1px solid var(--border); margin-bottom: var(--s3);
}
.snips__tabs label {
  font-size: .82rem; font-weight: 600; color: var(--muted);
  padding: .4em .75em; border-radius: var(--r) var(--r) 0 0;
  cursor: pointer; border: 1px solid transparent; border-bottom: 0;
  margin-bottom: -1px;
}
.snips__tabs label:hover { color: var(--ink) }
/* The keyboard is not an afterthought here: the radios are the control, so
   the visible focus ring has to move to the label the radio is for. */
.snips__radio:focus-visible + .snips__tabs label[data-for],
.snips__tabs label:focus-visible { outline: 2px solid var(--accent, #1c1c1c); outline-offset: 2px }
.snips__panel { display: none }
.snips__note {
  font-size: .78rem; color: var(--muted); margin-top: calc(var(--s2) * -1);
}

/* A one-time code, and a recovery code in the same box: wide tracking so
   the digits are countable, and no six-character cap, because the day
   somebody loses their phone is the day they type a longer one. */
input.code {
  font-family: var(--font-mono); font-size: 1.4rem; letter-spacing: .3em;
  text-align: center; padding: .5em .2em;
  /* Centred, the width of a code and not of the card, rounded like the button under it
     (1.2: the box used to be a square, full-left stray). */
  display: block; width: 100%; max-width: 15rem; margin-inline: auto;
  border-radius: var(--r);
}
.field:has(> input.code) > span { display: block; text-align: center; margin-bottom: var(--s3) }
.field:has(> input.code) { margin-block: var(--s5) var(--s5) }
/* Signing in with Google. Bordered rather than filled: it is an
   alternative, not the recommendation. */
.sso {
  display: flex; align-items: center; justify-content: center; gap: .6em;
  width: 100%; padding: .75em; margin-top: var(--s4);
  border: 1px solid var(--border-2); border-radius: var(--r);
  color: var(--ink); background: var(--white); font-size: .94rem;
  font-weight: 600;
}
.sso:hover { background: var(--paper); border-color: var(--border-2);
             color: var(--ink); text-decoration: none }
.sso svg { width: 1.15rem; height: 1.15rem }

.panel__who {
  font-size: .88rem; color: var(--muted);
  padding-bottom: var(--s4); margin-bottom: var(--s5);
  border-bottom: 1px solid var(--border);
}
.panel__who strong { color: var(--ink) }

.panel__foot {
  margin-top: var(--s6); padding-top: var(--s5);
  border-top: 1px solid var(--border);
  text-align: center; font-size: .9rem; color: var(--muted);
}

/* --- 4.18 forms --------------------------------------------------------- */
.field { display: block; margin-bottom: var(--s5) }
.field > span {
  display: block; font-size: .88rem; font-weight: 600;
  margin-bottom: var(--s2); color: var(--ink);
}
.field .hint { font-weight: 400; color: var(--muted); font-size: .84rem;
               margin-top: var(--s2); display: block }

input[type=text], input[type=email], input[type=password], input[type=tel],
input[type=number], input.code, select, textarea {
  width: 100%; font-family: var(--font); font-size: 1rem; color: var(--ink);
  background: var(--white);
  border: 1px solid var(--border-2); border-radius: var(--r);
  padding: .7em .85em;
  transition: border-color var(--t), box-shadow var(--t);
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--green); box-shadow: var(--ring);
}
input::placeholder, textarea::placeholder { color: var(--muted) }

.note {
  border-radius: var(--r); padding: var(--s4) var(--s5);
  font-size: .93rem; border: 1px solid var(--border); background: var(--paper);
  color: var(--ink-2);
  /* an address is one word: the closed-signup note's widened /signup to 411px at 320 (run4, 10-27) */
  overflow-wrap: anywhere;
}
.note--error { background: #fdf1ee; border-color: #f6cfc5; color: #8c2a15 }
.note--ok { background: var(--soft); border-color: var(--tint); color: #1d5c11 }
/* A toast sits clear of what follows it, whatever that is (1.2). */
.note { margin-bottom: var(--s5) }
.note + .panel__who { margin-top: 0 }

/* --- 4.19 utilities. Few, and named for what they do -------------------- */
.muted { color: var(--muted) }
.micro { font-size: .84rem; line-height: 1.55 }

/* Compulsory and optional, marked rather than discovered on submit. The
   asterisk is decorative — `aria-required` carries the same fact to a screen
   reader, so the mark is `aria-hidden` and the two never disagree. */
.req { color: var(--danger, #b3261e); font-weight: 700; }
.opt { color: var(--muted); font-weight: 400; font-size: .88em; }
/* The submit is disabled by script once the required fields are known to be
   missing — never in the markup, or a browser with no JavaScript would show
   a button nobody can press. */
.btn[disabled] { opacity: .55; cursor: not-allowed; }

.center { text-align: center }
.mt-4 { margin-top: var(--s4) }
.mt-5 { margin-top: var(--s5) }
.mt-6 { margin-top: var(--s6) }
.mt-7 { margin-top: var(--s7) }

/* --- 4.20 the legal pages ----------------------------------------------
   The published contract, privacy notice, cookie policy, DPA, subprocessor
   list and SLA, plus the price list they point at. Long prose with tables
   in it, which is a shape this stylesheet did not have before: everything
   above is marketing, where nothing runs for twenty screens.

   Two decisions worth stating. The measure is capped at 68 characters
   rather than at the shell, because a contract read edge to edge on a
   1400px monitor is a contract nobody finishes. And the tables scroll
   horizontally inside their own box instead of shrinking: four columns of
   Italian legal prose at 360px is four columns of one word each, and a
   scrollbar is the honest answer.

   New colours: none. Every value here is an existing token, so
   test_palette_contrast.py has already measured it.
   ---------------------------------------------------------------------- */
.legal { padding-block: clamp(2rem, 5vw, var(--s8)) }
.legal__shell { max-width: 62rem }

.legal__head { margin-bottom: var(--s6) }
.legal__head h1 {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 4.4vw, 2.6rem);
  line-height: 1.12; letter-spacing: -.02em; margin: var(--s3) 0 var(--s4);
}
.legal__meta { color: var(--muted); font-size: .92rem }

.legal__draft {
  background: var(--yellow-tint); border: 1px solid var(--yellow-line);
  border-radius: var(--r); padding: var(--s4) var(--s5);
  color: var(--yellow-deep); font-size: .93rem; margin-bottom: var(--s6);
}
.legal__draft p { margin: 0 0 var(--s2) }
.legal__draft p:last-child { margin-bottom: 0 }

.legal-todo {
  color: var(--warm-deep); font-weight: 600; white-space: nowrap;
  border-bottom: 2px dotted var(--warm-deep);
}

/* --- the document body ------------------------------------------------- */
.legal__doc { max-width: 42em; font-size: 1.02rem; line-height: 1.72 }
/* The renderer puts a document's sections at <h2> (the page owns the <h1>,
   and skipping a level breaks the outline for a screen reader), so <h2>
   carries the look the sections always had and <h3> the sub-section look. */
.legal__doc h2 {
  font-family: var(--font-display); font-size: 1.15rem;
  margin: var(--s6) 0 var(--s3);
}
.legal__doc h3 { font-size: 1rem; margin: var(--s5) 0 var(--s3) }
.legal__doc h4 { font-size: .95rem; margin: var(--s4) 0 var(--s2) }
.legal__doc > h2:first-child, .legal__doc > h3:first-child { margin-top: 0 }
.legal__doc p { margin: 0 0 var(--s4) }
.legal__doc ul, .legal__doc ol { margin: 0 0 var(--s4); padding-left: 1.35em }
.legal__doc li { margin-bottom: var(--s2) }
.legal__doc hr { border: 0; border-top: 1px solid var(--border); margin: var(--s6) 0 }
.legal__doc code {
  font-family: var(--font-mono); font-size: .88em;
  background: var(--soft); border-radius: var(--r-sm); padding: .1em .35em;
}
.legal__doc a { color: var(--green-700) }

/* The release notes: the container's full width, one accordion per version. */
.legal__doc--wide { max-width: none; width: 100% }
.release-current {
  display: inline-flex; align-items: baseline; gap: .4em; margin: 0 0 var(--s4);
  padding: .35em .9em; border-radius: var(--r-pill);
  background: var(--soft); border: 1px solid var(--tint); font-size: .95rem;
}
.release-current strong { color: var(--green-800); font-size: 1.05rem }
.releases .release { border-top: 1px solid var(--border) }
.releases .release:last-child { border-bottom: 1px solid var(--border) }
.releases .release > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center;
  gap: var(--s3); padding: var(--s4) 0;
}
.releases .release > summary::-webkit-details-marker { display: none }
.releases .release > summary::before {
  content: ""; flex: none; width: .55em; height: .55em;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(-45deg); transition: transform var(--t-fast);
}
.releases .release[open] > summary::before { transform: rotate(45deg) }
.releases .release > summary h2 { margin: 0 }
.releases .release > summary:focus-visible { outline: 2px solid var(--green-700); outline-offset: 2px }
.release__body { padding: 0 0 var(--s5) calc(.55em + var(--s3)) }
.legal__doc a:hover { color: var(--green-800) }

/* The anchor beside a heading. Invisible until the heading is hovered or
   the link itself is focused, so a keyboard user can still reach it. */
.legal-anchor {
  margin-left: .4em; color: var(--border-2); text-decoration: none;
  opacity: 0; transition: opacity var(--t-fast);
}
h2:hover > .legal-anchor, h3:hover > .legal-anchor,
h4:hover > .legal-anchor, .legal-anchor:focus { opacity: 1 }

.legal__doc blockquote {
  margin: 0 0 var(--s4); padding: var(--s4) var(--s5);
  background: var(--soft); border-left: 3px solid var(--green-700);
  border-radius: 0 var(--r) var(--r) 0; color: var(--ink-2);
}
.legal__doc blockquote p:last-child { margin-bottom: 0 }

/* An editorial note to the reviewing lawyer, kept rather than deleted and
   marked as what it is. See composer/legal.py. */
.legal-note {
  margin: 0 0 var(--s4); padding: var(--s4) var(--s5);
  background: var(--paper); border: 1px dashed var(--border-2);
  border-radius: var(--r); color: var(--muted); font-size: .93rem;
}
.legal-note__tag {
  text-transform: uppercase; letter-spacing: .06em; font-size: .72rem;
  font-weight: 700; color: var(--warm-deep); margin: 0 0 var(--s2);
}
.legal-note p:last-child { margin-bottom: 0 }

/* --- tables ------------------------------------------------------------- */
.table-wrap {
  overflow-x: auto; margin: 0 0 var(--s5);
  border: 1px solid var(--border); border-radius: var(--r);
  -webkit-overflow-scrolling: touch;
}
.table-wrap table { border-collapse: collapse; width: 100%; min-width: 30rem }
.table-wrap th, .table-wrap td {
  text-align: left; vertical-align: top; padding: .7em .9em;
  border-bottom: 1px solid var(--border); font-size: .93rem; line-height: 1.55;
}
.table-wrap thead th { background: var(--soft); font-weight: 700; color: var(--ink) }
.table-wrap tbody tr:last-child td { border-bottom: 0 }

/* --- the index ---------------------------------------------------------- */
.legal__list { display: grid; gap: var(--s4) }
@media (min-width: 720px) { .legal__list { grid-template-columns: repeat(2, 1fr) } }

.legal-card {
  display: block; text-decoration: none; color: inherit;
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--s5);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--t), box-shadow var(--t), transform var(--t);
}
.legal-card:hover {
  border-color: var(--border-2); box-shadow: var(--shadow); transform: translateY(-2px);
}
.legal-card h2 {
  font-family: var(--font-display); font-size: 1.1rem; margin: 0 0 var(--s2);
  color: var(--green-700);
}
.legal-card p { margin: 0; color: var(--ink-2); font-size: .94rem }
.legal-card__meta { margin-top: var(--s3) !important; color: var(--muted) !important;
                    font-size: .84rem !important }

.legal__foot {
  margin-top: var(--s7); padding-top: var(--s5);
  border-top: 1px solid var(--border); max-width: 42em;
}
.legal__foot h2 { font-family: var(--font-display); font-size: 1.2rem; margin: 0 0 var(--s3) }
.legal__foot p { color: var(--ink-2); margin: 0 0 var(--s3) }
.legal__foot code { font-family: var(--font-mono); font-size: .82em; word-break: break-all }

/* --- the price list ------------------------------------------------------ */
.legal__packs {
  display: grid; gap: var(--s4); margin: var(--s5) 0 var(--s6);
  grid-template-columns: 1fr;
}
@media (min-width: 620px) { .legal__packs { grid-template-columns: repeat(2, 1fr) } }
@media (min-width: 980px) { .legal__packs { grid-template-columns: repeat(3, 1fr) } }

.pack {
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--s5); box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column;
}
.pack--featured { border-color: var(--green-700); box-shadow: var(--shadow) }
.pack__tag {
  display: inline-block; align-self: flex-start;
  background: var(--soft); color: var(--green-800);
  border-radius: var(--r-pill); padding: .2em .8em;
  font-size: .74rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; margin: 0 0 var(--s3);
}
.pack h3 { font-family: var(--font-display); font-size: 1.25rem; margin: 0 0 var(--s2) }
.pack__price {
  font-family: var(--font-display); font-size: 1.9rem; font-weight: 800;
  letter-spacing: -.02em; margin: 0 0 var(--s2); color: var(--ink);
}
.pack__price span { font-size: .8rem; font-weight: 600; color: var(--muted); margin-left: .4em }
.pack__credits { margin: 0; font-weight: 600; color: var(--green-700) }
.pack__docs, .pack__unit { margin: 0; color: var(--muted); font-size: .9rem }
.pack__blurb { margin: var(--s3) 0 var(--s4); color: var(--ink-2); font-size: .92rem; flex: 1 }
.pack__gross { margin: 0; color: var(--muted); font-size: .8rem }

/* --- 4.21 consent and acceptance on the signup form ---------------------
   Two boxes that are conditions and two that are not, on the same form.
   They are visually separated because that separation is the substance:
   a consent bundled in with a condition is not freely given, and the
   commonest way to bundle them is to draw them the same.
   ---------------------------------------------------------------------- */
.consent {
  border: 1px solid var(--border); border-radius: var(--r);
  padding: var(--s4); margin: 0 0 var(--s5);
}
.consent legend {
  padding: 0 .5em; font-size: .82rem; font-weight: 700;
  letter-spacing: .02em; color: var(--ink);
}
.consent--optional { background: var(--paper) }
.consent--optional legend { color: var(--muted); font-weight: 600 }

.consent__row {
  display: flex; gap: .7em; align-items: flex-start;
  margin-bottom: var(--s4); cursor: pointer;
}
.consent__row:last-of-type { margin-bottom: 0 }
.consent__row input[type=checkbox] {
  flex: 0 0 auto; width: 1.1rem; height: 1.1rem; margin-top: .18rem;
  accent-color: var(--green-700);
}
.consent__row > span { font-size: .88rem; line-height: 1.55; color: var(--ink-2) }
.consent__row strong { display: block; color: var(--ink); font-weight: 600 }
.consent__row em { display: block; font-style: normal; color: var(--muted);
                   font-size: .84rem; margin-top: .15em }
.consent .micro { margin: var(--s4) 0 0 }

/* The capacity question, and the one box it governs. A radio is drawn like
   the checkboxes beside it because it is the same kind of decision, taken
   once, on the same form.

   `:has` rather than a sibling selector: the radio lives inside its own
   label, which is where a pointer and a screen reader both want it. Where
   `:has` is missing nothing breaks - the approval stays visible, a consumer
   who ticks it is accepted anyway, and the refusal for a business that did
   not tick it comes from the server either way. Hiding it is a courtesy,
   never the enforcement. */
.consent__row input[type=radio] {
  flex: 0 0 auto; width: 1.1rem; height: 1.1rem; margin-top: .18rem;
  accent-color: var(--green-700);
}
form:has(#kind-consumer:checked) .clause-approval { display: none }

.mb-4 { margin-bottom: var(--s4) }

/* --- 4.22 the acceptance interstitial ----------------------------------
   One page, one decision. The contract is shown in a scrollable region
   rather than linked: a page that asks somebody to accept and then sends
   them to another tab to read is designed to be clicked through, and that
   design is what gets looked at afterwards.
   ---------------------------------------------------------------------- */
.legal__pending { margin-bottom: var(--s6) }
.legal__pending-title {
  font-family: var(--font-display); font-size: 1.2rem;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .6em;
  margin: 0 0 var(--s3);
}
.legal__scroll {
  max-height: 26rem; overflow-y: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border); border-radius: var(--r);
  padding: var(--s5); background: var(--white); margin-bottom: var(--s3);
}
.legal__scroll:focus-visible { outline: 2px solid var(--green-700); outline-offset: 2px }
.legal__scroll .legal__doc { max-width: none; font-size: .95rem }
.legal__scroll .legal__doc h2 { font-size: 1.15rem }
.legal__scroll .legal__doc h3 { font-size: 1rem }
.legal__accept { max-width: 42em }

/* --- the FAQ, and the developer note under the hero CTA ----------------
   `<details>` rather than a scripted accordion: the answers have to be in
   the HTML whether or not anything runs, because the two readers that
   matter here — a crawler and an answer engine — do not run scripts, and a
   question whose answer only appears on click is a question nobody
   indexed. Open by keyboard, open by search-in-page, open with CSS off. */
.faq { max-width: 52rem; margin-inline: auto }
.faq__item {
  border-bottom: 1px solid var(--border);
  padding: var(--s4) 0;
}
.faq__item summary {
  cursor: pointer; font-weight: 650; font-size: 1.02rem;
  list-style: none; display: flex; align-items: center; gap: .6em;
}
.faq__item summary::-webkit-details-marker { display: none }
.faq__item summary::before {
  content: "+"; font-family: var(--font-mono); color: var(--muted);
  font-weight: 400; width: 1em; flex: none;
}
.faq__item[open] summary::before { content: "\2212" }
.faq__item p {
  margin: var(--s3) 0 0 1.6em; color: var(--muted);
  font-size: .96rem; line-height: 1.65; max-width: 46rem;
}
.faq__item code { font-family: var(--font-mono); font-size: .88em }
.hero__devnote {
  margin-top: var(--s4); font-size: .88rem; color: var(--muted);
  max-width: 34rem; line-height: 1.6;
}
.value code { font-family: var(--font-mono); font-size: .9em }

/* v1.3 (owner, 2026-10-25): a plan's ribbon on the price list - OFFERTA, or
   ANCORA PER POCO in its last thirty days of sale. Text on a filled ground. */
.ribbon {
  display: inline-block; margin-left: .5em; padding: .1em .55em; border-radius: 999px;
  font-size: .72em; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  vertical-align: middle; background: var(--green-700); color: var(--white);
}
.ribbon--soon { background: var(--warm-deep) }

/* 1.3: the footer link that reopens the consent panel stays out of sight until consent.js
   shows it (only when a channel is configured), whatever display the nav gives its links. */
a[data-consent-open][hidden] { display: none }

/* 1.3 (owner, 2026-10-29): the campaign pages - `/en/` and one page per product, written by
   scripts/build_landing_pages.py. Classes for what index.html does with style= on the spot. */
.card--pad { padding: var(--s6) }
.features--plain { list-style: none; margin: 0; padding: 0 }
.feature__icon--signer { background: var(--yellow-tint); color: var(--yellow-deep); border-color: var(--yellow-line) }

/* The guest's language flag (2026-11-05), top right of the bar: small, one link to the other
   language, never for a signed-in person (`_lang_switch.html`). */
.panel-page__bar .shell, .site-header .shell { display: flex; align-items: center; justify-content: space-between; gap: var(--s3, .75rem) }
.lang-switch { margin-left: auto; display: flex; align-items: center }
.lang-switch a { display: inline-flex; align-items: center; gap: .35rem; min-height: 44px; padding: 0 .5rem;
  font-size: .85rem; font-weight: 600; color: inherit; text-decoration: none; border-radius: 6px }
.lang-switch a:hover, .lang-switch a:focus-visible { background: rgba(0, 0, 0, .05) }
.lang-switch__flag { display: block; border-radius: 2px; box-shadow: 0 0 0 1px rgba(0, 0, 0, .12) }
