/* ============================================================================
 * MATRICE FTTH SWISSCOM — FEUILLE DE STYLE
 * ----------------------------------------------------------------------------
 * Fichier : css/app.css
 * Charte  : Kito Digital — glassmorphism dark, liserés dégradés, Syne + DM Sans
 * Méthode : mobile-first, une seule main, lisible au soleil (thème « Soleil »)
 *
 * Sommaire
 *   1.  Tokens & thèmes
 *   2.  Base & accessibilité
 *   3.  En-tête applicative
 *   4.  Barre de recherche
 *   5.  Sélecteur de câble
 *   6.  Carte résultat
 *   7.  Liste de résultats
 *   8.  Pavé numérique
 *   9.  Historique & favoris
 *   10. Matrice
 *   11. Légende, encarts & FAQ
 *   12. Bannière d'installation & mise à jour
 *   13. Pied de page
 *   14. Responsive & préférences système
 * ==========================================================================*/

/* ============================================================================
 * 1. TOKENS & THÈMES
 * ==========================================================================*/
:root {
  /* Charte Kito Digital */
  --ow-primary:        #7C5CFF;
  --ow-accent:         #2EE5FF;
  --ow-bg:             #070A12;
  --ow-bg-secondary:   #0B1020;
  --ow-card:           #111827;
  --ow-text:           #EAF0FF;
  --ow-text-secondary: #94A3B8;
  --ow-border-accent:  rgba(124, 92, 255, 0.25);
  --ow-glow:           rgba(124, 92, 255, 0.25);
  --ow-edge-gradient:  linear-gradient(90deg, transparent, #7C5CFF, #2EE5FF, transparent);

  --radius:    20px;
  --radius-sm: 12px;
  --radius-xs: 8px;

  --font-heading: "Syne", ui-sans-serif, system-ui, sans-serif;
  --font-body:    "DM Sans", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Couleurs fibres — standard Swisscom (source de vérité : js/core.js) */
  --c-rouge:     #E8211B;
  --c-vert:      #00A651;
  --c-jaune:     #FFE200;
  --c-bleu:      #0050C8;
  --c-blanc:     #F0F0EE;
  --c-violet:    #7A2E9A;
  --c-orange:    #F07428;
  --c-noir:      #141414;
  --c-gris:      #969696;
  --c-brun:      #804828;
  --c-rose:      #E8007E;
  --c-turquoise: #00B4C8;

  /* Sémantique d'interface (surchargée par le thème Soleil) */
  --surface:        rgba(17, 24, 39, 0.72);
  --surface-solid:  #111827;
  --surface-raised: rgba(23, 32, 52, 0.86);
  --border:         rgba(255, 255, 255, 0.08);
  --border-strong:  rgba(124, 92, 255, 0.28);
  --shadow:         0 8px 32px rgba(0, 0, 0, 0.45);
  --blur:           blur(18px) saturate(160%);
  --danger:         #FF5B6E;
  --success:        #2EE5FF;

  /* Ergonomie terrain : cible tactile minimale WCAG 2.2 (44 px) */
  --touch:     48px;
  --touch-lg:  56px;
  --gap:       1rem;
  --pad:       clamp(0.85rem, 3vw, 1.5rem);
  --cell:      clamp(42px, 11vw, 54px);
  --rowhead:   clamp(62px, 20vw, 92px);
  --transition: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---- Thème « Soleil » : contraste maximal, aucun effet coûteux ------------ */
[data-theme="sun"] {
  --ow-bg:             #FFFFFF;
  --ow-bg-secondary:   #F1F4FA;
  --ow-card:           #FFFFFF;
  --ow-text:           #05070D;
  --ow-text-secondary: #333C4D;
  --ow-primary:        #4B23D6;
  --ow-accent:         #005E75;
  --ow-border-accent:  rgba(0, 0, 0, 0.45);
  --ow-glow:           transparent;
  --ow-edge-gradient:  linear-gradient(90deg, transparent, #4B23D6, #005E75, transparent);

  --surface:        #FFFFFF;
  --surface-solid:  #FFFFFF;
  --surface-raised: #F1F4FA;
  --border:         rgba(0, 0, 0, 0.35);
  --border-strong:  rgba(0, 0, 0, 0.65);
  --shadow:         0 2px 8px rgba(0, 0, 0, 0.22);
  --blur:           none;
  --danger:         #B3001B;
  --success:        #005E75;
}

/* Repli si backdrop-filter n'est pas supporté : fonds pleins. */
@supports not (backdrop-filter: blur(1px)) {
  :root {
    --surface:        #111827;
    --surface-raised: #172034;
  }
}

/* ============================================================================
 * 2. BASE & ACCESSIBILITÉ
 * ==========================================================================*/
*, *::before, *::after { box-sizing: border-box; }

/* L'attribut `hidden` doit toujours l'emporter.
   La règle du navigateur ([hidden]{display:none}) provient de sa feuille par
   défaut : n'importe quelle règle d'auteur posant `display` la neutralise
   silencieusement. C'est ce qui laissait apparaître l'image cassée du logo
   MX Solution alors même que le repli texte s'était activé. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  min-height: 100svh;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ow-text);
  background: var(--ow-bg);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* Encoches iPhone + barre de gestes */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* Halo d'ambiance — désactivé en thème Soleil pour la lisibilité */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(ellipse 70% 40% at 12% 0%,   rgba(124, 92, 255, 0.10) 0%, transparent 62%),
    radial-gradient(ellipse 55% 38% at 88% 100%, rgba(46, 229, 255, 0.06) 0%, transparent 62%);
}
[data-theme="sun"] body::before { background: none; }

h1, h2, h3 { font-family: var(--font-heading); font-weight: 800; margin: 0; line-height: 1.2; }
p  { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }

a { color: var(--ow-accent); }
[data-theme="sun"] a { color: var(--ow-primary); }

button, input, select {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
}

/* Focus visible partout — exigence WCAG 2.4.7 */
:focus-visible {
  outline: 3px solid var(--ow-accent);
  outline-offset: 2px;
  border-radius: 4px;
}
[data-theme="sun"] :focus-visible { outline-color: var(--ow-primary); }

/* Contenu réservé aux lecteurs d'écran */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Lien d'évitement */
.skip-link {
  position: absolute;
  top: -100px; left: 8px;
  z-index: 999;
  padding: 0.7rem 1.1rem;
  background: var(--ow-primary);
  color: #fff;
  border-radius: var(--radius-xs);
  font-weight: 700;
  text-decoration: none;
}
.skip-link:focus { top: 8px; }

.app {
  max-width: 1360px;
  margin: 0 auto;
  padding: 0 var(--pad) 3rem;
}

/* Liseré dégradé — signature visuelle Kito Digital */
.edge::after {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 100%;
  height: 1px;
  background: var(--ow-edge-gradient);
  opacity: 0.75;
  pointer-events: none;
}

/* Badge pill de section */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.28rem 0.85rem;
  border-radius: 100px;
  background: rgba(124, 92, 255, 0.14);
  border: 1px solid var(--ow-border-accent);
  color: var(--ow-accent);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  white-space: nowrap;
}
[data-theme="sun"] .pill { background: #E7E1FF; color: #2E128F; border-color: #2E128F; }

/* Carte générique */
.card {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
}

.section-title {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.95rem;
  margin-bottom: 0.75rem;
}

/* ============================================================================
 * 3. EN-TÊTE APPLICATIVE
 * ==========================================================================*/
.appbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.85rem 0 1.6rem;
}

/* Logo seul, sans pastille : le texte porte la marque.
   Colonne alignée à gauche, verticalement centrée face aux boutons d'action. */
.brand {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  gap: 0.1rem;
  min-width: 0;
  min-height: var(--touch);
}

/* Seul le logo est cliquable. Zone de clic élargie par le padding, décalage
   négatif pour que le texte reste aligné sur le sous-titre. */
.brand-link {
  display: inline-block;
  padding: 0.25rem 0.4rem;
  margin: -0.25rem -0.4rem;
  border-radius: var(--radius-xs);
  text-decoration: none;
  transition: background var(--transition);
}
.brand-link:hover { background: var(--surface-raised); }

.brand-name {
  display: block;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(1.05rem, 4.4vw, 1.3rem);
  letter-spacing: -0.02em;
  line-height: 1.1;
  white-space: nowrap;
  color: var(--ow-text);
}

/* Variante image, si un fichier de logo est utilisé à la place du texte. */
.brand-logo {
  display: block;
  height: clamp(24px, 6vw, 30px);
  width: auto;
}
.brand-name .grad {
  background: linear-gradient(90deg, var(--ow-primary), var(--ow-accent));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--ow-primary);
}
[data-theme="sun"] .brand-name .grad {
  -webkit-text-fill-color: var(--ow-primary);
  color: var(--ow-primary);
}
.brand-sub {
  display: block;
  max-width: 100%;
  font-size: 0.68rem;
  line-height: 1.2;
  color: var(--ow-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.appbar-actions { display: flex; align-items: center; gap: 0.4rem; flex-shrink: 0; }

/* -----------------------------------------------------------------------------
   TITRE PRINCIPAL — volontairement compact.
   Il pose le sujet de la page pour le référencement et pour le lecteur, sans
   repousser la barre de recherche hors de portée du pouce.
   -------------------------------------------------------------------------- */
.intro { padding: 0 0 0.55rem; }
.intro h1 {
  font-size: clamp(1.15rem, 4.6vw, 1.6rem);
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.intro p {
  margin-top: 0.25rem;
  max-width: 62ch;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ow-text-secondary);
}

.icon-btn {
  width: var(--touch); height: var(--touch);
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--ow-text);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.icon-btn:hover { border-color: var(--border-strong); background: rgba(124, 92, 255, 0.14); }
.icon-btn:active { transform: scale(0.94); }
.icon-btn svg { width: 21px; height: 21px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.icon-btn[aria-pressed="true"] { background: var(--ow-primary); border-color: var(--ow-primary); color: #fff; }

/* ============================================================================
 * 4. BARRE DE RECHERCHE (collante — reste accessible au pouce)
 * ==========================================================================*/
.searchbar {
  position: sticky;
  top: 0;
  z-index: 60;
  padding: 0.5rem 0 0.65rem;
  background: linear-gradient(to bottom, var(--ow-bg) 68%, transparent);
}
[data-theme="sun"] .searchbar { background: var(--ow-bg); }

.search-shell {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--touch-lg);
  padding: 0 0.5rem 0 1rem;
  border-radius: 100px;
  background: var(--surface-raised);
  border: 2px solid var(--border-strong);
  box-shadow: var(--shadow);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.search-shell:focus-within {
  border-color: var(--ow-primary);
  box-shadow: 0 0 0 4px rgba(124, 92, 255, 0.2), var(--shadow);
}

.search-icon {
  flex-shrink: 0;
  width: 20px; height: 20px;
  stroke: var(--ow-accent); fill: none; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
}

#search-input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  padding: 0.6rem 0;
  font-family: var(--font-mono);
  /* 16px minimum : empêche le zoom automatique iOS au focus */
  font-size: max(1.05rem, 16px);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ow-text);
  caret-color: var(--ow-accent);
}
#search-input::placeholder {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.92rem;
  color: var(--ow-text-secondary);
  opacity: 1;
}

.search-btn {
  flex-shrink: 0;
  width: 42px; height: 42px;
  display: none;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.08);
  color: var(--ow-text-secondary);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.search-btn.visible { display: grid; }
.search-btn svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 2.6; stroke-linecap: round; }
.search-btn:hover { color: var(--ow-text); background: rgba(255, 255, 255, 0.16); }

