/* IBEX — responsive, touch and device-safety layer.

   Everything here is either impossible to express inline (media and feature
   queries, env() safe areas, print) or a site-wide rule that would otherwise be
   repeated on fourteen pages. Inline styles still own the visual design; this
   file only adapts it to the device. */

/* ---- 1. Safe areas -------------------------------------------------------
   Notched and rounded-corner devices in landscape put the display cutout over
   the left or right gutter. Pad the scroll container, not each section, so no
   band needs to know about it. */
@supports (padding: max(0px)) {
  body {
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
  }
}

/* ---- 2. Horizontal overflow ---------------------------------------------
   A decorative element that bleeds past the right edge must never create a
   scrollbar. `clip` rather than `hidden`: hidden on <html> makes it a scroll
   container, which moves scrolling to <body>, permanently zeroes window.scrollY
   and silently kills window.scrollTo — breaking deep links, the menu's scroll
   restore and the header's band inversion. */
html { overflow-x: clip; }
body { overflow-x: clip; max-width: 100%; }

/* ---- 3. Touch targets ----------------------------------------------------
   Pointer-coarse devices get a 44px minimum on every navigation-scale control.
   Inline styles never set display or min-height on these, so there is no
   specificity fight. Applied by input type, not by width: a touch laptop
   deserves the same target as a phone. */
@media (hover: none), (pointer: coarse) {
  /*  Due selettori sono usciti da questo elenco perche' non corrispondevano
   *  piu' a niente, e sono stati tolti solo dopo aver misurato che cosa
   *  reggeva gli elementi che nominavano.
   *
   *  [data-consent-open] apriva il banner del consenso, tolto il 26.08.2026
   *  perche' dichiarava cookie che il sito non imposta — home/tests/
   *  test_cookies.py.
   *
   *  [data-langbar] button era doppiamente morto: il selettore di lingua non
   *  si chiama piu' cosi' (sono [data-desklang] e [data-moblang]) e non e'
   *  piu' fatto di `button` ma di `a`. Misurato con il cassetto aperto a
   *  375px: i quattro link di lingua sono alti 44px, e li prende `header nav
   *  a` due righe piu' su. Larghi 14–20px, cioe' sotto misura, ma passano
   *  tutti e quattro per l'eccezione di spaziatura — nessun altro bersaglio
   *  ha il centro entro 24px. */
  header nav a,
  footer nav a,
  footer a[href],
  [data-mobnav] a {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  /* Links inside running prose keep their own line box — turning those into
     44px blocks would wreck the paragraph. */
  p a, li a, dd a, span a, td a { min-height: 0; display: inline; }
}

/* ---- 3b. era la casella di consenso --------------------------------------
   Tolta il 02.09.2026, ESC-22. Vestiva una casella che non esiste: il banner
   dei cookie e' stato ritirato il 26.08.2026, e il modulo di contatto non ne
   ha mai avuta una — home/blocks.py lo dice per esteso, «consent to send a
   message is pressing send in your own mail program», e
   test_no_consent_checkbox_survives impedisce che ne torni una.

   Il secondo selettore era generico, `input[type="checkbox"]`, quindi la sua
   morte non si leggeva dal nome: e' stato misurato che su tutto il sito non
   c'e' nessuna casella, in nessun template. Se un giorno ne servisse una, il
   bersaglio da 44 px va riscritto insieme al campo, non riesumato da qui. */

/* ---- 4. Landscape phones -------------------------------------------------
   A short, wide viewport makes editorial vertical rhythm absurd: the hero
   alone fills two screens. Compress the band padding and the display type. */
@media (max-height: 560px) and (orientation: landscape) and (max-width: 1024px) {
  [data-band] > div { padding-top: 40px !important; padding-bottom: 40px !important; }
  h1 { font-size: clamp(26px, 4.4vw, 40px) !important; }
}

/* ---- 5. Very small phones ------------------------------------------------
   320px is still a real width. Tighten the gutter so line lengths stay usable
   rather than shrinking the type further. */
@media (max-width: 360px) {
  [data-band] > div { padding-left: 18px !important; padding-right: 18px !important; }
}

/* ---- 5b. Cookie tables on small screens ---------------------------------
   A four-column table cannot be read on a 390px phone, and a horizontally
   scrolling legal disclosure is close to unreadable. Below 620px each row
   becomes its own block with the column name printed as a label, so the same
   information reads top to bottom with no scrolling. */
@media (max-width: 620px) {
  table { min-width: 0 !important; }
  thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  tbody tr { display: block; padding: 14px 0; border-bottom: 1px solid currentColor; border-color: color-mix(in srgb, currentColor 16%, transparent); }
  tbody td { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 12px; align-items: baseline;
             border: 0 !important; padding: 4px 0 !important; white-space: normal !important; }
  tbody td::before {
    content: attr(data-label);
    font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
    opacity: .62; line-height: 1.7;
  }
}

/* ---- 5c-5e. erano le tre griglie del sito statico ------------------------
   [data-svcgrid], [data-case] e [data-ledger]: tolte il 02.09.2026, ESC-22.
   Erano i nomi che il sito statico dava alle sue griglie, e la riscrittura li
   ha sostituiti con [data-cols2], [data-cols3] e [data-cols4] senza tornare
   qui — «two shapes wearing thirteen names», dice CLAUDE.md. Nessun template
   li ha mai scritti, e nessuno script li dipinge: misurato su 193 sorgenti di
   markup e sui cinque file JS.

   DOVE VIVONO ORA QUELLE TRE GRIGLIE, che e' la domanda che si fa chi legge
   questo foglio e non le trova: non qui. ibex-layout.js:18-20 dimensiona
   [data-cols4], [data-cols3] e [data-cols2] a 1180 e a 760 px leggendo la
   larghezza, perche' quelle soglie dipendono dal numero di colonne dichiarato
   nel blocco e non da una media query fissa. Cercare qui una regola per le
   discipline o per le situazioni e' cercarla nel foglio sbagliato. */

/* ---- 6. Zoom and text scaling -------------------------------------------
   At 200% zoom the viewport reports ~half its width, so the mobile rules above
   already apply. This keeps tables from forcing a horizontal scroll of the
   whole page — they scroll within their own wrapper instead. */
table { max-width: 100%; }

/* ---- 7. Reduced motion ---------------------------------------------------
   The atmosphere paints one static frame by itself. This covers the CSS-driven
   reveals, transitions and scroll behaviour. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ---- 8. Print ------------------------------------------------------------
   Legal pages get printed. Drop the atmosphere, the chrome and the ink. */
@media print {
  /*  [data-ibex-consent] stava in questo elenco e non corrisponde piu' a
   *  niente: il banner del consenso e' stato tolto il 26.08.2026 perche'
   *  diceva a ogni primo visitatore due cose false — che il sito usa cookie
   *  necessari, e che con il consenso ne usa uno analitico — mentre non ne
   *  imposta nessuno. Si veda home/tests/test_cookies.py. Non e' codice che
   *  potrebbe tornare vivo: e' lo stile di una cosa che una decisione ha
   *  cancellato, e lasciarlo qui fa trovare a chi cerca «consent» in questo
   *  repository l'apparenza di un meccanismo che non c'e'. */
  ibex-atmosphere, header, footer nav, [data-burger], [data-mobnav] { display: none !important; }
  html, body { background: #fff !important; color: #000 !important; }

  /*  CIO' CHE IL LETTORE NON HA ANCORA SCORSO, e che senza questa riga non si
   *  stampa affatto.
   *
   *  `[data-reveal]` parte a opacity:0 in ibex-base.css e arriva a 1 quando
   *  l'IntersectionObserver di ibex-layout.js lo vede entrare nella finestra.
   *  Stampare non scorre: chi apre una pagina e preme stampa senza scendere
   *  stampa a opacita' zero ogni sezione che non ha mai visto. Chi invece
   *  l'aveva letta tutta stampa bene — un difetto che si manifesta o no a
   *  seconda di che cosa ha fatto prima il lettore.
   *
   *  MISURATO sulla home servita il 02.09.2026, finestra 1440x900: la pagina
   *  e' alta 20'020 pixel e porta 21 elementi [data-reveal]. Tutti e 21
   *  cominciano sotto la piega — nessun blocco e' nella prima schermata — per
   *  9'838 caratteri, cioe' il corpo intero della pagina.
   *
   *  LA CORREZIONE C'ERA GIA', SU UNA PAGINA SOLA. Stava in ibex-print.css,
   *  che base.html carica dietro un {% if %} solo sulla nota legale: quattro
   *  pagine su quarantotto. Stesso errore di raggio di [data-shell] qui
   *  sotto, e stessa risposta — riguarda ogni pagina che qualcuno stampi,
   *  quindi sta nel blocco che ogni pagina carica.
   *
   *  NESSUNA PROVA DI STAMPA LO VEDE. Chrome headless dichiara
   *  prefers-reduced-motion: reduce, e la regola che nasconde vive dentro
   *  `no-preference`: in un PDF generato per prova il difetto non c'e'.  */
  html.ibex-js [data-reveal],
  html.ibex-js [data-reveal]:not(.is-in) {
    opacity: 1 !important;
    transform: none !important;
  }
  /*  [data-shell] e' il div di base.html che porta il fondo scuro del sito, e
   *  footer se lo dichiara per conto suo: tutti e due in un attributo style,
   *  che batte ogni selettore senza !important. Sbiancare html e body non li
   *  toccava, e il #0D0D0D restava dipinto sotto e affiorava dove le bande non
   *  arrivano. Misurato sulla nota legale stampata: l'11% della seconda pagina
   *  nero, e la meta' inferiore dell'ultima — una pagina che qualcuno stampa
   *  per tenerla agli atti. Vale per ogni pagina del sito, non solo per
   *  quella, quindi la correzione sta qui e non nel foglio della nota.  */
  [data-shell], footer { background: #fff !important; color: #000 !important; }
  [data-band] { background: #fff !important; color: #000 !important; }

  /*  SBIANCARE IL PIE' DI PAGINA DA SOLO SAREBBE STATO UN PEGGIORAMENTO. Il
   *  suo testo e' --ink-045 #8C857D: sul fondo scuro fa 5.34:1 e passa, sul
   *  bianco fa 3.64:1 e non passa piu'. Le due righe vanno insieme. Stessa
   *  ragione per --ink-060 (2.61:1 sul bianco), --ink-100 (1.17:1) e --mut,
   *  che le bande dichiarano nell'attributo style e che nessun selettore
   *  raggiungerebbe senza !important. I valori non sono inventati: --fg e'
   *  --paper-900, l'inchiostro che il sito usa gia' sulle bande chiare
   *  (17.69:1), e il muto e' un parente piu' scuro di --paper-500 (12.14:1
   *  invece di 6.59:1, perche' su carta il muto porta la dichiarazione
   *  regolamentare e non una didascalia). I filetti restano grigi: sono
   *  linee, non testo, e il criterio non li riguarda.  */
  [data-band], footer {
    --fg: #1A1817 !important;
    --mut: #3A352F !important;
    --acc: #1A1817 !important;
    --gold: #1A1817 !important;
    --ink-100: #1A1817 !important;
    --ink-060: #3A352F !important;
    --ink-045: #3A352F !important;
    --rl: #c9c9c9 !important;
    --rl2: #8a8a8a !important;
  }

  /*  --acc porta i due ruoli in un token solo. In diciotto punti e' colore di
   *  TESTO — gli occhielli, i ruoli delle persone, i numeri, le etichette dei
   *  collegamenti, il codice delle pagine d'errore — e sulla carta bianca fa
   *  2.24:1 sulle bande scure, dove _band.html scrive --acc: var(--gold).
   *  Misurato su una pagina qualsiasi stampata: 230 caratteri sotto soglia.
   *  In un punto solo, il primo pulsante di hero.html, e' un RIEMPIMENTO: li'
   *  annerire il token darebbe nero su nero. Quel punto ha data-cta apposta,
   *  e qui torna un pulsante a filo — fondo bianco, bordo e testo neri —
   *  esattamente come il secondo pulsante che gli sta accanto.  */
  [data-cta] {
    background: #fff !important;
    border-color: #1A1817 !important;
    color: #000 !important;
  }
  /*  IL VELO DELLA BANDA FOTOGRAFICA E' L'UNICA COSA CHE NON SEGUE I TOKEN.
   *  place.html sfuma due gradienti scuri sopra la fotografia perche' la
   *  didascalia le sta accanto su fondo --ink-900: sulla carta bianca quel
   *  fondo non c'e' piu', e il velo resterebbe una macchia grigia sul bordo
   *  inferiore e destro dell'immagine, senza piu' niente da raccordare. Un
   *  gradiente non e' un token e nessuna riscrittura di --fg lo raggiunge,
   *  quindi porta un attributo suo e qui si spegne.  */
  [data-veil] { display: none !important; }
  /*  LA FOTOGRAFIA DELLA HERO E' POSIZIONATA IN ASSOLUTO SULLO SCHERMO. Sopra
   *  900 sta nell'angolo in alto a destra della sezione, che sullo schermo e'
   *  vuoto; su carta la sezione si impagina alla larghezza del foglio e quel
   *  vuoto non esiste piu', quindi il pannello si stamperebbe SOPRA il titolo.
   *  Torna nel flusso, prima del testo, e la maschera si spegne con lui: una
   *  dissolvenza verso sinistra raccorda la fotografia al fondo scuro della
   *  banda, e sulla carta bianca quel fondo non c'e'.  */
  [data-heroland] { position: static !important; width: auto !important; }
  [data-heropanel] {
    height: 56mm !important;
    -webkit-mask-image: none !important;
    mask-image: none !important;
  }
  [data-herocredit] { text-align: left !important; padding: 3mm 0 0 !important; }
  [data-band] > div { padding: 12mm 0 !important; max-width: none !important; }
  a { color: #000 !important; text-decoration: underline; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
  h1, h2, h3 { break-after: avoid; }
  p, li, tr { break-inside: avoid; }
}