/* Suggestions contextuelles */
.suggestions {
  display: flex;
  gap: 0.4rem;
  overflow-x: auto;
  padding: 0.55rem 0.15rem 0.1rem;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.suggestions::-webkit-scrollbar { display: none; }
.suggestions:empty { display: none; }

.suggestion {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  min-height: 40px;
  padding: 0.3rem 0.8rem;
  border-radius: 100px;
  border: 1px solid var(--border-strong);
  background: rgba(124, 92, 255, 0.1);
  color: var(--ow-text);
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.suggestion .hint { font-size: 0.62rem; font-weight: 400; color: var(--ow-text-secondary); }
.suggestion:active { transform: scale(0.96); }

/* ============================================================================
 * 5. SÉLECTEUR DE CÂBLE
 * ==========================================================================*/
.cable-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: var(--gap);
}

.cable-scroll {
  display: flex;
  gap: 0.35rem;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  padding: 0.2rem 0.1rem;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.cable-scroll::-webkit-scrollbar { display: none; }

.cable-tab {
  flex-shrink: 0;
  scroll-snap-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-width: 66px;
  min-height: 46px;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--ow-text-secondary);
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.cable-tab .cap { font-family: var(--font-body); font-size: 0.56rem; font-weight: 400; opacity: 0.75; }
.cable-tab:hover { color: var(--ow-text); border-color: var(--border-strong); }
.cable-tab:active { transform: scale(0.95); }
.cable-tab[aria-pressed="true"] {
  color: #fff;
  background: linear-gradient(135deg, var(--ow-primary), #5438CC);
  border-color: var(--ow-primary);
  box-shadow: 0 0 14px var(--ow-glow);
}
.cable-tab.mono[aria-pressed="true"] {
  background: linear-gradient(135deg, #0A7A8A, #04505E);
  border-color: var(--ow-accent);
}
[data-theme="sun"] .cable-tab[aria-pressed="true"] { background: var(--ow-primary); box-shadow: none; }

.cable-group-label {
  flex-shrink: 0;
  align-self: stretch;
  display: grid;
  place-items: center;
  width: 34px;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 0.52rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ow-text-secondary);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

/* ============================================================================
 * 6. CARTE RÉSULTAT
 * ==========================================================================*/
.result-zone { margin-bottom: var(--gap); }
.result-zone:empty { display: none; }

.result-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  border: 2px solid var(--border-strong);
  background: var(--surface-raised);
  box-shadow: var(--shadow), 0 0 28px rgba(124, 92, 255, 0.1);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  animation: slide-in 0.2s ease both;
}
[data-theme="sun"] .result-card { box-shadow: var(--shadow); }

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

.result-head {
  display: flex;
  align-items: stretch;
}

/* Pastille couleur de la fibre — l'information la plus lue sur le terrain */
.fiber-chip {
  position: relative;
  flex-shrink: 0;
  width: clamp(96px, 27vw, 130px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  padding: 1rem 0.5rem;
  overflow: hidden;
}
/* Double strie noire — rendu fidèle du marquage réel */
.fiber-chip.striped::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    transparent 20%, rgba(0,0,0,0.42) 20%, rgba(0,0,0,0.42) 26%,
    transparent 26%, transparent 72%, rgba(0,0,0,0.42) 72%,
    rgba(0,0,0,0.42) 78%, transparent 78%);
}
.fiber-chip > * { position: relative; z-index: 1; }
.fiber-chip .num {
  font-family: var(--font-mono);
  font-size: clamp(2rem, 9vw, 2.7rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
}
.fiber-chip .cname { font-size: 0.86rem; font-weight: 700; text-align: center; }
.fiber-chip .mark {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 1px 7px;
  border-radius: 100px;
  background: rgba(0, 0, 0, 0.3);
}
.fiber-chip.on-light .mark { background: rgba(255, 255, 255, 0.45); }

.result-body {
  flex: 1;
  min-width: 0;
  padding: 0.8rem 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  border-left: 1px solid var(--border);
}

.result-kicker {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ow-text-secondary);
}

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 0.4rem; }

.fact {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 0.45rem 0.6rem;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
}
[data-theme="sun"] .fact { background: var(--surface-raised); }
.fact dt {
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ow-text-secondary);
}
.fact dd {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--font-mono);
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--ow-text);
}
.fact .swatch {
  width: 13px; height: 13px;
  flex-shrink: 0;
  border-radius: 3px;
  border: 1px solid rgba(255, 255, 255, 0.35);
}
[data-theme="sun"] .fact .swatch { border-color: #000; }
.fact.key { border-color: var(--border-strong); background: rgba(124, 92, 255, 0.12); }
.fact.key dd { color: var(--ow-accent); }
[data-theme="sun"] .fact.key { background: #E7E1FF; }
[data-theme="sun"] .fact.key dd { color: #2E128F; }

.result-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 42px;
  padding: 0.5rem 0.95rem;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--ow-text);
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  transition: var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.btn svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.btn:hover { border-color: var(--border-strong); }
.btn:active { transform: scale(0.97); }
.btn.primary {
  background: linear-gradient(135deg, var(--ow-primary), #5438CC);
  border-color: var(--ow-primary);
  color: #fff;
}
[data-theme="sun"] .btn.primary { background: var(--ow-primary); }
.btn.on { border-color: var(--ow-accent); color: var(--ow-accent); }

/* -----------------------------------------------------------------------------
   FIBRE NON COLORÉE — position 20

   Les positions 13 à 24 reprennent les douze couleurs, marquées d'une bague
   noire. Sur la fibre noire, cette bague serait invisible : la fibre de rang
   « Noir » est donc livrée naturelle, translucide.

   Un damier discret signale cette transparence, comme dans un logiciel
   d'image. Il se glisse SOUS la bague grâce à un z-index négatif, sans créer
   d'élément de flux supplémentaire.
   -------------------------------------------------------------------------- */
.natural { position: relative; }
.natural::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.5;
  background-image:
    linear-gradient(45deg, rgba(90, 110, 130, 0.35) 25%, transparent 25%, transparent 75%, rgba(90, 110, 130, 0.35) 75%),
    linear-gradient(45deg, rgba(90, 110, 130, 0.35) 25%, transparent 25%, transparent 75%, rgba(90, 110, 130, 0.35) 75%);
  background-size: 8px 8px;
  background-position: 0 0, 4px 4px;
}
/* Le contenu de la cellule reste au-dessus du damier. */
.natural > * { position: relative; z-index: 1; }
[data-theme="sun"] .natural::before { opacity: 0.7; }

/* Bandeau d'avertissement pour les données indicatives */
.result-note {
  display: flex;
  align-items: flex-start;
  gap: 0.45rem;
  padding: 0.55rem 0.9rem;
  border-top: 1px solid var(--border);
  background: rgba(255, 200, 60, 0.08);
  font-size: 0.72rem;
  color: var(--ow-text-secondary);
}
[data-theme="sun"] .result-note { background: #FFF4D6; color: #4A3800; }
.result-note svg { flex-shrink: 0; width: 15px; height: 15px; margin-top: 2px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }

/* États erreur / vide */
.state-card {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  padding: 0.9rem 1rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
}
.state-card.error { border-color: var(--danger); background: rgba(255, 91, 110, 0.09); }
[data-theme="sun"] .state-card.error { background: #FFE7EA; }
.state-card svg { flex-shrink: 0; width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.state-card .msg { font-size: 0.88rem; font-weight: 600; }
.state-card .hints { margin-top: 0.45rem; display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.76rem; color: var(--ow-text-secondary); }
.state-card .hints code {
  font-family: var(--font-mono);
  color: var(--ow-accent);
  background: rgba(46, 229, 255, 0.1);
  border-radius: 4px;
  padding: 0 4px;
}
[data-theme="sun"] .state-card .hints code { color: #00404F; background: #D9F2F8; }

/* ============================================================================
 * 7. LISTE DE RÉSULTATS MULTIPLES
 * ==========================================================================*/
.result-list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0.75rem 0.95rem;
  border-bottom: 1px solid var(--border);
}
.result-list-head h2 { font-size: 0.95rem; }
.result-list-head .meta { font-family: var(--font-mono); font-size: 0.72rem; color: var(--ow-text-secondary); }

.result-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
  gap: 0.35rem;
  padding: 0.7rem;
  max-height: 46vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.mini {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-height: 56px;
  padding: 0.3rem;
  border-radius: var(--radius-xs);
  border: 1px solid rgba(255, 255, 255, 0.14);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
[data-theme="sun"] .mini { border-color: #000; border-width: 1.5px; }
.mini.striped::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    transparent 20%, rgba(0,0,0,0.42) 20%, rgba(0,0,0,0.42) 26%,
    transparent 26%, transparent 72%, rgba(0,0,0,0.42) 72%,
    rgba(0,0,0,0.42) 78%, transparent 78%);
}
.mini > * { position: relative; z-index: 1; }
.mini .n { font-family: var(--font-mono); font-size: 1rem; font-weight: 800; line-height: 1; }
.mini .t { font-size: 0.56rem; font-weight: 700; opacity: 0.9; }
.mini:active { transform: scale(0.94); }

/* ============================================================================
 * 8. PAVÉ NUMÉRIQUE (saisie à une main, gants compatibles)
 * ==========================================================================*/
.keypad {
  display: none;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.4rem;
  margin-bottom: var(--gap);
  padding: 0.7rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
}
.keypad.open { display: grid; }

.key {
  min-height: 54px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--ow-text);
  font-family: var(--font-mono);
  font-size: 1.4rem;
  font-weight: 700;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.1s;
}
.key:active { background: var(--ow-primary); color: #fff; transform: scale(0.96); }
.key.util { font-size: 0.82rem; font-family: var(--font-body); font-weight: 700; color: var(--ow-text-secondary); }
.key svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

/* ============================================================================
 * 9. HISTORIQUE & FAVORIS
 * ==========================================================================*/
.quick-row { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: var(--gap); }
.quick-row:empty { display: none; }

.quick-line { display: flex; align-items: center; gap: 0.45rem; min-width: 0; }
.quick-label {
  flex-shrink: 0;
  display: flex; align-items: center; gap: 0.3rem;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ow-text-secondary);
}
.quick-label svg { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.chips {
  display: flex;
  gap: 0.3rem;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  padding: 0.15rem 0;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.chips::-webkit-scrollbar { display: none; }

.chip {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 36px;
  padding: 0.25rem 0.7rem;
  border-radius: 100px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ow-text);
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.chip:active { transform: scale(0.95); }
.chip .dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; border: 1px solid rgba(255,255,255,0.3); }
[data-theme="sun"] .chip .dot { border-color: #000; }
.chip.fav { border-color: var(--border-strong); background: rgba(124, 92, 255, 0.12); }

/* Effacement de l'historique et des favoris — discret, aligné à droite, hors
   de la zone du pouce pour éviter tout appui involontaire en intervention. */
.quick-clear {
  align-self: flex-end;
  min-height: 34px;
  padding: 0.2rem 0.6rem;
  border: 0;
  background: none;
  color: var(--ow-text-secondary);
  font-size: 0.7rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  opacity: 0.7;
  -webkit-tap-highlight-color: transparent;
}
.quick-clear:hover, .quick-clear:focus-visible { opacity: 1; color: var(--ow-text); }

/* ============================================================================
 * 10. MATRICE
 * ==========================================================================*/
.matrix-card { margin-bottom: var(--gap); }

.matrix-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0.7rem 0.95rem;
  border-bottom: 1px solid var(--border);
}
.matrix-head h2 { font-size: 0.95rem; }
.matrix-head h2 .lbl { color: var(--ow-accent); }
[data-theme="sun"] .matrix-head h2 .lbl { color: var(--ow-primary); }

.matrix-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.7rem;
  font-size: 0.68rem;
  color: var(--ow-text-secondary);
}
.matrix-stats strong { font-family: var(--font-mono); color: var(--ow-accent); }
[data-theme="sun"] .matrix-stats strong { color: var(--ow-primary); }

.matrix-scroll {
  overflow: auto;
  max-height: 68vh;
  padding: 0.6rem;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--ow-primary) transparent;
}
.matrix-scroll::-webkit-scrollbar { width: 6px; height: 6px; }
.matrix-scroll::-webkit-scrollbar-thumb { background: rgba(124, 92, 255, 0.5); border-radius: 3px; }

table.matrix {
  border-collapse: separate;
  border-spacing: 2px;
  width: max-content;
}

table.matrix .corner {
  position: sticky;
  left: 0; top: 0;
  z-index: 6;
  min-width: var(--rowhead);
  padding: 0.3rem 0.4rem;
  background: var(--ow-bg-secondary);
  border-radius: 5px;
  font-family: var(--font-mono);
  font-size: 0.55rem;
  color: var(--ow-text-secondary);
  text-align: center;
  white-space: nowrap;
}

table.matrix .toron-band td {
  padding: 0.22rem 0.4rem;
  background: rgba(124, 92, 255, 0.1);
  border-top: 2px solid var(--ow-border-accent);
  border-left: 2px solid var(--ow-border-accent);
  border-radius: 5px 5px 0 0;
  color: var(--ow-accent);
  font-family: var(--font-mono);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  white-space: nowrap;
}
[data-theme="sun"] table.matrix .toron-band td { background: #E7E1FF; color: #2E128F; }

table.matrix th.tube {
  position: sticky;
  top: 0;
  z-index: 4;
  min-width: var(--cell);
  min-height: 42px;
  padding: 0.35rem 0.25rem;
  border-radius: 5px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  font-family: var(--font-body);
  font-size: 0.62rem;
  font-weight: 700;
  text-align: center;
  white-space: nowrap;
  line-height: 1.25;
}
table.matrix th.tube.pilote    { background: var(--c-rouge); color: #fff; }
table.matrix th.tube.direction { background: var(--c-vert);  color: #fff; }
table.matrix th.tube.naturel   { background: #303A4B; color: var(--ow-text); }
[data-theme="sun"] table.matrix th.tube.naturel { background: #D8DEE9; color: #05070D; border-color: #000; }
table.matrix th.tube .role { display: block; font-family: var(--font-mono); font-size: 0.46rem; opacity: 0.8; font-weight: 500; }

table.matrix th.rowhead {
  /* -webkit-sticky d'abord : Safari ancien le comprend, les autres l'ignorent
     et retiennent la déclaration standard qui suit. */
  position: -webkit-sticky;
  position: sticky;
  left: 0;
  z-index: 3;
  min-width: var(--rowhead);
  padding: 0.28rem 0.4rem;
  border-radius: 5px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.56rem;
  font-weight: 700;
  text-align: center;
  white-space: nowrap;
  line-height: 1.25;
  overflow: hidden;
}
table.matrix th.rowhead .p {
  display: inline-block;
  padding: 0 4px;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.3);
  font-family: var(--font-mono);
  font-size: 0.55rem;
}
table.matrix th.rowhead.on-light .p { background: rgba(255, 255, 255, 0.5); }

table.matrix td.cell {
  position: relative;
  overflow: hidden;
  min-width: var(--cell);
  height: 42px;
  padding: 0.25rem;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.1s, filter 0.1s;
}
[data-theme="sun"] table.matrix td.cell { border-color: rgba(0, 0, 0, 0.45); }

/* Strie appliquée en surcouche : la couleur de fond reste exacte */
table.matrix .stripes {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg,
    transparent 20%, rgba(0,0,0,0.4) 20%, rgba(0,0,0,0.4) 26%,
    transparent 26%, transparent 72%, rgba(0,0,0,0.4) 72%,
    rgba(0,0,0,0.4) 78%, transparent 78%);
}
table.matrix .stripes.on-light {
  background: linear-gradient(90deg,
    transparent 20%, rgba(0,0,0,0.55) 20%, rgba(0,0,0,0.55) 26%,
    transparent 26%, transparent 72%, rgba(0,0,0,0.55) 72%,
    rgba(0,0,0,0.55) 78%, transparent 78%);
}
table.matrix td.cell > span.n { position: relative; z-index: 1; }

table.matrix .toron-edge { border-left: 2px solid rgba(124, 92, 255, 0.55) !important; }
[data-theme="sun"] table.matrix .toron-edge { border-left-color: #2E128F !important; }

table.matrix td.cell:hover { transform: scale(1.1); filter: brightness(1.12); z-index: 8; }

table.matrix td.cell.hit {
  outline: 3px solid #fff;
  outline-offset: 1px;
  transform: scale(1.16);
  filter: brightness(1.25);
  z-index: 20;
  box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.2), 0 6px 18px rgba(0, 0, 0, 0.5);
}
[data-theme="sun"] table.matrix td.cell.hit { outline-color: #05070D; box-shadow: 0 0 0 4px rgba(0,0,0,0.15); }

/* Correspondances secondaires d'une recherche multiple */
table.matrix td.cell.dim { opacity: 0.22; }
table.matrix td.cell.match { outline: 2px solid rgba(255, 255, 255, 0.85); outline-offset: -1px; }
[data-theme="sun"] table.matrix td.cell.match { outline-color: #05070D; }

table.matrix tr.split td { height: 6px; padding: 0; background: transparent; border: 0; }
table.matrix tr.split .rule {
  height: 2px;
  border-radius: 2px;
  background: var(--ow-edge-gradient);
  opacity: 0.6;
}

.scroll-hint {
  display: none;
  align-items: center;
  gap: 0.3rem;
  padding: 0.3rem 0.95rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.66rem;
  color: var(--ow-text-secondary);
}
.scroll-hint svg { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }

/* ============================================================================
 * 11. LÉGENDE & FAQ
 * ==========================================================================*/
.panels { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: var(--gap); margin-bottom: var(--gap); }

.panel { padding: 1rem 1.05rem; }

.legend-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 0.3rem; }
.legend-item { display: flex; flex-direction: column; align-items: center; gap: 0.15rem; }

/* Pastille de légende.
   Un seul enfant en flux, donc une seule piste de grille : le numéro reste
   parfaitement centré, à l'identique pour les 24 positions. */
.legend-swatch {
  position: relative;
  width: 100%;
  height: 26px;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  font-family: var(--font-mono);
  font-size: 0.58rem;
  font-weight: 700;
  line-height: 1;
}
[data-theme="sun"] .legend-swatch { border-color: #000; }

/* Double strie noire des positions 13 à 24.
   Dessinée en surcouche absolue : hors flux, la pseudo-classe n'est donc pas
   une piste de grille et ne déplace pas le numéro. Mêmes proportions que la
   strie de la matrice, pour que la légende et le tableau se répondent. */
.legend-swatch.striped::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg,
    transparent 20%, rgba(0, 0, 0, 0.42) 20%, rgba(0, 0, 0, 0.42) 26%,
    transparent 26%, transparent 72%, rgba(0, 0, 0, 0.42) 72%,
    rgba(0, 0, 0, 0.42) 78%, transparent 78%);
}
/* Fonds clairs (Jaune, Blanc) : strie renforcée pour rester franche. */
.legend-swatch.striped.on-light::after {
  background: linear-gradient(90deg,
    transparent 20%, rgba(0, 0, 0, 0.58) 20%, rgba(0, 0, 0, 0.58) 26%,
    transparent 26%, transparent 72%, rgba(0, 0, 0, 0.58) 72%,
    rgba(0, 0, 0, 0.58) 78%, transparent 78%);
}
/* Le numéro passe au-dessus de la strie. */
.legend-swatch > span { position: relative; z-index: 1; }

.legend-name { font-size: 0.52rem; color: var(--ow-text-secondary); text-align: center; line-height: 1.15; }

.tube-legend { display: flex; flex-direction: column; gap: 0.55rem; }
.tube-legend-row { display: flex; align-items: center; gap: 0.65rem; }
.tube-swatch { width: 34px; height: 22px; flex-shrink: 0; border-radius: 4px; border: 1px solid rgba(255, 255, 255, 0.2); }
[data-theme="sun"] .tube-swatch { border-color: #000; }
.tube-legend-row strong { display: block; font-size: 0.8rem; }
.tube-legend-row span { font-size: 0.68rem; color: var(--ow-text-secondary); }

/* -----------------------------------------------------------------------------
   ENCART D'AVERTISSEMENT MÉTIER
   Employé pour les précisions qui engagent une intervention : exception de la
   position 20, rappel que le plan du site fait foi.
   -------------------------------------------------------------------------- */
.warn-box {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin-top: 0.7rem;
  padding: 0.65rem 0.8rem;
  border-radius: var(--radius-xs);
  border: 1px solid rgba(255, 200, 60, 0.35);
  background: rgba(255, 200, 60, 0.09);
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--ow-text-secondary);
}
[data-theme="sun"] .warn-box { background: #FFF4D6; border-color: #8A6D00; color: #4A3800; }
.warn-box strong { color: var(--ow-text); }
[data-theme="sun"] .warn-box strong { color: #2B2000; }
.warn-box svg {
  flex-shrink: 0;
  width: 16px; height: 16px;
  margin-top: 2px;
  stroke: currentColor; fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

/* Référence RAL dans la légende des tubes — discrète mais repérable. */
.tube-legend-row em {
  font-family: var(--font-mono);
  font-style: normal;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--ow-accent);
  margin-left: 0.2rem;
}
[data-theme="sun"] .tube-legend-row em { color: var(--ow-primary); }

/* -----------------------------------------------------------------------------
   TEXTE COURANT DES SECTIONS ÉDITORIALES (vocation, à propos)
   -------------------------------------------------------------------------- */
.prose { display: flex; flex-direction: column; gap: 0.7rem; }
.prose p {
  max-width: 72ch;
  font-size: 0.87rem;
  line-height: 1.7;
  color: var(--ow-text-secondary);
}
.prose strong { color: var(--ow-text); font-weight: 700; }
.prose .fineprint {
  font-size: 0.74rem;
  line-height: 1.6;
  opacity: 0.8;
  padding-top: 0.6rem;
  border-top: 1px solid var(--border);
}

/* -----------------------------------------------------------------------------
   SIGNATURE « À PROPOS » — logo MX Solution

   Le bloc entier est un lien : cible tactile large, sans zone morte entre le
   logo et l'adresse. Sobre volontairement — c'est une signature d'auteur, pas
   un encart publicitaire.
   -------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
   SIGNATURE « À PROPOS » — le logo MX Solution, seul élément cliquable.
   Aucun texte, aucune adresse affichée : le logo porte le lien.
   -------------------------------------------------------------------------- */
.about-brand {
  display: inline-block;
  margin-top: 0.6rem;
  padding: 0.5rem 0.7rem;
  margin-left: -0.7rem;          /* le logo reste aligné sur le texte au-dessus */
  border-radius: var(--radius-sm);
  text-decoration: none;
  transition: background var(--transition), transform var(--transition);
}
.about-brand:hover,
.about-brand:focus-visible {
  background: var(--surface-raised);
  transform: translateY(-2px);
}
.about-brand:active { transform: translateY(0); }

/* Logo très allongé (viewBox 5000 × 660, ratio 7,6:1) : on le dimensionne par
   la LARGEUR, la hauteur suit. Le dimensionner par la hauteur donnerait une
   largeur inattendue sur petit écran. */
.about-brand-logo {
  display: block;
  width: clamp(128px, 44vw, 160px);
  height: auto;
}

/* Le tracé est en #fafafa : pensé pour un fond sombre.
   En mode plein soleil, le fond devient blanc et le logo disparaîtrait.
   Le logo étant monochrome, une inversion suffit et donne un tracé quasi noir,
   sans avoir à maintenir un second fichier. */
[data-theme="sun"] .about-brand-logo { filter: invert(1); }

/* Repli si le fichier SVG est introuvable (bascule pilotée par js/app.js).
   Il ne s'affiche jamais tant que le logo est en place. */
.about-brand-fallback {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.05rem;
  color: var(--ow-text);
}

@media (prefers-reduced-motion: reduce) {
  .about-brand:hover, .about-brand:focus-visible { transform: none; }
}

/* FAQ — pattern Kito Digital : details/summary, barre dégradée, hover lift */
.faq { display: flex; flex-direction: column; gap: 0.5rem; }

.faq details {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  transition: transform var(--transition), box-shadow var(--transition);
}
.faq details::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 2px;
  background: var(--ow-edge-gradient);
  opacity: 0;
  transition: opacity var(--transition);
}
.faq details[open]::after { opacity: 1; }
.faq details:hover { transform: translateY(-4px); box-shadow: 0 8px 24px var(--ow-glow); }
[data-theme="sun"] .faq details:hover { box-shadow: var(--shadow); }

.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.7rem;
  min-height: var(--touch);
  padding: 0.75rem 0.95rem;
  cursor: pointer;
  font-weight: 700;
  font-size: 0.86rem;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "";
  flex-shrink: 0;
  width: 9px; height: 9px;
  border-right: 2px solid var(--ow-accent);
  border-bottom: 2px solid var(--ow-accent);
  transform: rotate(45deg);
  transition: transform var(--transition);
}
.faq details[open] summary::after { transform: rotate(-135deg); }
.faq .answer { padding: 0 0.95rem 0.9rem; font-size: 0.83rem; color: var(--ow-text-secondary); line-height: 1.65; }

/* ============================================================================
 * 12. BANNIÈRE D'INSTALLATION & MISE À JOUR
 * ==========================================================================*/
.banner {
  display: none;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: var(--gap);
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: rgba(124, 92, 255, 0.12);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
}
.banner.show { display: flex; }
.banner .txt { flex: 1; min-width: 0; font-size: 0.8rem; }
.banner .txt strong { display: block; font-size: 0.86rem; }
.banner svg.lead { flex-shrink: 0; width: 22px; height: 22px; stroke: var(--ow-accent); fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* -----------------------------------------------------------------------------
   TOAST — notification éphémère de confirmation d'action.
   Élément unique et permanent (#toast), piloté par toast() dans js/app.js :
   favoris, copie presse-papier, bascule de thème, réinitialisation des règles,
   effacement des données, installation de l'application.

   Masquage : `visibility` + `opacity`, et non un simple décalage.
   Un décalage en pourcentage (translateY 140 %) se calcule sur la hauteur de
   l'élément : au repos le toast est vide, donc très bas, et 140 % d'une petite
   hauteur ne suffisait pas à le sortir du cadre — une pastille restait visible
   au bas de la page. `visibility: hidden` est indépendant du contenu et retire
   par ailleurs l'élément de l'ordre de tabulation.
   `visibility` reste préférable à `display: none` : la région aria-live doit
   demeurer dans l'arbre d'accessibilité pour que ses mises à jour soient
   annoncées de façon fiable.
   -------------------------------------------------------------------------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(1.2rem + env(safe-area-inset-bottom));
  z-index: 200;
  max-width: min(92vw, 420px);
  padding: 0.7rem 1.1rem;
  border-radius: 100px;
  border: 1px solid var(--border-strong);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  font-size: 0.82rem;
  font-weight: 600;
  text-align: center;

  /* État masqué */
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 0.75rem);
  transition: opacity 0.2s ease,
              transform 0.24s cubic-bezier(0.34, 1.4, 0.64, 1),
              visibility 0s linear 0.24s;   /* masquage après l'animation */
}

.toast.show {
  visibility: visible;
  opacity: 1;
  transform: translate(-50%, 0);
  transition: opacity 0.2s ease,
              transform 0.24s cubic-bezier(0.34, 1.4, 0.64, 1),
              visibility 0s;                /* affichage immédiat */
}

/* ============================================================================
 * 13. PIED DE PAGE
 * ==========================================================================*/
.site-footer {
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  text-align: center;
  font-size: 0.72rem;
  color: var(--ow-text-secondary);
  line-height: 1.8;
}
.site-footer a { font-weight: 600; text-decoration: none; }
.site-footer a:hover { text-decoration: underline; }

/* Mention d'hébergement — discrète, sur une ligne, centrée et repliable.
   Séparée du reste par un filet fin pour ne pas concurrencer le contenu métier. */
.footer-host {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  max-width: 100%;
  margin: 0.7rem auto 0;
  padding-top: 0.7rem;
  border-top: 1px solid var(--border);
  font-size: 0.7rem;
  color: var(--ow-text-secondary);
  opacity: 0.85;
  transition: opacity var(--transition);
}
.footer-host:hover { opacity: 1; }
.footer-host svg {
  flex-shrink: 0;
  width: 13px; height: 13px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Cible tactile confortable sans alourdir la ligne. */
.footer-host a {
  display: inline-block;
  padding: 0.2rem 0.15rem;
  color: var(--ow-accent);
  border-bottom: 1px solid transparent;
}
.footer-host a:hover,
.footer-host a:focus-visible {
  text-decoration: none;
  border-bottom-color: currentColor;
}
[data-theme="sun"] .footer-host { opacity: 1; }
[data-theme="sun"] .footer-host a { color: var(--ow-primary); }

.footer-version {
  margin-top: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  opacity: 0.7;
}

/* ============================================================================
 * 14. RESPONSIVE & PRÉFÉRENCES SYSTÈME
 *
 * Trois usages, trois priorités :
 *   · iPhone  — usage principal, une main, gants, plein soleil. Cibles
 *               généreuses, texte large, saisie confortable.
 *   · iPad    — le résultat et la matrice tiennent côte à côte : le technicien
 *               garde la fiche sous les yeux en parcourant le tableau.
 *   · Bureau  — bureaux d'études et conduite de chantier. Deux colonnes, plus
 *               de matrice visible, sans rien retirer au mobile.
 * ==========================================================================*/

/* ---- Téléphone : usage principal ------------------------------------------ */
@media (max-width: 640px) {
  :root {
    --cell:    46px;   /* cible tactile confortable avec des gants */
    --rowhead: 62px;
    --gap:     0.8rem;
  }
  .brand-sub { display: none; }
  .result-head { flex-direction: column; }
  .fiber-chip { width: 100%; flex-direction: row; justify-content: center; gap: 0.8rem; padding: 0.9rem; }
  .fiber-chip .num { font-size: 2.6rem; }
  .fiber-chip .cname { font-size: 1rem; }
  .result-body { border-left: 0; border-top: 1px solid var(--border); }
  .legend-grid { grid-template-columns: repeat(4, 1fr); }
  .matrix-scroll { max-height: 58vh; }
  .result-grid { max-height: 40vh; }

  /* Les faits clés restent lisibles à bout de bras. */
  .fact dd { font-size: 1rem; }
  .fact dt { font-size: 0.6rem; }

  /* Une action par ligne : aucun appui voisin possible avec des gants. */
  .result-actions .btn { flex: 1 1 100%; min-height: 46px; }
}

@media (max-width: 380px) {
  :root { --cell: 42px; --rowhead: 54px; }
  .legend-grid { grid-template-columns: repeat(3, 1fr); }
  .cable-tab { min-width: 60px; padding: 0.3rem 0.55rem; font-size: 0.76rem; }
}

/* ---- Tablette et petits portables ----------------------------------------- */
@media (max-width: 900px) {
  .scroll-hint { display: flex; }
}

@media (min-width: 768px) and (max-width: 1099px) {
  :root { --cell: 48px; }
  /* La matrice occupe la hauteur disponible : moins de défilement au doigt. */
  .matrix-scroll { max-height: 62vh; }
  .result-grid { grid-template-columns: repeat(auto-fill, minmax(86px, 1fr)); }
}

/* ---- Poste sans aucune surface tactile ------------------------------------
   Le pavé numérique n'a pas d'usage devant un clavier physique : on retire la
   commande plutôt que de laisser un bouton sans objet.
   Le test porte sur `any-pointer: coarse` et non sur `pointer: fine` : un
   portable à écran tactile déclare un pointeur principal précis tout en
   disposant du tactile — il doit conserver le pavé.
   -------------------------------------------------------------------------- */
@media not all and (any-pointer: coarse) {
  #btn-keypad { display: none; }
  .keypad { display: none !important; }
}

/* ---- Grand écran : fiche et matrice côte à côte ----------------------------
   Seuil à 1200 px : en dessous, la colonne latérale serait trop étroite pour
   la fiche et le tableau perdrait sur les deux tableaux. Mieux vaut alors
   rester sur une colonne pleine largeur.
   -------------------------------------------------------------------------- */
@media (min-width: 1200px) {
  :root { --cell: 50px; --rowhead: 92px; }

  .app { padding-bottom: 4rem; }

  .workspace {
    display: grid;
    grid-template-columns: clamp(360px, 30vw, 440px) minmax(0, 1fr);
    align-items: start;
    gap: 1.25rem;
  }

  /* La fiche reste visible pendant le parcours du tableau. */
  .workspace-main {
    position: sticky;
    top: calc(var(--touch-lg) + 1.4rem);
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-height: calc(100vh - var(--touch-lg) - 3rem);
    overflow-y: auto;
    /* Marge intérieure pour ne pas rogner les ombres portées. */
    padding: 2px;
    scrollbar-width: thin;
  }
  .workspace-main .result-zone,
  .workspace-main .quick-row { margin-bottom: 0; }
  .workspace > .matrix-card { margin-bottom: 0; }

  /* Dans une colonne de 360 à 440 px, la fiche se lit mieux empilée : la
     pastille couleur en bandeau, puis les informations pleine largeur. C'est
     la même disposition qu'en mobile, pour la même raison — la largeur. */
  .workspace-main .result-head { flex-direction: column; }
  .workspace-main .fiber-chip {
    width: 100%;
    flex-direction: row;
    justify-content: center;
    gap: 0.9rem;
    padding: 0.85rem;
  }
  .workspace-main .fiber-chip .num { font-size: 2.4rem; }
  .workspace-main .fiber-chip .cname { font-size: 1rem; }
  .workspace-main .result-body {
    border-left: 0;
    border-top: 1px solid var(--border);
  }
  /* Deux colonnes de faits tiennent confortablement à cette largeur. */
  .workspace-main .facts { grid-template-columns: repeat(2, 1fr); }
  .workspace-main .result-actions .btn { flex: 1 1 auto; }

  /* La matrice occupe toute la hauteur utile : moins de défilement. */
  .matrix-scroll { max-height: calc(100vh - 12rem); }

  /* Les douze couleurs sur une seule ligne, leurs variantes baguées en dessous. */
  .legend-grid { grid-template-columns: repeat(12, 1fr); }

  /* Barre de recherche : plus large, mais pas démesurée. */
  .search-shell { max-width: 780px; }
  .suggestions { max-width: 780px; }
}

/* Au-delà, on cesse d'élargir : une ligne de texte trop longue devient pénible
   à lire, et la matrice n'y gagne rien. */
@media (min-width: 1600px) {
  .app { max-width: 1520px; }
  .workspace { grid-template-columns: 460px minmax(0, 1fr); }
}

/* Écran tactile sans survol : pas d'effet hover parasite */
@media (hover: none) {
  table.matrix td.cell:hover { transform: none; filter: none; }
  .faq details:hover { transform: none; box-shadow: none; }
}

/* Paysage sur mobile : on rend de la hauteur à la matrice */
@media (max-height: 500px) and (orientation: landscape) {
  .matrix-scroll { max-height: 62vh; }
  .searchbar { position: static; }
}

/* Respect de la préférence système : aucune animation */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Contraste renforcé demandé par le système */
@media (prefers-contrast: more) {
  :root { --border: rgba(255, 255, 255, 0.4); --border-strong: var(--ow-accent); }
}

/* ============================================================================
 * IMPRESSION — fiche de repérage papier
 * ==========================================================================*/
@media print {
  body { background: #fff; color: #000; padding: 0; }
  body::before { display: none; }
  .searchbar, .cable-bar, .keypad, .quick-row, .banner, .toast,
  .appbar-actions, .suggestions, .site-footer, .faq { display: none !important; }
  .card, .result-card, .matrix-card {
    background: #fff !important;
    border: 1px solid #000 !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
  }
  .matrix-scroll { max-height: none; overflow: visible; }
  table.matrix td.cell, table.matrix th { color: #000 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .fiber-chip .num, .fact dd { color: #000 !important; -webkit-text-fill-color: #000 !important; }
}
