/* ============================================================================
   SENTINELLE — Cockpit HUD. 2026-07 redesign: premium deep dark by default,
   giant hero LIMIT panel (regulatory circle, or B30 in a 30 zone),
   discreet satellite speed, “road ahead” rail.
   Every class/ID referenced by app.js is kept (hook contract).
   ========================================================================== */

html{-webkit-text-size-adjust:100%;text-size-adjust:100%}  /* no auto-enlargement on reflow; the scale follows the system preference (Dynamic Type) via the root below */

/* Accessibility: follows the system text size (iOS Dynamic Type « Texte plus grand » / Android).
   -apple-system-body reflects the user's preference; the root therefore becomes the anchor for rem,
   and everything sized in rem (HUD, labels, settings) grows with the phone setting.
   Guarded by @supports so nothing changes where the keyword does not exist. */
@supports (font: -apple-system-body){ :root{ font: -apple-system-body; } }

/* ---- Jetons ---- */
:root{
  /* The rodap identity, once only. These three values are the stops of the
     brand gradient (public/css/app-theme.css): the house, not the module. */
  --tint:#2563eb; --tint-vif:#1d9bf0; --tint-2:#06b6d4;
  /* THREE SHADOWS, TWO BLURS, FOUR RADII. About twenty unique shadows and eight
     different blurs coexisted: the eye cannot name them, but it senses that
     nothing has been decided. Three depth levels are enough — placed, floating, modal. */
  --sh-1:0 2px 8px rgba(2,6,16,.22);
  --sh-2:0 10px 28px rgba(2,6,16,.30);
  --sh-3:0 18px 46px rgba(2,6,16,.38);
  --blur-voile:none;
  --r-s:8px; --r-m:12px; --r-l:16px; --r-xl:20px;
  /* THE TOP STACK. Each element was placed at a hand-written distance, without
     knowing what was already there: moving one hit the next. The steps are
     declared here, once, and each sits on the previous one. */
  --haut-0: calc(env(safe-area-inset-top, 0px) + .6rem);   /* nom d'axe */
  --haut-1: calc(env(safe-area-inset-top, 0px) + 3.4rem);  /* barre d'itineraire */
  --haut-2: calc(env(safe-area-inset-top, 0px) + 5.1rem);  /* bandeau d'etat */
  --haut-3: calc(env(safe-area-inset-top, 0px) + 7.6rem);  /* bandeau de lecon */
  --haut-4: calc(env(safe-area-inset-top, 0px) + 10.1rem); /* what is coming up ahead */
  --s-accent:var(--tint-vif); --s-danger:#ff453a; --s-ok:#30d47c; --s-warn:#ffb020;
  --blur:none;
  /* DARK THEME (default) — navy/black cockpit */
  --bg1:#07111f; --bg2:#040a13;
  --txt:#f4f7fc; --txt-dim:#aab9cf;
  --glass:#111e2f; --glass-2:#0d1827;
  --dial:#0b1726; --dial-edge:rgba(142,178,226,.24);
  --brd:rgba(150,182,235,.32); --brd-soft:rgba(150,182,235,.18);
  --hi:rgba(160,195,255,.08);
  --shadow:var(--sh-1);
  --sign-red:#ff0000;
  --track:rgba(148,178,225,.24); --road-glow:rgba(62,162,255,.14);
  --num-grad:#ffffff;
  --amb:rgba(62,162,255,.05);   /* lueur d'ambiance azur attenuee (aplati, plus mat) */
}
[data-theme="light"]{
  --bg1:#edf3fa; --bg2:#dfe8f3;
  --txt:#0a1b31; --txt-dim:#40536d;
  --glass:#f7faff; --glass-2:#ffffff;
  --dial:#f8fbff; --dial-edge:rgba(14,35,72,.22);
  --brd:rgba(14,35,72,.26); --brd-soft:rgba(14,35,72,.14);
  --hi:rgba(255,255,255,.6);
  --shadow:0 2px 8px rgba(24,48,92,.14);
  --track:rgba(14,35,72,.16); --road-glow:rgba(52,110,205,.12);
  --num-grad:#0e1c33;
  --amb:rgba(255,255,255,.5);
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;color:var(--txt);font-family:'Roboto',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;overflow:hidden;overscroll-behavior:none;
  background:linear-gradient(180deg,var(--bg1) 0%,var(--bg2) 100%);transition:background .4s,color .3s}
/* Atmosphere: a very slight azure glow descending from the top, BELOW everything (background z) — gives
   depth to the cockpit without ever interfering with the zone edge glow (#sent-zonebg). */
body{background:linear-gradient(180deg,var(--bg1) 0%,var(--bg2) 100%)}
html{background:var(--bg2)}
html, body { min-height: 100dvh; touch-action: manipulation; }

/* Tabular figures: readable while driving, no “jumping” */
#dash-speed,#limit-big,#pk-spd,.sent-speed span,#nav-eta,#nav-man-dist,#limit-val,.rail-d{font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}

/* ---- Carte ---- */
#map{position:fixed;inset:0;z-index:0;background:var(--bg1);height:100dvh}
.maplibregl-ctrl-attrib{display:none}
.sent-pos-dot,.sent-loc-dot{width:20px;height:20px;border-radius:50%;background:var(--s-accent);border:3px solid #fff;box-shadow:0 0 0 4px rgba(62,162,255,.35),0 2px 8px rgba(0,0,0,.5)}
.sent-center-dot{pointer-events:none;z-index:5;display:flex;flex-direction:column;align-items:center}
#sent-mapctrl button[hidden]{display:none}
/* Puck: arrow (logo-style) + actual speed inside */
.sent-center-dot .pk-svg{width:52px;height:auto;display:block;filter:drop-shadow(0 2px 5px rgba(0,0,0,.35))}
.sent-center-dot .pk-shape{fill:#16a34a}
.sent-center-dot.warn .pk-shape{fill:#f59e0b}
.sent-center-dot.over .pk-shape{fill:#dc2626}
body.mode-map .sent-speed{display:none}
/* Map: discreet cinematic vignetting */
body.mode-map .maplibregl-map::after{content:'';position:absolute;inset:0;pointer-events:none;z-index:5;background:radial-gradient(ellipse at 50% 58%,transparent 60%,rgba(2,6,16,.22) 100%)}

/* ---- STAGING/dev ribbon (top-left corner, does not push the content) ---- */
.app-dev-banner, .sent-dev-banner, .dev-banner {
  position:fixed; z-index:9999;
  top: 15px !important; left: -46px !important; right: auto !important; bottom: auto !important;
  width: auto !important; height: auto !important;
  transform: rotate(-45deg) !important; transform-origin: center !important;
  background: #b45309 !important; color: #fff !important;
  padding:4px 48px !important; font-size: 10px !important; font-weight: 800 !important; letter-spacing: .16em !important;
  box-shadow: 0 2px 8px rgba(0,0,0,.35) !important; display: block !important; border-radius: 0 !important;
  text-transform:uppercase;
}
.app-dev-banner::before, .sent-dev-banner::before, .dev-banner::before { content: '' !important; }
body.has-dev-banner { padding-top:0 !important; }
body.has-dev-banner .app-nav, body.has-dev-banner nav, body.has-dev-banner .rd-progress { top: 0 !important; }
body:has(#sent-settings:not([hidden])) .sent-dev-banner, body:has(#sent-player:not([hidden])) .sent-dev-banner, body:has(#sent-sheet:not([hidden])) .sent-dev-banner, body:has(#sent-credits:not([hidden])) .sent-dev-banner, body:has(#sent-limedit:not([hidden])) .sent-dev-banner, body:has(#sent-ios:not([hidden])) .sent-dev-banner { display:none !important; }

/* ---- Settings: small, discreet floating button (the header is gone, all the space goes to the HUD) ---- */
#sent-top{position:fixed;top:calc(env(safe-area-inset-top) + .6rem);right:.7rem;left:auto;z-index:500;display:flex;pointer-events:none}
@keyframes rtpulse{0%{box-shadow:0 0 0 0 rgba(48,212,124,.5)}70%{box-shadow:0 0 0 6px rgba(48,212,124,0)}100%{box-shadow:0 0 0 0 rgba(48,212,124,0)}}
#sent-set{pointer-events:auto;width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--txt);opacity:.85;
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);border:1px solid var(--brd)}
#sent-set:active{opacity:1}
#sent-set svg{width:18px;height:18px}
#sent-info{pointer-events:auto;width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--txt-dim);font-weight:700;font-style:italic;font-size:.74rem;font-family:Georgia,serif;opacity:.85;
  background:transparent;border:1px solid var(--brd-soft)}
#sent-info:active{opacity:.9}

/* ---- Bouton debug (dev only) ---- */
#sent-debug{ position:static; display:none; align-items:center; gap:0.25rem;
  padding:0.5rem 0.75rem; border-radius:12px; font-size:.7rem; font-weight:800; letter-spacing:.04em; cursor:pointer; color:#fff;
  background:rgba(24,34,58,.9); border:1px solid var(--brd); backdrop-filter:var(--blur); -webkit-backdrop-filter:var(--blur); }
body.sent-dev #sent-debug{ display:inline-flex; }
#sent-debug.rec{ background:#d70015; animation:rtpulse 1.4s infinite; }

/* ============================================================================
   MODE COPILOT — cockpit
   ========================================================================== */
#map{transition:opacity .5s ease, transform .62s cubic-bezier(.22,.61,.36,1);will-change:opacity,transform}
body.mode-hud #map{opacity:0;visibility:hidden;pointer-events:none;transform:scale(1.06);transition:opacity .42s ease, transform .6s cubic-bezier(.22,.61,.36,1), visibility 0s .46s}
body.mode-map #map{opacity:1;visibility:visible;transform:none}

/* Top offset = safe area (notch/status bar/URL) + margin: ensures that the top of the ring AND the
   speed bubble (highest needle position, ~5% from the top of the ring) remain visible,
   even when env(safe-area-inset-top) is 0 (Safari outside standalone mode). max() = absolute floor. */
#sent-dash{position:fixed;inset:0;z-index:480;display:none;flex-direction:column;align-items:center;justify-content:flex-start;padding:max(2.8rem, calc(env(safe-area-inset-top) + 1.5rem)) 1rem 0;gap:0.75rem;pointer-events:none}
#sent-dash > *{pointer-events:auto}
body.mode-hud #sent-dash{display:flex}
/* ambient azure glow behind the instrument */
body.mode-hud #sent-dash::before{content:"";position:absolute;inset:0;pointer-events:none;background:none}

/* “current road” label (road name / number) at the top of the Copilot HUD --- */
#sent-road{max-width:min(86vw,420px);padding:0.45rem 1rem;border-radius:var(--r-m);
  background:var(--glass);border:1px solid var(--brd);color:var(--txt);
  font-size:1rem;font-weight:700;letter-spacing:.01em;line-height:1.2;text-align:center;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);box-shadow:var(--shadow)}
#sent-road[hidden]{display:none}
body.mode-map #sent-road{display:none!important}
/* Route change: the new name fades in while descending (never a hard replacement) */
@keyframes roadSwap{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
#sent-road.swap{animation:roadSwap .45s cubic-bezier(.22,.9,.32,1)}

/* Central instrument: giant LIMIT panel at the heart of the ring + satellite speed --- */
/* margin-top, two roles. (1) Anti-overlap floor: the speed bubble extends ~9% of the
   dial ABOVE the .dash-hero box when the needle reaches the top of the arc (mid-gauge,
   e.g. 24 km/h in a 50 zone) -> never less than ~2rem, otherwise the bubble bites into the road name pill
   (#sent-road). (2) At rest (no hazard ahead, no alert), the module is lowered (~15vh)
   to sit centered with breathing room on the page; as soon as a hazard rail or alert card needs
   room, it rises smoothly to the floor (rules: :has below). */
/* AND IT CAN NO LONGER TAKE UP MORE THAN HALF THE PAGE. On a short screen, an
   instrument that fills the whole screen leaves no room for what it must announce:
   the alert tile ended up on the buttons. */
.dash-hero{position:relative;width:min(82vw,430px,46vh);height:min(82vw,430px,46vh);flex:none;margin-top:clamp(2rem,15vh,8rem);container-type:size;isolation:isolate;
  transition:opacity .3s ease, transform .4s cubic-bezier(.22,.61,.36,1), margin-top .45s ease}
body.mode-hud:has(#sent-predict .rail) .dash-hero,
body.mode-hud:has(#sent-card:not([hidden])) .dash-hero,
body.mode-hud:has(#lim-vote:not([hidden])) .dash-hero{margin-top:2rem}   /* vote card shown: the module moves up too (otherwise it grazes the bottom of the dial, seen in QA) */
/* BUT NEVER ABOVE WHAT IS ALREADY THERE. Two rem place the dial exactly on
   the status banner on a phone: the banner is written over the ring, and the speed
   pill touches it. The upward shift now knows about the top stack. */
body.mode-switching .dash-hero{opacity:0;transform:scale(.84)}
.dash-hero::before{content:"";position:absolute;inset:3.5%;z-index:0;border-radius:50%;pointer-events:none;
  background:var(--dial);border:1px solid var(--dial-edge);box-shadow:inset 0 1px 0 var(--hi),var(--sh-2)}
.speedring{position:relative;z-index:1;width:100%;height:100%;display:block}
.speedring circle{fill:none;stroke-linecap:round}
/* ONE CIRCLE, TWO CLEARLY ASYMMETRICAL GAUGES (same radius r=90, circumference 565.5):
   SPEED DOMINATES — a 264° arc (414.7, ~80% of the usable circle) across the top and both
   sides, thick stroke; CONFIDENCE (azure gradient) is a discreet arc centered at the bottom —
   66° (103.7, ~20%), thin stroke. The 80/20 split was approved by the owner; a symmetrical
   physical gap of 15° at each junction: two separate gauges that, together,
   form a circle. Confidence fills BACKWARDS (dashoffset = stroke length):
   it starts from the left, like speed. The speed number (.hero-core) follows the
   end of the speed arc, like a needle. */
.sr-track{stroke:var(--track);stroke-dasharray:414.7 565.5;stroke-width:12}
.sr-val{stroke:var(--s-ok);stroke-dasharray:0 565.5;stroke-width:12;transition:stroke-dasharray .5s cubic-bezier(.4,0,.2,1),stroke .22s ease;filter:drop-shadow(0 0 4px rgba(48,212,124,.3))}
.sr-conf-track{stroke:var(--track);stroke-width:5;stroke-dasharray:103.7 461.8;stroke-dashoffset:103.7}
.sr-conf{stroke:url(#sr-conf-grad);stroke-width:5;stroke-dasharray:0 565.5;stroke-dashoffset:0;visibility:hidden;transition:stroke-dasharray .5s cubic-bezier(.4,0,.2,1),stroke-dashoffset .5s cubic-bezier(.4,0,.2,1),stroke .3s;filter:drop-shadow(0 0 3px rgba(29,155,240,.28))}
/* Azure confidence gradient: stops controlled in CSS for light/dark */
.scg-a{stop-color:var(--tint-vif)}
.scg-b{stop-color:var(--tint-2)}
[data-theme="light"] .scg-a{stop-color:var(--tint)}
[data-theme="light"] .scg-b{stop-color:#0891b2}
#dash-hero.warn .sr-val{stroke:var(--s-warn);filter:drop-shadow(0 0 4px rgba(255,176,32,.34))}
#dash-hero.over .sr-val{stroke:var(--s-danger);stroke-width:14;filter:drop-shadow(0 0 5px rgba(255,69,58,.38))}

/* Vehicle speed: needle pill that FOLLOWS the end of the speed arc
   (left/top set as % by updateHero; start = beginning of arc, at the bottom left).
   Same iOS radial-gradient-without-border workaround as the panel: never a residual square. */
.hero-core{position:absolute;left:16.6%;top:80.1%;transform:translate(-50%,-50%);width:34%;aspect-ratio:1;container-type:size;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;z-index:3;
  transition:left .5s cubic-bezier(.4,0,.2,1),top .5s cubic-bezier(.4,0,.2,1);
  background:radial-gradient(circle closest-side, var(--glass-2) 0 70%, rgba(150,182,235,.55) 70% 78%, transparent 78.6%)}
.hero-core{-webkit-backdrop-filter:none!important;backdrop-filter:none!important}
.hero-core b{font-size:46cqmin;font-weight:800;line-height:.92;letter-spacing:-.02em;
  background:var(--num-grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
  transition:filter .25s}
#dash-hero.spd3 .hero-core b{font-size:34cqmin}
.hero-unit{margin-top:1cqmin;font-size:11cqmin;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-dim)}
#dash-hero.warn .hero-core b{background:none;-webkit-text-fill-color:var(--s-warn)}
#dash-hero.over .hero-core b{background:none;-webkit-text-fill-color:var(--s-danger);filter:drop-shadow(0 0 14px rgba(255,69,58,.45))}
@keyframes heroIntro{0%{opacity:0;transform:scale(.86)}60%{opacity:1}100%{opacity:1;transform:scale(1)}}
@keyframes dash-in{from{opacity:0;transform:translateY(14px) scale(.96)}to{opacity:1;transform:none}}
/* ── HUD entrance on launch (class applied for ~1.2 s by app.js): elegant stagger
   gauge -> road name -> radio -> rail. transform/opacity only (GPU), once. ── */
body.hud-intro .dash-hero{animation:heroIntro .6s cubic-bezier(.22,.9,.32,1) backwards}
body.hud-intro #sent-road{animation:dash-in .5s cubic-bezier(.22,.9,.32,1) .1s backwards}
body.hud-intro #sent-radio-mini{animation:dash-in .5s cubic-bezier(.22,.9,.32,1) .2s backwards}
body.hud-intro #sent-predict{animation:dash-in .55s cubic-bezier(.22,.9,.32,1) .3s backwards}

/* --- Speed-limit panel: giant HERO at the ring centre --- */
/* DEFINITIVE iOS workaround retained: the whole shape (disc + ring + transparent corners)
   is ONE radial-gradient on a square without border/box-shadow/mask -> never a residual square.
   Centred with left/top (not with transform: the limFlip animation overwrites transform). */
.limit-sign{position:absolute;left:14%;top:14%;width:72%;aspect-ratio:1;cursor:pointer;container-type:size;overflow:hidden;z-index:2;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  background:radial-gradient(circle closest-side, var(--glass-2) 0 70%, rgba(150,182,235,.55) 70% 78%, transparent 78.6%);
  transition:background .25s;-webkit-tap-highlight-color:transparent}
.limit-sign{-webkit-backdrop-filter:none!important;backdrop-filter:none!important}
.limit-sign #limit-big{font-size:30cqmin;font-weight:900;line-height:1;color:var(--txt-dim)}
.limit-sign #limit-cap{font-size:9cqmin;font-weight:800;letter-spacing:.14em;color:var(--txt-dim);margin-top:1cqmin;opacity:.75}
.limit-sign.has-limit{background:radial-gradient(circle closest-side,#f3f5f8 0 67%,var(--sign-red) 67% 83%,#111 83% 84%,transparent 84.4%)!important;border:0!important;box-shadow:none!important;-webkit-mask-image:none!important;mask-image:none!important;-webkit-clip-path:none!important;clip-path:none!important}
.limit-sign.has-limit #limit-big{font-size:47cqmin!important;transform:none;color:#0a0a0a}
.limit-sign.has-limit.lim3 #limit-big{font-size:34cqmin!important;transform:none;letter-spacing:-.03em;transform-origin:center}
.limit-sign.has-limit #limit-cap{display:none}
.limit-sign.has-limit.pending{background:radial-gradient(circle closest-side,#ffd23d 0 61%,#e0a51a 61% 79%,transparent 79.5%)!important;border:0!important}
.limit-sign.has-limit.pending #limit-big{color:#3a2c00}
/* 30 ZONE: genuine French B30 sign — white vertical rectangle, thin red outline,
   “ZONE” in black capitals, red circular sign underneath. 100 % CSS drawing. --- */
.limit-sign.has-limit.zone30:not(.pending){left:29%;top:22.5%;width:42%;height:55%;aspect-ratio:auto;gap:3.5cqmin;
  background:#fff!important;border-radius:7cqmin;
  box-shadow:inset 0 0 0 1.6cqmin #fff, inset 0 0 0 4.2cqmin var(--sign-red), 0 10px 28px rgba(2,6,16,.35)!important}
.limit-sign.has-limit.zone30:not(.pending) #limit-cap{display:block;order:-1;margin:0;opacity:1;
  font-size:21cqmin;font-weight:800;letter-spacing:.05em;color:#0a0a0a}
.limit-sign.has-limit.zone30:not(.pending) #limit-big{width:70cqmin;aspect-ratio:1;flex:none;
  display:flex;align-items:center;justify-content:center;font-size:30cqmin!important;color:#0a0a0a;
  background:radial-gradient(circle closest-side,#fff 0 70%,var(--sign-red) 70.5% 99%,#fff 99.5%)}
body.mode-map .limit-sign.has-limit.zone30:not(.pending){left:13%;top:0;width:74%;height:100%}
.limit-sign:focus{outline:none}
.limit-sign:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(37,99,235,.45)}
@keyframes limFlip{0%{transform:scale(1);opacity:1}42%{transform:scale(.72);opacity:.28}100%{transform:scale(1);opacity:1}}
.limit-sign.flip{animation:limFlip .5s ease-in-out}
/* Panel micro-pulse when the LIMIT CHANGES (supports the odometer scroll, discreet) */
@keyframes limTick{0%{transform:scale(1)}38%{transform:scale(1.045)}100%{transform:scale(1)}}
.limit-sign.tick{animation:limTick .6s cubic-bezier(.3,.7,.3,1)}
/* ── “Odometer” scrolling of the limit number ─────────────────────────────────
   On entering a control zone, the limit MOVES DOWN: each digit slides
   downward through the intermediate values (8 -> 7 -> 6 -> 5), in
   SYNC with the rise of the edge glow (#sent-zonebg: same duration,
   same curve). On exit, the digits move back up and the glow fades.
   Built by rollLimit() in app.js; never a hard replacement. */
#limit-big{display:flex;align-items:center;justify-content:center}
#limit-big .lb-col{display:block;height:1em;overflow:hidden}
#limit-big .lb-strip{display:flex;flex-direction:column;will-change:transform;
  transition:transform .95s cubic-bezier(.3,.86,.22,1)}
#limit-big .lb-strip i{font-style:normal;display:block;height:1em;line-height:1;text-align:center}
/* An estimated limit is stated in words: no visual code to learn. */
.limit-estimated{display:none}
.limit-sign.has-limit.lim-estimated .limit-estimated{display:block;color:#0a0a0a;font-size:7cqmin;font-weight:700;line-height:1;letter-spacing:.02em;margin-top:2cqmin}
.limit-sign.has-limit.zone30.lim-estimated .limit-estimated{font-size:6cqmin;margin-top:-1cqmin}
/* Lowered limit indicator (rain / recent licence) — placed INSIDE the free space between the bottom of the
   panel and the confidence arc (the bottom arc now occupies the lower center of the circle: at
   -1.6rem the badge bit into the arc and radio bar). z-index above the dial. */
/* bottom 9.2%: in the free strip between the bottom of the panel (86%) and the confidence arc (95%), without biting into its glow */
#limit-adj{position:absolute;left:50%;transform:translateX(-50%);bottom:9.2%;z-index:3;padding:.16rem .5rem;border-radius:999px;background:var(--s-accent);color:#04101f;font-weight:800;font-size:.62rem;letter-spacing:.02em;white-space:nowrap;box-shadow:0 4px 12px rgba(62,162,255,.4)}
/* Community correction: edit button */
#lim-edit{margin:0.5rem auto 0;display:flex;align-items:center;gap:0.25rem;border:1px solid var(--brd);background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);color:var(--txt);border-radius:999px;padding:0.25rem 0.75rem;font-size:.78rem;font-weight:600;cursor:pointer;opacity:.9}
#lim-edit svg{width:15px;height:15px}
body.mode-map #lim-edit{display:none}

/* ============================================================================
   ROAD AHEAD — Sentinelle hazard queue (copilot mode)
   Vertical perspective feed: “You” at the bottom, hazards tiered toward the horizon.
   Lifecycle: fades in (far away, small) -> grows continuously as it approaches
   (--prox) + near/mid/far tiers -> ARRIVAL (.here: foreground, pop) ->
   passed (.leaving: fade out). Imminence glow: type color
   (calm) -> orange (.u-warn) -> red (.u-hot), the type identity remains on
   the icon and left border.
   ========================================================================== */
#sent-predict{width:100%;max-width:430px;flex:1;min-height:0;display:none;flex-direction:column;justify-content:flex-end;padding-top:0.25rem;padding-bottom:calc(env(safe-area-inset-bottom) + 5.2rem);pointer-events:none}
body.mode-hud #sent-predict{display:flex}
.rail{position:relative;display:flex;flex-direction:column;justify-content:flex-end;gap:0.5rem;padding-left:2.25rem;padding-right:.5rem;padding-top:0.5rem}
/* Single timeline axis: X = 1rem from the rail's left edge. The line AND all
   points (normal/near/far/here + « Vous » arrow) are centered on it: the points place
   their CENTER on the axis via left + translate(-50%,-50%), whatever their size. */
.rail::before{content:'';position:absolute;left:calc(1rem - 1.5px);top:0;bottom:2rem;width:3px;border-radius:2px;
  background:linear-gradient(180deg, transparent 0%, rgba(142,175,230,.22) 22%, rgba(62,162,255,.6) 100%)}
.rail-row{position:relative;display:flex;align-items:center;transition:opacity .5s ease}
.rail-row.enter{animation:rr-in .55s cubic-bezier(.2,.8,.3,1) both}
@keyframes rr-in{from{opacity:0;transform:translateY(-12px) scale(.92)}to{opacity:1;transform:none}}
.rail-row.leaving{opacity:0;pointer-events:none}
.rail-row.leaving .rail-chip{transform:translateY(16px) scale(.9);filter:blur(2px);transition:transform .6s ease,filter .6s ease}
.rail-node{position:absolute;left:-1.15rem;top:50%;width:11px;height:11px;border-radius:50%;transform:translate(-50%,-50%);
  background:var(--pc,#ef4444);box-shadow:0 0 0 3px rgba(6,10,20,.8),0 0 14px 1px var(--pc,#ef4444);transition:width .45s,height .45s,left .45s}
[data-theme="light"] .rail-node{box-shadow:0 0 0 3px rgba(255,255,255,.9),0 0 12px 0 var(--pc,#ef4444)}
.rail-ping{position:absolute;inset:-4px;border-radius:50%;border:2px solid var(--pc,#ef4444);opacity:0}
.rail-row.near .rail-ping{animation:rail-ping 2s ease-out infinite}
.rail-row.here .rail-ping{animation-duration:1.1s}
@keyframes rail-ping{0%{transform:scale(.55);opacity:.85}70%,100%{transform:scale(2.2);opacity:0}}
.rail-chip{position:relative;overflow:hidden;flex:1;min-width:0;display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0.75rem;border-radius:var(--r-m);color:var(--txt);
  --halo:var(--pc,#ef4444);
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);border:1px solid var(--brd-soft);border-left:3px solid var(--pc,#ef4444);
  transform:scale(calc(.93 + .07*var(--prox,0)));transform-origin:left center;
  transition:transform .6s cubic-bezier(.3,.7,.3,1),padding .45s ease,border-radius .45s ease,box-shadow .6s ease,background-color .45s ease}
/* type tint, as a discreet side veil that rises with proximity */
.rail-chip::after{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(130% 160% at 0% 50%, color-mix(in srgb, var(--pc,#ef4444) 15%, transparent), transparent 55%);
  opacity:calc(.3 + .7*var(--prox,0));transition:opacity .5s ease}
.rail-ic{flex:none;display:flex;align-items:center;justify-content:center;width:24px;height:24px;transition:width .45s,height .45s}
.rail-ic svg{width:100%;height:100%;display:block;filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}
.rail-tx{flex:1;min-width:0;display:flex;flex-direction:column;gap:.06rem}
.rail-lab{min-width:0;font-size:.86rem;font-weight:700;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;opacity:.92;transition:font-size .45s}
.rail-eta{font-size:.7rem;font-weight:700;color:var(--txt-dim);letter-spacing:.02em;font-variant-numeric:tabular-nums;transition:font-size .45s}
.rail-eta[hidden]{display:none}
.rail-d{flex:none;font-size:1.02rem;font-weight:800;color:var(--txt);text-align:right;white-space:nowrap;line-height:1.05;transition:font-size .45s,color .5s}
.rail-d small{font-size:.6em;font-weight:700;opacity:.75;margin-right:.18em}
/* approach gauge (starts at ~1.5 km, fills up to the hazard) — visible on the dominant item */
.rail-gauge{position:absolute;left:0;right:0;bottom:0;height:4px;pointer-events:none;opacity:0;transition:opacity .4s;background:color-mix(in srgb, var(--pc, #888) 25%, transparent);border-radius:0 0 2px 2px}
.rail-gauge::before{content:'';position:absolute;left:0;top:0;bottom:0;width:var(--gw,0%);border-radius:0 2px 2px 0;
  background:linear-gradient(90deg, transparent, var(--halo));transition:width .95s linear}
.rail-row.near .rail-gauge{opacity:.9}
/* ── Levels: the nearest is dominant, the following ones progressively weaker ── */
.rail-row.near .rail-chip{padding:0.75rem 0.75rem;border-radius:var(--r-l);background:var(--glass-2);border-color:var(--brd);
  box-shadow:var(--sh-1)}
.rail-row.near .rail-ic{width:38px;height:38px}
.rail-row.near .rail-d{font-size:1.72rem;letter-spacing:-.01em}
.rail-row.near .rail-lab{font-size:1rem;font-weight:800;opacity:1}
.rail-row.near .rail-eta{font-size:.8rem;color:var(--txt);opacity:.85}
.rail-row.near .rail-node{width:16px;height:16px}
.rail-row.far .rail-chip{padding:0.25rem 0.5rem;opacity:.8}
.rail-row.far .rail-ic{width:19px;height:19px}
.rail-row.far .rail-lab{font-size:.76rem}
.rail-row.far .rail-d{font-size:.88rem}
.rail-row.far .rail-eta{display:none}
.rail-row.far .rail-node{width:8px;height:8px}
/* ── Imminence: calm glow -> orange -> red (the type remains on the icon/border) ── */
.rail-row.u-warn .rail-chip{--halo:#ff9f2e}
.rail-row.u-hot .rail-chip,.rail-row.here .rail-chip{--halo:#ff4538}
.rail-row.near.u-hot .rail-chip{animation:rail-hot 1.15s ease-in-out infinite}
@keyframes rail-hot{0%,100%{box-shadow:0 14px 34px -14px rgba(2,6,16,.7),0 0 24px -10px var(--halo)}
  50%{box-shadow:0 14px 34px -14px rgba(2,6,16,.7),0 0 46px -4px var(--halo)}}
/* ── ARRIVAL: “you are here” — the hazard moves to the foreground ── */
.rail-row.here{z-index:5}
.rail-row.here .rail-chip{padding:0.75rem 1rem;border-radius:var(--r-l);background:var(--glass-2);border-color:var(--brd);
  transform:scale(1.04);animation:rail-arrive .55s cubic-bezier(.2,1.35,.35,1),rail-hot 1.15s ease-in-out .55s 3;
  box-shadow:var(--sh-2)}
@keyframes rail-arrive{0%{transform:scale(.98)}55%{transform:scale(1.08)}100%{transform:scale(1.04)}}
.rail-row.here .rail-ic{width:44px;height:44px}
.rail-row.here .rail-d{font-size:1.95rem}
.rail-row.here .rail-lab{font-size:1.05rem;font-weight:800;opacity:1}
.rail-row.here .rail-node{width:18px;height:18px}
/* Origine : « Vous » */
.rail-you{position:relative;display:flex;align-items:center;height:1.5rem;color:var(--txt-dim);font-size:.66rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}
.rail-you .you{position:absolute;left:-1.15rem;top:50%;transform:translate(-50%,-50%);width:17px;height:17px;border-radius:0;background:var(--s-accent);
  clip-path:polygon(50% 0, 100% 100%, 50% 78%, 0 100%);box-shadow:none}
/* ============================================================================
   ALERTE DANGER — carte instrument (copilot) + bandeau (carte)
   ========================================================================== */
#sent-card{width:92%;max-width:358px;margin-inline:auto;flex:none;display:flex;align-items:center;gap:0.75rem;padding:0.75rem 1rem;border-radius:var(--r-l);color:var(--txt);position:relative;overflow:hidden;
  background:var(--ba,#ef4444);border:2px solid rgba(0,0,0,.28)}
/* FULL SUN. Behind a windshield, a translucent blurred background takes on the color
   of the road: it becomes unreadable exactly when it is needed most. The whole
   structure remains; only the materials become solid fills and the strokes
   become thicker. This is a mode that is CHOSEN — never guessed on behalf of
   someone. */
body.plein-soleil #sent-card,body.plein-soleil #sent-road,body.plein-soleil #sent-status-chip,
body.plein-soleil .set-card,body.plein-soleil .sheet-card,body.plein-soleil .bl-card{
  backdrop-filter:none!important;-webkit-backdrop-filter:none!important}
body.plein-soleil #sent-road,body.plein-soleil #sent-status-chip{background:var(--glass-2);border-width:2px}
body.plein-soleil .sr-val,body.plein-soleil .sr-conf{filter:none!important}
body.plein-soleil #dash-hero .sr-val{stroke-width:15}
body.plein-soleil{--brd:rgba(150,182,235,.5);--txt-dim:#c2cee0}

/* THE TILE'S GRAIN. It remains exactly what it is — full color, visibly deliberate:
   it stands out and owns it. A 2.5% texture is added, invisible in screenshots, and
   the color becomes ink on aluminum instead of a slab of backlit plastic.
   No request: the noise is generated in the page. */
#sent-card::after{content:"";position:absolute;inset:0;pointer-events:none;opacity:.025;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E")}
#sent-card[hidden]{display:none}
#sent-card::before{display:none}
body.alerting #sent-card{box-shadow:0 6px 18px -9px rgba(2,6,16,.5);animation:cardIn .42s cubic-bezier(.2,.7,.3,1)}
@keyframes cardIn{from{transform:translateY(14px) scale(.94);opacity:0}to{transform:none;opacity:1}}
.card-ic{width:58px;height:58px;flex:none;border-radius:15px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.94);border:0;box-shadow:none}
.card-ic svg{width:40px;height:40px}
@keyframes sent-mob-pulse{0%,100%{box-shadow:0 0 0 0 rgba(225,29,72,.55)}50%{box-shadow:0 0 0 11px rgba(225,29,72,0)}}
body.alerting[data-kind="mouvante"] .card-ic{animation:sent-mob-pulse 1s ease-in-out infinite}
.card-main{flex:1;min-width:0}
/* Alert card label: 2 lines max, never an ellipsis — « ZONE DE VIGILANCE
   PERMANENTE » (the longest) must be fully readable on a 390 px screen. */
.card-label{font-size:.9rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--ba-txt,#fff);opacity:.96;line-height:1.2;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.card-dist{font-size:1.62rem;font-weight:800;line-height:1.08;color:var(--ba-txt,#fff);letter-spacing:-.01em;white-space:nowrap}
.card-act{display:flex;gap:0.5rem;flex:none}
.card-act[hidden]{display:none}
.card-act button{width:44px;height:44px;border-radius:13px;border:1px solid var(--brd);background:var(--hi);display:flex;align-items:center;justify-content:center;cursor:pointer}
.card-act button#card-yes{color:var(--s-ok)}
.card-act button#card-no{color:var(--s-danger)}
.card-bar{position:absolute;left:0;bottom:0;height:5px;width:0;background:color-mix(in srgb, var(--ba-txt,#fff) 85%, transparent);box-shadow:0 -1px 0 rgba(0,0,0,.18);transition:width .5s ease}

/* Alert banner (map mode) */
#sent-alert{position:fixed;top:calc(env(safe-area-inset-top) + 3rem);left:50%;transform:translateX(-50%) translateY(-140%);opacity:0;visibility:hidden;
  z-index:600;min-width:280px;max-width:calc(100vw - 1.5rem);display:none;align-items:center;gap:0.75rem;
  background:var(--glass-2);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  border:1px solid var(--brd);border-left:5px solid var(--ba,#ef4444);color:var(--txt);
  border-radius:var(--r-l);padding:0.75rem 1rem;box-shadow:var(--sh-2);transition:transform .35s cubic-bezier(.2,.7,.3,1),opacity .3s,visibility 0s linear .35s}
body.mode-map #sent-alert:not([hidden]){display:flex;transform:translateX(-50%) translateY(0);opacity:1;visibility:visible;transition:transform .35s cubic-bezier(.2,.7,.3,1),opacity .3s,visibility 0s}
#sent-alert strong{font-size:1rem}
#sent-alert #sent-alert-dist{margin-left:auto;font-weight:800;font-size:1.14rem;color:var(--txt);white-space:nowrap}

/* AVERAGE speed in a section-type control zone: premium azure indicator,
   comparing the current average with the limit. Color code: green (OK) / orange (limit) / red (trigger risk). */
#sent-troncon{position:fixed;top:calc(env(safe-area-inset-top) + 3rem);left:50%;transform:translateX(-50%);
  z-index:590;width:min(92vw,340px);display:flex;flex-direction:column;gap:.5rem;pointer-events:none;
  --tc:var(--s-ok);
  background:var(--glass-2);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  border:1px solid var(--brd);border-top:3px solid var(--tc);color:var(--txt);
  border-radius:var(--r-l);padding:0.75rem 1rem 0.75rem;box-shadow:var(--sh-1);
  transition:transform .3s cubic-bezier(.2,.7,.3,1),opacity .25s,border-color .3s,box-shadow .3s}
#sent-troncon[hidden]{display:none}
#sent-troncon.tr-warn{--tc:var(--s-warn)}
#sent-troncon.tr-over{--tc:var(--s-danger)}
#sent-troncon.tr-enter{animation:trIn .4s cubic-bezier(.2,.7,.3,1)}
@keyframes trIn{from{opacity:0;transform:translateX(-50%) translateY(-16px)}to{opacity:1;transform:translateX(-50%) translateY(0)}}
.tr-cap{font-size:.75rem;font-weight:800;letter-spacing:.03em;text-transform:uppercase;color:var(--txt-dim);text-align:center}
.tr-cap em{font-style:normal;font-weight:700;opacity:.8}
.tr-row{display:flex;align-items:flex-end;justify-content:center;gap:1rem}
.tr-avg{display:flex;flex-direction:column;align-items:center;line-height:1}
.tr-avg b{font-size:2.5rem;font-weight:800;letter-spacing:-.02em;color:var(--txt);font-variant-numeric:tabular-nums;
  transition:color .3s;text-shadow:none}
.tr-avg small,.tr-rest small{margin-top:.15rem;font-size:.62rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-dim)}
.tr-lim{display:flex;flex-direction:column;align-items:center;gap:.2rem}
.tr-lim small{font-size:.58rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-dim)}
.tr-limsign{display:flex;align-items:center;justify-content:center;width:2.35rem;height:2.35rem;border-radius:50%;
  background:#fff;color:#0a0a0a;font-weight:800;font-size:1.05rem;font-style:normal;font-variant-numeric:tabular-nums;
  box-shadow:inset 0 0 0 3px var(--sign-red),0 4px 12px -4px rgba(2,6,16,.5)}
.tr-rest{display:flex;flex-direction:column;align-items:center;line-height:1}
.tr-rest b{font-size:1.35rem;font-weight:800;color:var(--txt);font-variant-numeric:tabular-nums}
.tr-bar{height:5px;border-radius:99px;background:var(--brd-soft,rgba(142,175,230,.22));overflow:hidden}
.tr-bar i{display:block;height:100%;width:0;border-radius:99px;background:var(--tc);transition:width .4s ease,background .3s}

/* “On your route” (map mode): tiered chips */
#sent-ahead{position:fixed;left:.7rem;top:var(--haut-4);z-index:560;display:flex;flex-direction:column;gap:0.5rem;max-width:66vw;pointer-events:none}
#sent-ahead[hidden]{display:none}
/* Two banners above: “what is coming up ahead” moves down accordingly. The stylesheet
   OBSERVES what is present — it has no state to synchronize with the code. */
body:has(#sent-lesson-chip:not([hidden])) #sent-ahead{top:calc(var(--haut-4) + 2.5rem)}
body.mode-hud #sent-ahead{display:none}
.ahead-item{display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0.75rem;border-radius:13px;
  background:var(--glass-2);border:1px solid var(--brd-soft);border-left:3px solid currentColor;box-shadow:0 8px 22px -10px rgba(2,6,16,.6)}
.ahead-ic{display:flex;flex:none}
.ahead-ic svg{display:block}
.ahead-lab{font-size:.82rem;font-weight:700;color:var(--txt);white-space:nowrap}
.ahead-d{margin-left:auto;font-size:.9rem;font-weight:800;color:var(--txt);padding-left:0.5rem;white-space:nowrap}
.ahead-d small{font-size:.78em;font-weight:600;color:var(--txt-dim)}
.ahead-item.near{border-left:3px solid var(--pc,#ef4444)}
.ahead-item.near .ahead-lab{font-size:.9rem}
.ahead-item.near .ahead-d{font-size:1.02rem;color:var(--txt)}

/* Anti-stacking: during an alert, show only the speedometer + alert card */
body.alerting #sent-install, body.alerting #lim-vote, body.alerting #sent-predict{ display:none !important; }
/* DURING AN ALERT, TURN OFF THE RADIO AND ROAD NAME. In one second of looking, only
   the speed, limit and alert card must remain. Nothing is REMOVED — anything
   that does not belong in the foreground at that exact moment is moved back. */
body.alerting #sent-radio-mini{opacity:.3;filter:saturate(.4)}
body.alerting #sent-road{opacity:.5}
body.mode-hud:has(#sent-predict .rail) #sent-install{ display:none !important; }

/* ============================================================================
   CAUTION ZONE — EDGE GLOW (luminous vignette): the color comes from the
   edges of the screen; the center stays sharp and readable (clear HUD).
   Green (speed <= limit) -> orange (over limit) -> red (well over, PULSE).
   Two inner shadows: saturated line right at the edge + broad fading wash.
   Fixed layer BEHIND the HUD (z-index below 480), pointer-events:none.
   ========================================================================== */
#sent-zonebg{position:fixed;inset:0;z-index:400;pointer-events:none;opacity:0;
  /* Glow rise/fall SYNCHRONIZED with the scrolling limit digit
     (#limit-big .lb-strip: .95s, same curve) — the glow rises when the limit moves down. */
  transition:opacity .95s cubic-bezier(.3,.86,.22,1),box-shadow .45s ease}
body.zone-ok #sent-zonebg,body.zone-over #sent-zonebg,body.zone-crit #sent-zonebg{opacity:1}
body.zone-ok #sent-zonebg{box-shadow:inset 0 0 3vmin .7vmin rgba(48,212,124,.52),inset 0 0 15vmin 3.2vmin rgba(34,197,94,.36)}
body.zone-over #sent-zonebg{box-shadow:inset 0 0 3.8vmin 1.1vmin rgba(255,159,46,.66),inset 0 0 17vmin 4.2vmin rgba(249,115,22,.46)}
body.zone-crit #sent-zonebg{box-shadow:inset 0 0 4.6vmin 1.6vmin rgba(255,69,58,.76),inset 0 0 21vmin 5.6vmin rgba(220,38,38,.54);animation:zonePulse .55s ease-in-out infinite}
@keyframes zonePulse{0%,100%{opacity:.66}50%{opacity:1}}
[data-theme="light"] body.zone-ok #sent-zonebg{box-shadow:inset 0 0 3vmin .7vmin rgba(22,163,74,.55),inset 0 0 15vmin 3.2vmin rgba(22,163,74,.38)}
[data-theme="light"] body.zone-over #sent-zonebg{box-shadow:inset 0 0 3.8vmin 1.1vmin rgba(234,88,12,.62),inset 0 0 17vmin 4.2vmin rgba(234,88,12,.42)}
[data-theme="light"] body.zone-crit #sent-zonebg{box-shadow:inset 0 0 4.6vmin 1.6vmin rgba(220,38,38,.7),inset 0 0 21vmin 5.6vmin rgba(220,38,38,.48)}

/* SLOW DOWN: no panel — just the word, centered in the FREE area below the alert card
   (never over the ring, speed bubble or « dans X m »), blurred background behind it.
   Only visible when over the limit (zone-over / zone-crit); it goes away as soon as you slow down. */
#sent-slowdown{position:fixed;inset:0;z-index:860;pointer-events:none;display:none;align-items:flex-end;justify-content:center;
  padding-bottom:calc(env(safe-area-inset-bottom) + 13vh)}
body.mode-map #sent-slowdown{align-items:center;padding-bottom:0}   /* on the map, no in-flow alert card: dead centre */
.sd-cible{position:absolute;left:50%;transform:translateX(-50%);bottom:-3.4rem;
  min-width:3.4rem;padding:.15rem .5rem;border-radius:999px;
  background:#f3f5f8;color:#0a0a0a;border:.28rem solid var(--sign-red);
  font-size:1.5rem;font-weight:900;line-height:1.15;text-align:center;font-variant-numeric:tabular-nums}
body.mode-map .sd-cible{bottom:-3.9rem}
#sent-slowdown span{font-weight:800;font-size:clamp(2.3rem,11vw,4.4rem);line-height:1;letter-spacing:.06em;color:#fff;
  padding:1.5rem 2rem;border-radius:30px;background:rgba(190,18,26,.94);
  box-shadow:var(--sh-3);
  text-shadow:0 2px 10px rgba(0,0,0,.4)}
body.zone-over #sent-slowdown,body.zone-crit #sent-slowdown{display:flex}
body.zone-over #sent-slowdown span,body.zone-crit #sent-slowdown span{animation:slowPulse .62s ease-in-out infinite}
@keyframes slowPulse{0%,100%{transform:scale(1)}50%{transform:scale(1.05)}}
/* When a LIMIT dialog is open, hide “SLOW DOWN”: it must never cover the
   correction window (P2/P3). Dialogs (z 950/951, at body level) already appear above it. */
body:has(#sent-limedit:not([hidden])) #sent-slowdown,
body:has(#sent-limconfirm:not([hidden])) #sent-slowdown{display:none!important}
/* While speeding, SLOW DOWN (safety) takes priority: the "toujours present ?" pop-up and vote card give way (never stacked). */
body:is(.zone-over,.zone-crit) #sent-passconfirm,
body:is(.zone-over,.zone-crit) #lim-vote{display:none!important}
body:has(#sent-limedit:not([hidden])) #sent-zonebg,
body:has(#sent-limconfirm:not([hidden])) #sent-zonebg{animation:none!important}

/* ============================================================================
   BOUTONS PRINCIPAUX
   ========================================================================== */
#sent-start{position:fixed;left:50%;bottom:calc(env(safe-area-inset-bottom) + 7.2rem);transform:translateX(-50%);z-index:700;
  background:var(--tint);color:#fff;border:none;border-radius:999px;
  padding:1rem 2rem;font-size:1rem;font-weight:800;box-shadow:0 12px 34px rgba(30,95,214,.45);cursor:pointer}
#sent-start:active{transform:translateX(-50%) scale(.97)}
body.mode-map #sent-start{bottom:calc(env(safe-area-inset-bottom) + 9.4rem)}
#sent-start[hidden]{display:none}

#sent-mode{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(env(safe-area-inset-bottom) + 1.1rem);z-index:600;
  color:var(--txt);background:var(--glass-2);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);border:1px solid var(--brd);border-radius:var(--r-m);
  padding:0.75rem 1.25rem;font-size:.95rem;font-weight:700;box-shadow:var(--shadow);cursor:pointer;display:none;align-items:center;gap:.5rem}
#sent-mode svg{color:var(--s-accent)}
#sent-mode.show{display:inline-flex}
body.mode-map #sent-mode{left:auto;right:1rem;bottom:calc(env(safe-area-inset-bottom) + 6.2rem);transform:none}
/* A two-line message reaches down to the « Carte » button. Give it
   room instead of relying on short text: text always gets longer. */
body:not(.mode-map) #sent-toast{bottom:calc(env(safe-area-inset-bottom) + 5.6rem)}
/* In MAP mode, the “Map” button moves down on the right: the message, 88% of
   the screen wide, catches it. It goes above — the button height is known (44 px),
   the message height is not, so the message must move aside. */
body.mode-map #sent-toast{bottom:calc(env(safe-area-inset-bottom) + 9.6rem)}

#sent-report{position:fixed;right:1rem;bottom:calc(env(safe-area-inset-bottom) + 1rem);z-index:520;width:62px;height:62px;border-radius:50%;
  background:var(--tint);color:#fff;border:none;box-shadow:0 12px 30px rgba(30,95,214,.45);cursor:pointer;display:none}
#sent-report.show{display:flex;align-items:center;justify-content:center}
#sent-report svg{display:block}

#sent-mapctrl{position:fixed;right:1rem;top:50%;transform:translateY(-50%);z-index:540;display:none;flex-direction:column;gap:.5rem}
body.mode-map #sent-mapctrl{display:flex}
/* WHILE MOVING, TARGETS GROW. 44 px is enough on a mounted phone;
   in a car, the hand shakes with the body and the arm is extended. They are spaced out too:
   a NEIGHBORING error (touching the button next to it) costs more than a
   simple miss, because it TRIGGERS something. */
body.en-route #sent-mapctrl button{width:56px;height:56px;border-radius:16px}
body.en-route #sent-mapctrl{gap:0.75rem}
#sent-mapctrl button{width:44px;height:44px;border-radius:13px;color:var(--txt);font-weight:800;font-size:.95rem;cursor:pointer;display:flex;align-items:center;justify-content:center;
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);border:1px solid var(--brd);box-shadow:var(--shadow)}
#sent-mapctrl button svg{width:20px;height:20px;display:block}
#sent-mapctrl button:active{transform:scale(.94)}

/* IGN credit */
#sent-credit{position:fixed;right:.5rem;bottom:.35rem;z-index:550;font-size:9px;color:var(--txt-dim);
  background:var(--glass);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);padding:1px 6px;border-radius:6px;pointer-events:none;display:none}
body.mode-map #sent-credit{display:block}

/* ============================================================================
   MAP MODE: reduced dial (limit panel) at bottom-left
   ========================================================================== */
/* THE COLUMN DID NOT KNOW THERE WERE FIXED BUTTONS AT THE BOTTOM. The radio player and
   alert tile came down over them. It now reserves their height: 50 px for the
   button, plus the phone's safe area, plus breathing room. */
/* PADDING ON THE CONTAINER IS NOT ENOUGH: measurements showed that the content
   still overflowed it. Padding reserves space if the content allows itself to be
   pushed — it prevents nothing. The margin is therefore placed on the LAST elements, those
   that touch the buttons: this is measurable; the other approach was only an intention. */
/* THE COLUMN STARTS BELOW THE TOP STACK and stops above the buttons. One
   gap declared ONCE on the container, instead of every element recalculating the
   space of its neighbors — that recalculation failed at every screen height. */
body.mode-hud #sent-dash{
  padding-top:calc(var(--haut-2) + 1.8rem);
  padding-bottom:calc(env(safe-area-inset-bottom) + 4.6rem)}
/* THE GAP WAS COUNTED TWICE: the column reserves 113 px, while the dial kept
   its original 117 px. The column owns the gap — the dial no longer has anything to
   compenser. */
body.mode-hud .dash-hero{margin-top:clamp(.5rem, 4vh, 2rem)}
/* The small-screen setting ALREADY lives in a block below — @media (max-height:
   740px). I had built a second one here: two parallel mechanisms for the same
   need, one of which never applied. Removed. */

/* AND ON A TRULY SHORT SCREEN, THE PLAYER IS HIDDEN — never the
   driving instruments. A radio that cannot be seen costs a song; a speed
   that cannot be seen costs something else. The player remains accessible in full screen. */
#sent-hud{position:fixed;left:1rem;bottom:calc(env(safe-area-inset-bottom) + 1rem);z-index:500;display:flex;align-items:flex-end;gap:0.75rem}
body.mode-hud #sent-hud{display:none}
body.mode-map #sent-hud{display:none}
.sent-speed{width:84px;height:84px;border-radius:50%;color:var(--txt);
  background:var(--glass-2);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);border:1px solid var(--brd);
  display:flex;flex-direction:column;align-items:center;justify-content:center;box-shadow:var(--shadow)}
.sent-speed span{font-size:1.9rem;font-weight:800;line-height:1}
.sent-speed small{font-size:.62rem;color:var(--txt-dim);letter-spacing:.04em}
.sent-speed.over{border-color:var(--s-danger);color:#fff;background:rgba(190,40,40,.6)}
.sent-limit{width:62px;height:62px;border-radius:50%;background:#fff;border:6px solid var(--sign-red);
  display:flex;flex-direction:column;align-items:center;justify-content:center;box-shadow:var(--shadow)}
.sent-limit span{font-size:1.35rem;font-weight:800;line-height:1;color:#0f2544}
.sent-limit[hidden]{display:none}
.sent-limit small{display:none}
html[data-veh="moto"] .sent-speed #sent-speed-val, html[data-veh="pl"] .sent-speed #sent-speed-val, html[data-veh="bus"] .sent-speed #sent-speed-val{font-size:2.5rem}

body.mode-map #sent-dash{display:block;position:fixed;inset:auto auto 0 0;width:auto;height:auto;min-height:0;padding:0;gap:0;pointer-events:none;z-index:490}
body.mode-map #sent-dash::before{content:none}
body.mode-map #sent-dash > #sent-card,
body.mode-map #sent-dash > #sent-predict{display:none!important}
body.mode-map .dash-hero{position:fixed;left:.7rem;bottom:calc(env(safe-area-inset-bottom) + .9rem);margin:0;width:min(27vw,108px);height:min(27vw,108px);pointer-events:auto;z-index:491}
body.mode-map .dash-hero .speedring{display:none}   /* the ring lives in copilot; on the map, speed sits in the puck */
body.mode-map .dash-hero .hero-core{display:none}
body.mode-map .limit-sign{position:absolute;inset:0;width:100%;height:100%;right:auto;bottom:auto}
body.mode-map #limit-adj{bottom:auto;top:-1.5rem}
.dash-hero{filter:none!important}  /* filter+compositing = light square (WebKit bug): never a filter on the dial */

/* ============================================================================
   NAVIGATION (Premium): search + route + guidance
   ========================================================================== */
#nav-bar,#nav-summary,#nav-maneuver{position:fixed;left:50%;transform:translateX(-50%);z-index:560;width:calc(100% - 1.4rem);max-width:440px;display:none}
#nav-bar{top:var(--haut-1)}
body.mode-map:not(.nav-routing):not(.guiding) #nav-bar{display:block}
.nav-srow{display:flex;align-items:center;gap:0.5rem;background:var(--glass-2);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);border:1px solid var(--brd);border-radius:var(--r-l);padding:0.25rem 0.75rem;box-shadow:var(--shadow)}
.nav-prow{margin-top:0.5rem}
.nav-prof-seg{background:var(--glass-2);backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);border:1px solid var(--brd);box-shadow:var(--shadow)}
.nav-prof-seg button.on{background:linear-gradient(135deg,#0d9488,#0f766e)}
.nav-srow svg{width:18px;height:18px;flex:none;opacity:.85;color:var(--txt-dim)}
#nav-input{flex:1;min-height:44px;background:transparent;border:0;outline:none;color:var(--txt);-webkit-text-fill-color:var(--txt);font-size:1rem;min-width:0;-webkit-appearance:none;appearance:none}
#nav-input::-webkit-search-cancel-button,#nav-input::-webkit-search-decoration{-webkit-appearance:none;appearance:none}
#nav-input::placeholder{color:var(--txt-dim)}
#nav-input:-webkit-autofill{-webkit-text-fill-color:var(--txt)!important;transition:background-color 99999s ease-in-out 0s}
/* ONLY ONE PREMIUM BADGE. Four rival styles were living in four places; a
   badge that changes appearance with the screen stops being recognized as the same
   badge, and therefore no longer signals anything. */
.nav-pro{font-style:normal;font-size:.6rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--tint-vif);background:transparent;border:1px solid var(--tint-vif);padding:.1rem 0.5rem;border-radius:6px;flex:none}
#nav-results{margin-top:0.5rem;display:flex;flex-direction:column;gap:.25rem;max-height:46vh;overflow:auto;-webkit-overflow-scrolling:touch}
#nav-results:empty{display:none}
.nav-res{text-align:left;background:var(--glass-2);backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);border:1px solid var(--brd);border-radius:12px;padding:0.5rem .75rem;color:var(--txt);font-size:.9rem;cursor:pointer;width:100%}
.nav-res:active{transform:scale(.99)}
.nav-res.nav-fav{display:flex;align-items:center;gap:0.5rem}
.nav-res.nav-fav svg{width:18px;height:18px;flex:none;opacity:.8}
#nav-summary{top:calc(env(safe-area-inset-top) + 3.4rem);background:var(--glass-2);backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);border:1px solid var(--brd);border-radius:16px;padding:0.5rem 0.75rem;box-shadow:var(--shadow);flex-direction:column;align-items:stretch;gap:.5rem}
body.mode-map.nav-routing:not(.guiding) #nav-summary{display:flex}
.nav-sumtop{display:flex;align-items:center;gap:0.5rem}
.nav-suminfo{flex:1;display:flex;flex-direction:column;line-height:1.12}
.nav-suminfo b{font-size:1.15rem;color:var(--txt)}
.nav-suminfo span{font-size:.8rem;color:var(--txt-dim)}
#nav-go{background:var(--tint);color:#fff;border:0;border-radius:12px;padding:0.5rem 1rem;font-weight:800;cursor:pointer}
#nav-cancel,#nav-stop{background:var(--hi);color:var(--txt);border:0;border-radius:50%;width:40px;height:40px;font-size:1rem;cursor:pointer;flex:none}
#nav-share{background:var(--hi);color:var(--txt);border:0;border-radius:50%;width:40px;height:40px;cursor:pointer;flex:none;display:inline-flex;align-items:center;justify-content:center}
.nav-sumact{display:flex;gap:0.5rem}
.nav-act{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:0.25rem;background:var(--hi);color:var(--txt);border:1px solid var(--brd);border-radius:10px;padding:.5rem;font-size:.82rem;font-weight:700;cursor:pointer}
.nav-act svg{width:16px;height:16px;flex:none}
#nav-maneuver{top:calc(env(safe-area-inset-top) + 3.4rem);align-items:center;gap:0.75rem;background:linear-gradient(150deg,#0f2544,#0a1830);border:1px solid rgba(142,175,230,.2);border-radius:18px;padding:.75rem 0.75rem;box-shadow:0 14px 36px rgba(2,6,16,.55),inset 0 1px 0 rgba(160,195,255,.12)}
body.mode-map.guiding #nav-maneuver{display:flex}
#nav-man-dist{font-size:1.7rem;font-weight:800;color:#39d5ff;flex:none;min-width:70px;letter-spacing:-.01em}
#nav-man-instr{flex:1;font-size:1.02rem;font-weight:600;color:#fff;line-height:1.18}
.nav-man-tx{flex:1;display:flex;flex-direction:column;gap:.1rem;min-width:0}
#nav-man-next{font-size:.85rem;font-weight:600;color:#9fd7ff;opacity:.92}
#nav-man-next[hidden]{display:none}
/* Puces contexte */
.nav-chips{display:flex;flex-wrap:wrap;gap:0.25rem}
.nav-chips:empty{display:none}
.nav-chip{font-size:.78rem;font-weight:700;padding:0.25rem 0.5rem;border-radius:999px;background:var(--hi);color:var(--txt);border:1px solid var(--brd)}
.nav-chip[hidden]{display:none}
.nav-chip.haz{background:#dc2626;color:#fff;border-color:transparent}
.nav-chip.wx{background:#1e5fd6;color:#fff;border-color:transparent}
.nav-chip.pl{background:#475569;color:#fff;border-color:transparent}
.nav-chip.restr{background:#b45309;color:#fff;border-color:transparent}
.nav-chip.brk{background:#d97706;color:#fff;border-color:transparent}
.nav-chip.learn{background:#16a34a;color:#fff;border-color:transparent}
.nav-chip.zfe{background:#0d9488;color:#fff;border-color:transparent}
/* Alternatives + arrive on time */
.nav-alts{display:flex;gap:0.5rem;flex-wrap:wrap}
.nav-alts:empty{display:none}
.nav-alt{flex:1;min-width:96px;display:flex;flex-direction:column;align-items:flex-start;gap:.02rem;background:var(--hi);color:var(--txt);border:1px solid var(--brd);border-radius:10px;padding:0.5rem 0.5rem;cursor:pointer}
.nav-alt.on{border-color:var(--s-accent);background:rgba(62,162,255,.15)}
.nav-alt b{font-size:.95rem;font-weight:800}
.nav-alt span{font-size:.72rem;color:var(--txt-dim)}
.nav-arrive{display:flex;align-items:center;justify-content:space-between;gap:.5rem;font-size:.82rem;font-weight:700;color:var(--txt);background:var(--hi);border:1px solid var(--brd);border-radius:10px;padding:0.25rem 0.25rem 0.25rem 0.75rem}
.nav-arrive input[type=time]{background:transparent;border:0;color:var(--txt);-webkit-text-fill-color:var(--txt);font-weight:700;font-size:.9rem}

/* ============================================================================
   SHEETS & POP-UPS (shared frosted-glass veil)
   ========================================================================== */
#sent-settings, #sent-sheet, #sent-limedit, #sent-ios, #sent-credits{ background:rgba(4,8,16,.42); backdrop-filter: blur(18px) saturate(1.12); -webkit-backdrop-filter: blur(18px) saturate(1.12); height:100dvh; }
/* Shared opening for sheets/pop-ups: fading veil + card with a soft spring (never abrupt).
   transform/opacity only; a single pass on opening, nothing running continuously. */
@keyframes veilIn{from{opacity:0}to{opacity:1}}
@keyframes cardPop{from{opacity:0;transform:translateY(16px) scale(.965)}to{opacity:1;transform:none}}
#sent-settings:not([hidden]),#sent-sheet:not([hidden]),#sent-limedit:not([hidden]),#sent-limconfirm:not([hidden]),#sent-credits:not([hidden]),#sent-ios:not([hidden]),#sent-trips:not([hidden]){animation:veilIn .26s ease}
#sent-settings:not([hidden]) .set-card,#sent-sheet:not([hidden]) .sheet-card,#sent-limedit:not([hidden]) .limedit-card,#sent-limconfirm:not([hidden]) .limedit-card,#sent-credits:not([hidden]) .credits-card,#sent-ios:not([hidden]) .ios-card,#sent-trips:not([hidden]) .trips-card{animation:cardPop .38s cubic-bezier(.22,1.18,.34,1)}

/* Credits */
#sent-credits{position:fixed;inset:0;z-index:950;display:flex;align-items:center;justify-content:center;padding:1.25rem}
#sent-credits[hidden]{display:none}
.credits-card{width:100%;max-width:360px;color:var(--txt);background:var(--glass-2);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);border:1px solid var(--brd);border-radius:var(--r-xl);padding:1.25rem 1.25rem 1rem;box-shadow:var(--sh-2)}
.credits-title{font-weight:800;font-size:1.2rem;margin-bottom:0.75rem}
.credits-card ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}
.credits-card li{font-size:.9rem;color:var(--txt)}
.credits-note{font-size:.74rem;color:var(--txt-dim);margin:1rem 0 1rem;line-height:1.4}
.credits-close{width:100%;min-height:48px;border-radius:14px;border:1px solid var(--brd);background:var(--hi);color:var(--txt);font-weight:800;font-size:1rem;cursor:pointer}

/* Report sheet */
#sent-sheet{position:fixed;inset:0;z-index:900;display:flex;align-items:center;justify-content:center;padding:0.75rem}
#sent-sheet[hidden]{display:none}
/* ANCHORED AT THE BOTTOM, NOT FULL SCREEN. The driver must never lose sight of speed and
   limit while choosing a type. All seventeen types remain
   present: scroll through them, remove nothing. */
body.en-route #sent-sheet{align-items:flex-end}
body.en-route .sheet-card{max-height:62dvh;border-radius:22px 22px 0 0}
/* MY DIRECTION / OPPOSITE DIRECTION. Two wide buttons, never a menu: this is a
   binary choice made in three seconds, often one-handed. It returns to « Mon sens » on
   every opening — a setting stuck on « inverse » would create
   dozens of false reports without anyone noticing. */
.pl-slots{display:flex;gap:0.5rem;margin:0 0 0.75rem}
.pl-slot{flex:1;min-height:44px;border:1px solid var(--brd);border-radius:12px;background:transparent;
  color:var(--txt-dim);font-weight:800;font-size:.82rem;cursor:pointer}
.pl-slot.actif{background:var(--tint);border-color:var(--tint);color:#fff}
.pl-garder{flex:0 0 auto;padding:0 0.75rem;color:var(--tint-vif);border-color:var(--tint-vif)}

.direction-seg{display:flex;gap:0.5rem;margin:.2rem 0 0.75rem}
.direction-b{flex:1;min-height:44px;border:1px solid var(--brd);border-radius:12px;
  background:transparent;color:var(--txt-dim);font-weight:800;font-size:.86rem;cursor:pointer}
.direction-b.actif{background:var(--tint);border-color:var(--tint);color:#fff}

.sheet-card{width:min(94vw,440px);max-height:calc(100dvh - 1.4rem);display:flex;flex-direction:column;background:var(--glass-2);border:1px solid var(--brd);border-radius:var(--r-xl);box-shadow:var(--sh-2);padding:1rem}
.sheet-title{position:relative;font-weight:800;font-size:1.25rem;text-align:center;margin:.1rem 0 1rem;color:var(--txt)}
.sheet-title .set-close{position:absolute;right:0;top:50%;transform:translateY(-50%)}
/* Quick selector: 5 large tiles, one tap = report sent, tap outside = close */
.sheet-grid{display:grid;grid-template-columns:repeat(2,1fr);grid-auto-rows:minmax(104px,auto);gap:0.5rem;align-content:start;flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;padding-right:.15rem}
.sheet-grid button{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:0.5rem;color:var(--txt);
  background:var(--hi);border:1px solid var(--brd-soft);border-radius:20px;padding:0.75rem .5rem;
  font-size:1.02rem;font-weight:800;line-height:1.15;text-align:center;cursor:pointer;-webkit-tap-highlight-color:transparent}
.sheet-grid button span{width:54px;height:54px;flex:none;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:var(--g2,#2f6fd0);box-shadow:0 8px 18px -8px var(--g2,#0a1a33)}
.sheet-grid button span svg{display:block;width:38px;height:38px}
.sheet-grid button.real-sign span{background:none!important;box-shadow:none!important;border-radius:0!important;filter:drop-shadow(0 2px 5px rgba(2,6,16,.35))}
.sheet-grid button.real-sign span svg{width:100%!important;height:100%!important}
.sheet-grid button:active{transform:scale(.97)}
.voice-report{display:flex;align-items:center;justify-content:center;gap:0.5rem;width:100%;margin:0 0 0.75rem;padding:0.75rem;border-radius:16px;border:0;font-weight:800;font-size:1rem;color:#fff;background:var(--tint);cursor:pointer;box-shadow:0 12px 28px -8px rgba(30,95,214,.7)}
.voice-report svg{width:22px;height:22px}
.voice-report.listening{background:linear-gradient(135deg,#ef4444,#b91c1c);animation:rtpulse 1.2s infinite}
.voice-report .vp-pro{font-style:normal;font-size:.6rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--tint-vif);background:transparent;border:1px solid var(--tint-vif);padding:.1rem 0.5rem;border-radius:6px;flex:none;margin-left:.5rem}

/* Limit correction */
#sent-limedit{position:fixed;inset:0;z-index:950;display:flex;align-items:center;justify-content:center}
#sent-limedit[hidden]{display:none}
.limedit-card{width:100%;max-width:440px;margin:0.75rem;background:var(--glass-2);border:1px solid var(--brd);border-radius:var(--r-xl);padding:1rem;color:var(--txt);box-shadow:var(--sh-2)}
.limedit-title{font-weight:800;font-size:1.25rem;text-align:center;margin-bottom:1.25rem}
.limedit-grid{display:flex;flex-wrap:wrap;justify-content:center;gap:1rem 5%}
.limedit-grid button{flex:0 0 27%;aspect-ratio:1;border:0;border-radius:50%;background:radial-gradient(circle closest-side,#fff 0 70%,var(--sign-red) 70% 86%,#111 86% 87%,transparent 87.4%);color:#0a0a0a;font-size:clamp(1.6rem,7.4vw,2.2rem);cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:none}
.limedit-grid button:active{transform:scale(.93)}
.limedit-cancel{margin-top:1.5rem;width:100%;border:0;border-radius:14px;padding:1rem;font-weight:700;font-size:1.05rem;background:var(--hi);color:var(--txt);cursor:pointer}
#sent-limconfirm{position:fixed;inset:0;z-index:951;display:flex;align-items:center;justify-content:center;background:rgba(4,8,16,.42);backdrop-filter:blur(18px) saturate(1.12);-webkit-backdrop-filter:blur(18px) saturate(1.12)}
#sent-limconfirm[hidden]{display:none}
.limconfirm-row{display:flex;gap:0.75rem}
.limconfirm-row button{flex:1;border:0;border-radius:14px;padding:1rem;font-weight:800;font-size:1.15rem;cursor:pointer;color:#fff}
.limconfirm-row button:active{transform:scale(.96)}
#limconfirm-yes{background:linear-gradient(135deg,#2563eb,#06b6d4)}
#limconfirm-fix{background:var(--hi);color:var(--txt)}

/* “Reported limit — correct?” card: premium azure, frosted glass, large and readable while driving.
   z-index 600 -> ABOVE the hazard rail (#sent-dash z480): no more overlap (P4). */
#lim-vote{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(env(safe-area-inset-bottom,0px) + 6.4rem);z-index:600;width:calc(100% - 1.6rem);max-width:430px;pointer-events:auto}
#lim-vote[hidden]{display:none}
.lv-card{position:relative;overflow:hidden;border-radius:var(--r-xl);padding:1rem 1rem 1.25rem;
  background:var(--glass-2);
  border:1px solid rgba(120,200,255,.34);color:var(--txt);
  box-shadow:var(--sh-2);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  animation:lvIn .42s cubic-bezier(.2,.9,.3,1) both}
[data-theme="light"] .lv-card{background:var(--glass-2);border-color:rgba(37,99,235,.28);color:#0f2036;box-shadow:var(--sh-2)}
/* lvIn applies to .lv-card (the CHILD): no translateX(-50%) here — the #lim-vote container is
   already centered by its own transform; doubling it shifted the card half a width off-screen. */
@keyframes lvIn{from{opacity:0;transform:translateY(14px) scale(.97)}to{opacity:1;transform:none}}
#lim-vote{transform:translateX(-50%)}
.lv-head{display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem}
.lv-sign{flex:none;width:56px;height:56px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:radial-gradient(circle closest-side,#fff 0 62%,var(--sign-red) 62% 100%);box-shadow:0 4px 14px rgba(0,0,0,.28)}
.lv-sign b{font-size:1.5rem;font-weight:800;color:#0a0a0a;font-variant-numeric:tabular-nums;line-height:1}
.lv-tx{min-width:0;display:flex;flex-direction:column;gap:.15rem}
.lv-tx b{font-size:1.14rem;font-weight:800;letter-spacing:.01em;line-height:1.15}
.lv-tx small{font-size:.86rem;font-weight:600;color:var(--txt-dim);opacity:.92}
.lv-actions{display:flex;gap:0.75rem}
body.en-route #sent-passconfirm .lv-actions button{min-height:76px;font-size:1.05rem}
.lv-actions button{flex:1;min-height:52px;display:flex;align-items:center;justify-content:center;gap:0.5rem;
  border:0;border-radius:15px;padding:0.75rem;font-weight:800;font-size:1.1rem;cursor:pointer;color:#fff;
  overflow:hidden;-webkit-tap-highlight-color:transparent;transition:transform .12s ease}
.lv-actions button svg{flex:none}
.lv-actions button:active{transform:scale(.96)}
.lv-yes{background:linear-gradient(135deg,#2563eb,#22d3ee)}
.lv-no{background:rgba(255,255,255,.14);color:var(--txt);border:1px solid rgba(255,255,255,.18)!important}
[data-theme="light"] .lv-no{background:rgba(15,32,54,.08);color:#0f2036;border-color:rgba(15,32,54,.14)!important}
.lv-mic{display:flex;align-items:center;justify-content:center;gap:.5rem;margin-top:.75rem;
  font-size:.82rem;font-weight:700;color:#7fd0ff;letter-spacing:.01em}
[data-theme="light"] .lv-mic{color:#0369a1}
.lv-mic[hidden]{display:none}
.lv-mic-dot{width:9px;height:9px;border-radius:50%;background:#38bdf8;box-shadow:0 0 0 0 rgba(56,189,248,.6);animation:lvMic 1.4s ease-out infinite}
@keyframes lvMic{0%{box-shadow:0 0 0 0 rgba(56,189,248,.55)}70%,100%{box-shadow:0 0 0 10px rgba(56,189,248,0)}}
/* Clean exclusion: when the card is present, move the rail above it -> no collision (P4). */
body:has(#lim-vote:not([hidden])) #sent-predict{padding-bottom:calc(env(safe-area-inset-bottom) + 13.5rem)}

/* Installation webapp */
#sent-install{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(env(safe-area-inset-bottom,0px) + 5.6rem);z-index:60;width:calc(100% - 1.6rem);max-width:430px}
#sent-install[hidden]{display:none}
.install-bar{display:flex;align-items:center;gap:0.75rem;padding:0.5rem 0.75rem;border-radius:18px;background:var(--glass-2);border:1px solid var(--brd);box-shadow:var(--sh-2);color:var(--txt)}
.install-ic{width:38px;height:38px;flex:none;border-radius:11px;display:flex;align-items:center;justify-content:center;background:var(--tint);color:#fff}
.install-ic svg{width:22px;height:22px}
.install-txt{flex:1;min-width:0;display:flex;flex-direction:column;line-height:1.18}
.install-txt b{font-size:.92rem}
.install-txt span{font-size:.72rem;opacity:.68}
#install-go{flex:none;border:0;border-radius:12px;padding:.5rem 1rem;font-weight:700;font-size:.85rem;color:#fff;background:var(--tint);cursor:pointer}
#install-x{flex:none;border:0;background:transparent;color:var(--txt);opacity:.45;font-size:.95rem;width:44px;height:44px;cursor:pointer}
#sent-ios{position:fixed;inset:0;z-index:950;display:flex;align-items:flex-end;justify-content:center}
#sent-ios[hidden]{display:none}
.ios-card{width:100%;max-width:480px;margin:0.5rem;border-radius:22px;padding:1rem 1rem 1rem;background:var(--glass-2);border:1px solid var(--brd);color:var(--txt);box-shadow:0 -10px 40px rgba(2,6,16,.4)}
.ios-title{font-weight:800;font-size:1.15rem;margin-bottom:.15rem}
.ios-sub{font-size:.8rem;opacity:.68;margin-bottom:1rem}
.ios-steps{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:0.75rem}
.ios-steps li{display:flex;align-items:center;gap:0.75rem;font-size:.92rem}
.ios-step-ic{width:34px;height:34px;flex:none;border-radius:10px;display:flex;align-items:center;justify-content:center;background:var(--hi);border:1px solid var(--brd-soft);color:var(--s-accent)}
.ios-step-ic svg{width:20px;height:20px}
#ios-note{font-size:.8rem;opacity:.85;margin:0.75rem 0 0;padding:0.5rem 0.75rem;border-radius:12px;background:var(--hi)}
#ios-note[hidden]{display:none}
.ios-close{margin-top:1rem;width:100%;border:0;border-radius:14px;padding:.75rem;font-weight:700;color:#fff;background:var(--tint);cursor:pointer}

/* Toast + suggestion */
/* THE FREE TRIAL. Same card as the summary: these are the same family of moments — stop,
   read, close. What is NOT requested is written as large as what is
   given: this is the part nobody else can copy. */
/* The « avant » screen: same card as the trial and summary. These are three moments from
   the same family — stop, read, close. It appears IN FRONT OF the
   consent without adding anything to it. */
#sent-before{position:fixed;inset:0;z-index:960;display:flex;align-items:center;justify-content:center;
  padding:1rem;background:rgba(4,8,16,.72);backdrop-filter:var(--blur-voile);-webkit-backdrop-filter:var(--blur-voile)}
#sent-before[hidden]{display:none}
[data-theme="light"] #sent-before{background:rgba(230,238,250,.8)}
#sent-before .bl-why div + div{margin-top:0.5rem}

/* THE QUICK-REPORT FAN. Four large discs around the thumb, where
   the hand already is. They appear in a cascade — the offset is not
   decoration: it shows the reading order, from nearest to farthest. */
.rep-fan{position:fixed;inset:0;z-index:1160;background:rgba(4,8,16,.5);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  display:flex;flex-direction:column;justify-content:flex-end;align-items:flex-end;
  gap:0.5rem;padding:0 1rem calc(env(safe-area-inset-bottom) + 5.6rem);
  opacity:0;transition:opacity .18s ease}
.rep-fan.ouvert{opacity:1}
.rep-ev{display:flex;align-items:center;justify-content:flex-end;min-height:60px;
  padding:0 1.25rem;border-radius:999px;border:1px solid var(--tint-vif);
  background:var(--glass-2);color:var(--txt);font-weight:800;font-size:1rem;cursor:pointer;
  box-shadow:var(--sh-2);transform:translateX(24px);opacity:0;
  transition:transform .22s cubic-bezier(.22,.9,.32,1),opacity .22s ease;
  transition-delay:calc(var(--i) * 40ms)}
.rep-fan.ouvert .rep-ev{transform:none;opacity:1}

/* REMEMBER THIS MOMENT. The button appears ONLY during a lesson — outside a lesson it
   would make no sense, and a useless button clutters a driving screen.
   On the passenger side, within the instructor's reach: the instructor uses it, not the student. */
#lecon-jalon{position:fixed;left:1rem;bottom:calc(env(safe-area-inset-bottom) + 1rem);z-index:520;
  display:flex;align-items:center;gap:0.5rem;min-height:56px;padding:0 1rem;border-radius:999px;
  background:var(--glass-2);color:var(--tint-vif);border:1px solid var(--tint-vif);
  font-weight:800;font-size:.86rem;cursor:pointer;box-shadow:var(--sh-2)}
#lecon-jalon[hidden]{display:none}
#lecon-jalon:active{transform:scale(.95)}
#lecon-jalon.pose{background:var(--tint);color:#fff;border-color:var(--tint)}

/* UNDER TEST CONDITIONS, remove the AIDS, never the dangers. Safety
   alerts remain complete: a mock test does not justify letting a student
   reach a crash without knowing. What disappears is what would help them
   look better — the list of what is ahead, the radio, the map. */
body.examen-blanc #sent-ahead,body.examen-blanc #sent-radio-mini,
body.examen-blanc #sent-predict,body.examen-blanc #sent-troncon{display:none!important}
body.examen-blanc #sent-mode{display:none!important}

/* Lesson summary: same card as the other stopping moments. It appears when
   the lesson ends, while the instructor can still discuss it with the student. */
#sent-lesson-summary{position:fixed;inset:0;z-index:1205;display:flex;align-items:center;justify-content:center;
  padding:1rem;background:rgba(4,8,16,.66);backdrop-filter:var(--blur-voile);-webkit-backdrop-filter:var(--blur-voile)}
#sent-lesson-summary[hidden]{display:none}
[data-theme="light"] #sent-lesson-summary{background:rgba(230,238,250,.74)}
#sent-lesson-summary .bl-why div + div{margin-top:0.5rem}

/* The school's gift: the same card as the other stopping moments. It is the
   strongest moment in the training — it deserves better than an email read between two
   publicites. */
#sent-gift{position:fixed;inset:0;z-index:1215;display:flex;align-items:center;justify-content:center;
  padding:1rem;background:rgba(4,8,16,.7);backdrop-filter:var(--blur-voile);-webkit-backdrop-filter:var(--blur-voile)}
#sent-gift[hidden]{display:none}
[data-theme="light"] #sent-gift{background:rgba(230,238,250,.78)}
#sent-gift .bl-why div + div{margin-top:0.5rem}

#sent-trial{position:fixed;inset:0;z-index:1210;display:flex;align-items:center;justify-content:center;
  padding:1rem;background:rgba(4,8,16,.66);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}
#sent-trial[hidden]{display:none}
[data-theme="light"] #sent-trial{background:rgba(230,238,250,.74)}
.es-title{font-size:1.5rem;font-weight:900;line-height:1.15;letter-spacing:-.01em}
.es-subtitle{margin:0.25rem 0 1rem;font-size:.92rem;font-weight:700;color:var(--tint-vif)}
#sent-trial .bl-why div + div{margin-top:0.5rem}

/* THE END-OF-TRIP SUMMARY. It WAITS — it is closed, it does not evaporate. It is the
   product's only free teaching moment: the driver has just experienced what
   it explains. The score is broken down, otherwise nothing is learned. */
#sent-summary{position:fixed;inset:0;z-index:1200;display:flex;align-items:center;justify-content:center;
  padding:1rem;background:rgba(4,8,16,.62);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}
#sent-summary[hidden]{display:none}
[data-theme="light"] #sent-summary{background:rgba(230,238,250,.72)}
.bl-card{width:100%;max-width:400px;border-radius:20px;padding:1.5rem 1.25rem 1rem;text-align:center;
  background:var(--glass-2);border:1px solid var(--brd);box-shadow:var(--sh-3)}
.bl-score{display:flex;flex-direction:column;align-items:center;line-height:1;margin-bottom:.2rem}
.bl-score b{font-size:3.5rem;font-weight:900;font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.bl-score small{font-size:.69rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-dim);margin-top:.25rem}
.bl-stats{display:flex;justify-content:center;gap:1.25rem;margin:1rem 0 1rem;font-variant-numeric:tabular-nums}
.bl-stats div{display:flex;flex-direction:column;gap:.15rem}
.bl-stats b{font-size:1.14rem;font-weight:800}
.bl-stats small{font-size:.69rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-dim)}
.bl-why{font-size:.88rem;line-height:1.5;color:var(--txt);text-align:left;
  background:var(--hi);border-radius:12px;padding:0.75rem 0.75rem}
.bl-why b{font-weight:800}
.bl-why div + div{margin-top:0.25rem}
.bl-lesson{margin-top:0.75rem;font-size:.86rem;line-height:1.45;text-align:left;
  border-left:3px solid var(--tint-vif);padding:0.5rem .75rem;border-radius:0 10px 10px 0;background:var(--hi)}
.bl-lesson[hidden]{display:none}
.bl-btn{width:100%;margin-top:1rem;min-height:52px;border:0;border-radius:14px;
  background:var(--tint);color:#fff;font-weight:800;font-size:1rem;cursor:pointer}
.bl-note{margin-top:0.75rem;font-size:.72rem;color:var(--txt-dim)}

/* THE LESSON BANNER. Discreet but permanent: while it is there, the trip goes into the
   training logbook. When it disappears, the road becomes private again — and that is visible. */
#sent-lesson-chip{position:fixed;left:50%;top:var(--haut-2);transform:translateX(-50%);
  z-index:1050;display:flex;align-items:center;gap:0.5rem;max-width:92vw;
  padding:0.25rem .75rem;border-radius:999px;font-size:.74rem;font-weight:800;white-space:nowrap;
  background:var(--glass-2);color:var(--txt);border:1px solid var(--tint-vif);
  box-shadow:0 6px 20px rgba(2,6,16,.35)}
#sent-lesson-chip[hidden]{display:none}
#sent-lesson-chip::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--tint-vif);flex:none}
#sent-lesson-chip small{font-weight:600;color:var(--txt-dim)}
/* THREE PROXIMITY LEVELS. The number grows as it approaches: the urgency is
   understood before even reading the number. And “over 2 km” moves into the background —
   two equally weighted numbers blur together in half a second. */
body.prox-2 .card-dist{font-size:1.9rem}
body.prox-3 .card-dist{font-size:2.3rem}
.card-dist .cd-over{font-size:.62em;font-weight:700;opacity:.72}

/* A THANK-YOU IS NOT AN ALERT: smaller, more restrained, it leaves sooner. */
/* The cancel button lives INSIDE the message: not another dialog to close,
   not another step across the road. It leaves by itself after eight seconds. */
.ts-annul{margin-left:0.5rem;min-height:32px;padding:.2rem 0.75rem;border:1px solid var(--brd);
  border-radius:999px;background:transparent;color:var(--tint-vif);font-weight:800;
  font-size:.82rem;cursor:pointer;pointer-events:auto}
#sent-toast:has(.ts-annul){pointer-events:auto}

#sent-toast.ts-merci{font-size:.84rem;font-weight:700;padding:0.5rem 1rem;border-color:var(--brd-soft);opacity:.94}

/* THE AGE OF A REPORT IS UNDERSTOOD WITHOUT READING. The text remains — it is the data — but
   the pill shows freshness at a glance: full for the first fifteen minutes,
   hollow after one hour. */
.card-age::before{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;
  margin-right:0.25rem;vertical-align:middle;background:currentColor;opacity:.9}
.card-age.age-moyen::before{opacity:.45}
.card-age.age-vieux::before{background:transparent;box-shadow:inset 0 0 0 1.5px currentColor;opacity:.7}

/* WHEN A QUESTION IS WAITING FOR AN ANSWER, NO MESSAGE. I had moved it up thirteen
   rem; the question card is taller, and it still fell onto it. Stop
   calculating heights: a message displayed over a question that must be
   read is noise at the worst moment. Do not move it — do not display it. */
body:has(#sent-passconfirm:not([hidden])) #sent-toast{display:none!important}
#sent-toast{position:fixed;left:50%;bottom:calc(env(safe-area-inset-bottom) + 6.4rem);transform:translate(-50%,12px);z-index:1100;max-width:88vw;padding:0.75rem 1rem;border-radius:14px;background:var(--glass-2);color:var(--txt);border:1px solid var(--brd);font-weight:700;font-size:.92rem;text-align:center;box-shadow:var(--sh-2);opacity:0;pointer-events:none;transition:opacity .28s ease, transform .28s ease}
#sent-toast.show{opacity:1;transform:translate(-50%,0)}
/* « radio de l'autoroute » suggestion: same visual family as the toast, but TAPPABLE (one tap = listen) */
#sent-radio-motorway{position:fixed;left:50%;bottom:calc(env(safe-area-inset-bottom) + 6.4rem);transform:translate(-50%,12px);z-index:1100;display:flex;align-items:center;gap:0.5rem;max-width:88vw;padding:0.75rem 1rem;border-radius:14px;background:var(--glass-2);color:var(--txt);border:1px solid var(--brd);font:inherit;font-weight:700;font-size:.92rem;text-align:left;box-shadow:var(--sh-2);opacity:0;pointer-events:none;cursor:pointer;transition:opacity .28s ease, transform .28s ease}
#sent-radio-motorway.show{opacity:1;transform:translate(-50%,0);pointer-events:auto}
#sent-radio-motorway[hidden]{display:none}
#sent-radio-motorway svg{flex:none;color:var(--s-accent)}
#sent-radio-motorway span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#sent-radio-motorway em{flex:none;font-style:normal;font-weight:800;font-size:.78rem;letter-spacing:.03em;color:#04101f;background:var(--s-accent);padding:0.25rem 0.5rem;border-radius:999px}
/* Distance badge (« ~12 km ») for stations around you */
.lib-km{font-style:normal;font-weight:700;font-size:.66rem;color:var(--s-accent);background:rgba(62,162,255,.14);border-radius:999px;padding:.08rem 0.5rem;margin-left:0.5rem;vertical-align:.08em;white-space:nowrap}
.lib-km[hidden]{display:none}
[data-theme="light"] .lib-km{background:rgba(14,116,220,.12)}
#sent-suggest{position:fixed;left:50%;bottom:calc(env(safe-area-inset-bottom) + 6.4rem);transform:translateX(-50%);z-index:1090;display:none;align-items:center;gap:0.5rem;padding:.5rem 0.5rem .5rem 1rem;border-radius:16px;background:var(--glass-2);color:var(--txt);border:1px solid var(--brd);font-weight:700;font-size:.9rem;box-shadow:0 14px 36px rgba(2,6,16,.45)}
#sent-suggest.show{display:flex}
#sent-suggest:not([hidden]){animation:cardIn .42s cubic-bezier(.2,.7,.3,1)}
#sent-suggest #suggest-yes{background:var(--tint);color:#fff;border:0;border-radius:10px;padding:.5rem 1rem;font-weight:800;font-size:.84rem;cursor:pointer}
#sent-suggest #suggest-no{background:transparent;color:var(--txt-dim);border:0;font-size:1.3rem;line-height:1;cursor:pointer;padding:0.5rem 0.5rem;min-width:44px}

/* Settings */
#sent-settings{position:fixed;inset:0;z-index:1000;display:flex;align-items:flex-start;justify-content:center;padding-top:calc(env(safe-area-inset-top) + 0.6rem);padding-bottom:calc(env(safe-area-inset-bottom) + 0.6rem)}
#sent-settings[hidden]{display:none}
body.sent-dev #sent-settings{padding-top:calc(env(safe-area-inset-top) + 0.8rem)}
.set-card{width:100%;max-width:440px;margin:1rem;max-height:86vh;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;background:var(--glass-2);border:1px solid var(--brd);border-radius:var(--r-xl);padding:1rem 1rem 1.25rem;color:var(--txt);box-shadow:var(--sh-3)}
.set-head{display:flex;align-items:center;justify-content:space-between;background:transparent;margin:-0.25rem 0 .5rem;padding:0}
.set-title{font-size:1.2rem;font-weight:800}
.set-close{border:0;background:var(--hi);color:var(--txt);width:44px;height:44px;border-radius:50%;font-size:.95rem;cursor:pointer}
/* Every close control has a 44 px hit area, with the drawing unchanged. Missing a
   cross while driving costs one more look at the screen, never less. */
.credits-close,.trips-close,#sent-sheet .sheet-title .set-close{min-width:44px;min-height:44px}
.set-row{display:flex;align-items:center;justify-content:space-between;gap:1rem;min-height:56px;padding:.75rem 0.25rem;border-top:1px solid var(--brd-soft)}
.set-row span{display:flex;flex-direction:column;min-width:0}
.set-row b{font-size:.96rem;font-weight:700}
.set-row small{font-size:.76rem;color:var(--txt-dim);margin-top:.1rem}
/* SOFT STANDBY: at night, while stopped. Reduce emitted light without hiding anything —
   the HUD remains fully readable; it only stops lighting the cabin. The
   return is instant: never any delay when the car starts moving again. */
body.soft-idle #dash-hero,body.soft-idle #sent-road,body.soft-idle #sent-radio-mini,
body.soft-idle #sent-ahead,body.soft-idle #map{opacity:.42;transition:opacity 1.2s ease}
body:not(.soft-idle) #dash-hero,body:not(.soft-idle) #sent-road{transition:opacity .12s ease}

/* Trip details open only on tap: the list remains readable at a
   glance, and the details are there when needed. */
.trip-det{display:none;margin-top:0.5rem;font-size:.78rem;line-height:1.5;color:var(--txt-dim)}
.trip-row.ouvert .trip-det{display:block}
.trip-row{cursor:pointer}
.trip-row:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(37,99,235,.35);border-radius:12px}

/* On resume, no staging: the HUD is there immediately. The entrance
   animation is a first-opening pleasure, not something forced on
   someone who is driving and has just lost their screen. */
body.reprise .dash-hero,body.reprise #sent-road,body.reprise #sent-radio-mini,
body.reprise #sent-predict{animation:none!important}

/* The STAGING badge occupied the top corner — exactly where « GPS perdu » appears.
   A development banner that hides a failure message is a trap for the
   tester. It moves to the left edge as a watermark. */
.sent-dev-banner{top:38vh!important;left:0!important;right:auto!important;bottom:auto!important;
  transform:rotate(-90deg)!important;transform-origin:0 0!important;opacity:.5!important;
  font-size:.56rem!important;padding:.1rem .5rem!important}

.boot-cost{margin-top:.5rem;text-align:center;font-size:.78rem;color:var(--txt-dim);line-height:1.4}
.qvq{margin-top:0.5rem;font-size:.82rem;line-height:1.5;color:var(--txt-dim)}
.qvq div{position:relative;padding-left:0.75rem}
.qvq div::before{content:"";position:absolute;left:0;top:.55em;width:4px;height:4px;border-radius:50%;background:var(--tint-vif)}
.qvq div + div{margin-top:0.25rem}
.qvq b{color:var(--txt);font-weight:800}
/* A collapsible subheading must LOOK collapsible: it has a chevron that
   rotates. Without a visible cue, nobody discovers that it can be touched. */
.set-sec-pliable{cursor:pointer;display:flex;align-items:center;gap:0.5rem;min-height:44px}
.set-sec-pliable::after{content:"";width:6px;height:6px;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:rotate(-45deg);transition:transform .2s ease;margin-left:auto;margin-right:.2rem}
.set-sec-pliable.ouverte::after{transform:rotate(45deg)}
.set-sec-pliable:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(37,99,235,.35);border-radius:8px}

.set-sec{font-size:.69rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-dim);margin:1rem 0 -.1rem;padding:.2rem .15rem 0}
.set-sw{appearance:none;-webkit-appearance:none;width:48px;height:28px;border-radius:999px;background:var(--hi);position:relative;cursor:pointer;flex:none;transition:background .2s;border:1px solid var(--brd-soft)}
.set-sw::after{content:'';position:absolute;top:2px;left:2px;width:22px;height:22px;border-radius:50%;background:#fff;transition:transform .2s;box-shadow:0 1px 3px rgba(0,0,0,.4)}
.set-sw:checked{background:var(--tint);border-color:transparent}
.set-sw:checked::after{transform:translateX(20px)}
#sent-theme{pointer-events:auto;width:42px;height:42px;border-radius:50%;border:1px solid var(--brd);background:var(--hi);color:var(--txt);display:flex;align-items:center;justify-content:center;cursor:pointer;flex:none}
#sent-theme svg{display:block;width:20px;height:20px}
body:not(.sent-dev) .set-row-dev{display:none}
.set-pro{display:inline-block;margin-left:0.5rem;vertical-align:middle;font-style:normal;font-size:.6rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--tint-vif);background:transparent;border:1px solid var(--tint-vif);padding:.1rem 0.5rem;border-radius:6px;flex:none}
/* A native `<select>` ignores `background` while it keeps its system appearance:
   on a dark background, WebKit rendered it WHITE with pale text, making it unreadable. Remove
   its appearance, restore the theme tokens, and draw its chevron —
   without a cue, a plain background no longer looks like something that opens. */
select.set-btn{-webkit-appearance:none;appearance:none;background-color:var(--glass-2);
  color:var(--txt);padding-right:2rem;
  background-image:linear-gradient(45deg,transparent 50%,var(--txt-dim) 50%),linear-gradient(135deg,var(--txt-dim) 50%,transparent 50%);
  background-position:calc(100% - 1.1rem) 52%,calc(100% - .75rem) 52%;
  background-size:6px 6px,6px 6px;background-repeat:no-repeat}
select.set-btn option{background:var(--glass-2);color:var(--txt)}
.set-btn.actif{background:var(--tint);border-color:var(--tint);color:#fff}
.set-btn{background:var(--hi);color:var(--txt);border:1px solid var(--brd);border-radius:10px;padding:0.5rem 1rem;font-weight:700;font-size:.9rem;cursor:pointer;flex:none}
.qual-seg{display:flex;flex-wrap:wrap;gap:.25rem;background:var(--glass-2);border-radius:12px;padding:.2rem}
.qual-seg button{flex:1 1 28%;border:0;background:transparent;color:var(--txt-dim);font-size:.8rem;font-weight:800;padding:.5rem .2rem;border-radius:9px;cursor:pointer;transition:background .2s,color .2s}
.qual-seg button.on{background:var(--tint);color:#fff}
.dm-seg{flex-wrap:wrap}
.dm-seg button{flex:1 1 30%}
#veh-heavy-row[hidden], #pl-dims-row[hidden]{display:none!important}

/* Trajets */
#sent-trips{position:fixed;inset:0;z-index:960;display:flex;align-items:center;justify-content:center;padding:1rem;background:rgba(4,8,16,.58);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}
#sent-trips[hidden]{display:none}
.trips-card{width:min(94vw,440px);max-height:calc(100dvh - 2rem);display:flex;flex-direction:column;background:var(--glass-2);border:1px solid var(--brd);border-radius:var(--r-xl);box-shadow:var(--sh-3);padding:1rem}
.trips-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:0.75rem;color:var(--txt);font-size:1.2rem;font-weight:800}
.trips-list{overflow:auto;display:flex;flex-direction:column;gap:.5rem}
.trip-row{display:flex;align-items:center;gap:0.75rem;background:var(--hi);border:1px solid var(--brd);border-radius:12px;padding:0.5rem 0.75rem}
.trip-score{font-size:1.55rem;font-weight:800;min-width:46px;text-align:center;font-variant-numeric:tabular-nums}
.trip-info{display:flex;flex-direction:column;min-width:0}
.trip-info b{color:var(--txt);font-size:.95rem}
.trip-info span{color:var(--txt-dim);font-size:.8rem}
.trips-empty{color:var(--txt-dim);text-align:center;padding:1.5rem 1rem;line-height:1.5}

/* ============================================================================
   MODES & ADAPTATIONS
   ========================================================================== */
/* AMOLED nuit */
html[data-theme="dark"].amoled{--bg1:#000;--bg2:#000;--glass:rgba(14,16,22,.72);--glass-2:rgba(6,8,12,.92)}
html.amoled #map{background:#000}
/* On OLED in the dark, a glow is not a stylistic effect: it is stray light
   reflected by the windshield. Turn off the glows, keep the strokes. */
html.amoled .sr-val,html.amoled .sr-conf,html.amoled #dash-hero.over .hero-core b{filter:none!important}
/* Eco mode: no costly blur */
html.perf-eco{--blur:none}
@media (prefers-reduced-motion: reduce){
  .limit-sign.flip,#sent-suggest:not([hidden]),.limit-sign.tick,#sent-road.swap,
  body.hud-intro .dash-hero,body.hud-intro #sent-road,body.hud-intro #sent-radio-mini,body.hud-intro #sent-predict,
  #sent-settings:not([hidden]),#sent-sheet:not([hidden]),#sent-limedit:not([hidden]),#sent-limconfirm:not([hidden]),#sent-credits:not([hidden]),#sent-ios:not([hidden]),#sent-trips:not([hidden]),
  #sent-settings:not([hidden]) .set-card,#sent-sheet:not([hidden]) .sheet-card,#sent-limedit:not([hidden]) .limedit-card,#sent-limconfirm:not([hidden]) .limedit-card,#sent-credits:not([hidden]) .credits-card,#sent-ios:not([hidden]) .ios-card,#sent-trips:not([hidden]) .trips-card,
  #sent-boot:not([hidden]) .boot-card,#sent-radio-mini .srm-tx.swap,#sent-radio-mini .srm-art.swap{animation:none!important}
  /* SAFETY PULSES DO NOT DISAPPEAR: they freeze at full
     intensity. Removing motion must never remove the signal — otherwise
     an alert is taken away from someone who only requested less animation. */
  .rail-row.near.u-hot .rail-chip,.rail-row.here .rail-chip{animation:none!important;
    box-shadow:0 14px 34px -14px rgba(2,6,16,.7),0 0 24px -10px var(--halo)!important}
  body.zone-over #sent-slowdown span,body.zone-crit #sent-slowdown span{animation:none!important;opacity:1!important}
  #sent-dashcam-rec .dc-rec-dot{animation:none!important;opacity:1!important}
}
/* Veille */
#sent-veille-overlay{display:none;position:fixed;inset:0;background:#000;opacity:.84;z-index:820;pointer-events:none;transition:opacity .35s}
html.dm-standby #sent-veille-overlay{display:block}
html.dm-standby.veille-wake #sent-veille-overlay{opacity:0}
/* Unreliable speed: grayed out */
body.speed-stale .hero-core, body.speed-stale .sent-speed, body.speed-stale #pk-spd{opacity:.42;transition:opacity .3s ease}
/* Motorcycle / Heavy vehicles / Coach: enlarged controls (gloves, cab) */
html[data-veh="moto"] #sent-report, html[data-veh="pl"] #sent-report, html[data-veh="bus"] #sent-report{width:72px;height:72px}
html[data-veh="moto"] #sent-report svg, html[data-veh="pl"] #sent-report svg, html[data-veh="bus"] #sent-report svg{width:30px;height:30px}
html[data-veh="moto"] #sent-mapctrl, html[data-veh="pl"] #sent-mapctrl, html[data-veh="bus"] #sent-mapctrl{transform:scale(1.12);transform-origin:right center}
/* Mirror HUD (windshield). Text enlargement now follows the system size (see root). */
body.hud-mirror:not(.mode-map) #sent-dash{transform:scaleX(-1)}

/* No iOS touch highlight rectangle */
#sent-dash, #sent-dash *, #sent-hud, #sent-mode, #sent-report, #sent-mapctrl button, .limit-sign, .app-tabbar *{-webkit-tap-highlight-color:transparent}

/* ── Consistent press states: slight finger depression on all round/pill controls.
   scale property (composed, does not overwrite existing transforms such as translateX(-50%)). ── */
#sent-set,#sent-info,#sent-report,#sent-mode,.set-close,.set-btn,.credits-close,#srm-name,#lim-edit,#sent-voice-cta{transition:scale .16s cubic-bezier(.2,.7,.3,1)}
#sent-set:active,#sent-info:active,.set-close:active,.set-btn:active{scale:.92}
#sent-report:active,#sent-mode:active,#srm-name:active,#lim-edit:active,.credits-close:active,#sent-voice-cta:active{scale:.96}

/* ============================================================================
   LAYOUT COORDINATION
   ========================================================================== */
:root{--tb:calc(env(safe-area-inset-top) + 3.4rem)}
body.sent-dev{--tb:calc(env(safe-area-inset-top) + 3.4rem)}   /* corner ribbon: no longer pushes the content */
#nav-bar,#nav-summary,#nav-maneuver{top:var(--tb)!important}
#sent-alert{top:var(--tb)!important}
/* THIS RULE IS UNCONDITIONAL and takes priority: it was the deciding rule, not
   the one in the base block. It sits on the stack like the others, otherwise the stack is
   useless — one hand-written value is enough to contradict it entirely. */
#sent-ahead{top:var(--haut-4)!important}
body.alerting.mode-map #nav-bar{display:none!important}
/* During an alert, the route bar disappears — « ce qui arrive devant » can therefore
   move up one step. But it moves up ON THE STACK, not to a hand-written
   value: otherwise it moves back in front of the status banner, which does not disappear. */
body.alerting.mode-map #sent-ahead{top:var(--haut-3)!important}
body.alerting.mode-map:has(#sent-status-chip:not([hidden])) #sent-ahead{top:var(--haut-4)!important}
/* toasts above the map button in cockpit mode */
body.mode-hud #lim-vote{bottom:calc(env(safe-area-inset-bottom,0px) + 7.2rem)}
body.mode-hud #sent-install{bottom:calc(env(safe-area-inset-bottom,0px) + 7.2rem)}
/* Average speed indicator (section-type control zone): never any collision.
   Copilot: the route label disappears (same position) and the HUD moves down to clear the ring.
   Carte: the search bar disappears; below the alert banner, the indicator moves down; the
   chips « sur votre route » passent en dessous. */
body.mode-hud:has(#sent-troncon:not([hidden])) #sent-road{display:none}
body.mode-hud:has(#sent-troncon:not([hidden])) #sent-dash{padding-top:calc(env(safe-area-inset-top) + 10.6rem)}
body.mode-map:has(#sent-troncon:not([hidden])) #nav-bar{display:none!important}
body.mode-map:has(#sent-alert:not([hidden])) #sent-troncon{top:calc(var(--tb) + 4.9rem)}
body.mode-map:has(#sent-troncon:not([hidden])) #sent-ahead{top:calc(var(--tb) + 11.6rem)!important}
/* An after-passage question temporarily replaces the secondary information in
   the same reading area. The instruments, limit, alerts and control remain present. */
body:has(#sent-passconfirm:not([hidden])) :is(#sent-radio-mini,#sent-predict,#sent-ahead,#sent-status-chip){display:none!important}
body:has(#sent-passconfirm:not([hidden])) #sent-mode{z-index:602}
body.mode-hud:has(#sent-predict .rail) #sent-radio-mini{display:none!important}
/* Safety banners take the top step; technical status returns as soon as they leave. */
body:has(#sent-troncon:not([hidden])) #sent-status-chip,
body:has(#sent-renforcee:not([hidden])) #sent-status-chip,
body:has(#sent-toast.show) #sent-status-chip,
body:is(.zone-over,.zone-crit) #sent-status-chip,
body.mode-hud:has(#sent-card:not([hidden])) #sent-status-chip,
body:has(#sent-troncon:not([hidden])) #sent-top,
body:has(#sent-renforcee:not([hidden])) #sent-top{display:none!important}
body:is(.zone-over,.zone-crit) #sent-toast,
body.mode-map:is(.zone-over,.zone-crit) #sent-mapctrl{display:none!important}
/* On the map, the reinforced zone and alert stack instead of occupying the same step. */
body.mode-map:has(#sent-renforcee:not([hidden])) #nav-bar{display:none!important}
body.mode-map:has(#sent-renforcee:not([hidden])) #sent-alert{top:calc(var(--tb) + 4.5rem)!important}
body.mode-map:has(#sent-alert:not([hidden])) #sent-ahead,
body.mode-map:has(#sent-troncon:not([hidden])) #sent-ahead{display:none!important}
/* pop-up ouvert = seul au premier plan */
body:is(:has(#sent-sheet:not([hidden])),:has(#sent-limedit:not([hidden])),:has(#sent-limconfirm:not([hidden])),:has(#sent-credits:not([hidden])),:has(#sent-ios:not([hidden])),:has(#sent-settings:not([hidden])),:has(#sent-player:not([hidden]))) :is(#sent-top,#sent-mapctrl,#sent-report,#sent-mode,#sent-hud,#sent-ahead,#sent-credit,#nav-bar,#nav-summary,#nav-maneuver,.dash-hero){display:none!important}

/* Small screens / notch: everything fits, nothing is cut off */
@media (max-height: 740px){
  #sent-dash{padding-top:calc(env(safe-area-inset-top) + 1rem);gap:0.5rem}
  body.mode-hud #sent-slowdown{padding-bottom:calc(env(safe-area-inset-bottom) + 10vh)}
  #sent-slowdown span{font-size:clamp(1.7rem,7.5vw,2.4rem);padding:.75rem 1.25rem;border-radius:22px}
  /* 80 vw let the speed pill leave the screen on the left: it is
     111 px wide and its center sits ON the arc, so it needs a 55 px margin. And on a page
     under 640 px, the dial must yield to what it announces — otherwise the alert
     tile ends up on the buttons. Measured figures, not estimates. */
  .dash-hero{width:min(74vw,320px,34vh);height:min(74vw,320px,34vh);margin-top:clamp(1rem,5vh,2.5rem)}
  #sent-dash{padding-bottom:calc(env(safe-area-inset-bottom) + 4.6rem)}
  .rail{gap:0.5rem}
  .rail-row.near .rail-d{font-size:1.4rem}
  .rail-row.here .rail-d{font-size:1.6rem}
  .rail-row.near .rail-ic{width:30px;height:30px}
  .rail-row.here .rail-ic{width:34px;height:34px}
}


/* Compact music player (Copilot view, below the dial) ---- */
#sent-radio-mini{position:relative;display:none;align-items:center;gap:.1rem;max-width:min(88vw,340px);padding:0.25rem;border-radius:999px;
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);border:1px solid var(--brd);box-shadow:var(--shadow)}
body.mode-hud #sent-radio-mini:not([hidden]){display:flex}
body.mode-map #sent-radio-mini, body.alerting #sent-radio-mini{display:none!important}
/* ON A SHORT SCREEN, THE player is hidden, never the driving instruments. A
   radio that cannot be seen costs a song; a speed that cannot be seen costs something
   else. It remains accessible in full screen.
   740 px is the usable page of an iPhone in Safari: the panel is 932 px, the two
   browser bars take about 210 away. */
@media (max-height: 740px){ body.mode-hud #sent-radio-mini{display:none!important} }
/* « limite signalée — correcte ? » card displayed: the player is hidden (same exclusion as
   during an alert) -> never any radio / vote card collision (observed in QA at 390x844). */
body:has(#lim-vote:not([hidden])) #sent-radio-mini{display:none!important}
body:is(:has(#sent-sheet:not([hidden])),:has(#sent-limedit:not([hidden])),:has(#sent-limconfirm:not([hidden])),:has(#sent-credits:not([hidden])),:has(#sent-ios:not([hidden])),:has(#sent-settings:not([hidden])),:has(#sent-player:not([hidden]))) #sent-radio-mini{display:none!important}
#sent-radio-mini > button{display:flex;align-items:center;justify-content:center;flex:none;border:0;background:transparent;color:var(--txt);cursor:pointer;padding:0;border-radius:999px}
#sent-radio-mini svg{display:block}
#srm-prev,#srm-next{width:32px;height:32px;color:var(--txt-dim)}
#srm-prev:active,#srm-next:active{color:var(--txt);transform:scale(.92)}
#srm-toggle{width:38px;height:38px;background:var(--s-accent);color:#04101f;box-shadow:0 4px 14px rgba(62,162,255,.4);margin-right:.15rem;transition:transform .15s,box-shadow .3s}
#srm-toggle:active{transform:scale(.92)}
#sent-radio-mini.on #srm-toggle{box-shadow:0 4px 18px rgba(62,162,255,.55)}
#sent-radio-mini .srm-ic-pause{display:none}
#sent-radio-mini.on .srm-ic-pause{display:block}
#sent-radio-mini.on .srm-ic-play{display:none}
/* Station chip: cover (logo, tinted initials fallback) + name + “playing” equalizer */
#srm-name{flex:0 1 auto!important;min-width:0;max-width:13rem;display:flex;align-items:center;gap:.5rem;justify-content:flex-start;
  padding:.14rem 0.5rem .14rem .16rem;text-align:left}
.srm-art{position:relative;flex:none;width:32px;height:32px;border-radius:50%;overflow:hidden;border:1px solid var(--brd);background:var(--glass-2)}
.srm-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:4px;background:#fff;box-sizing:border-box}
.srm-art img[hidden]{display:none}
.srm-ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#fff;font-size:.68rem;font-weight:800;letter-spacing:.02em}
#sent-radio-mini.on .srm-art{border-color:rgba(62,162,255,.55);box-shadow:0 0 10px rgba(62,162,255,.35)}
.srm-tx{min-width:0;display:flex;align-items:center;gap:0.5rem}
#srm-stname{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.78rem;font-weight:700;letter-spacing:.01em;color:var(--txt)}
#sent-radio-mini.on #srm-stname{color:var(--s-accent)}
/* equalizer: three bars that dance while playing, still while paused */
.srm-eq{flex:none;display:none;align-items:flex-end;gap:2px;height:12px}
#sent-radio-mini.on .srm-eq{display:flex}
.srm-eq i{width:2.5px;height:4px;border-radius:2px;background:var(--s-accent)}
#sent-radio-mini.on .srm-eq i{animation:srm-eq 1.05s ease-in-out infinite}
.srm-eq i:nth-child(2){animation-delay:.22s}
.srm-eq i:nth-child(3){animation-delay:.48s}
.srm-eq i:nth-child(4){animation-delay:.12s}
/* slightly desynchronised durations: the equaliser breathes instead of marching in step */
#sent-radio-mini.on .srm-eq i:nth-child(1){animation-duration:.94s}
#sent-radio-mini.on .srm-eq i:nth-child(2){animation-duration:1.18s}
#sent-radio-mini.on .srm-eq i:nth-child(3){animation-duration:.87s}
#sent-radio-mini.on .srm-eq i:nth-child(4){animation-duration:1.31s}
@keyframes srm-eq{0%,100%{height:4px}30%{height:12px}60%{height:6px}80%{height:10px}}
/* Station change: cover + name slide and fade (class applied by app.js) */
@keyframes stSwap{from{opacity:0;transform:translateX(7px)}to{opacity:1;transform:none}}
#sent-radio-mini .srm-tx.swap{animation:stSwap .4s cubic-bezier(.22,.9,.32,1)}
#sent-radio-mini .srm-art.swap{animation:stSwap .4s cubic-bezier(.22,.9,.32,1) .05s both}
@media (prefers-reduced-motion: reduce){.srm-eq i{animation:none!important;height:7px}}
#sent-radio-mini.ext #srm-prev,#sent-radio-mini.ext #srm-toggle,#sent-radio-mini.ext #srm-next,#sent-radio-mini.ext .srm-art,#sent-radio-mini.ext .srm-eq{display:none}
#sent-radio-mini.ext{padding:0.25rem 0.25rem 0.25rem .5rem}
#srm-open{flex:none;font-size:.72rem;font-weight:800;color:#04101f;background:var(--s-accent);border-radius:999px;padding:0.25rem 0.75rem;text-decoration:none}
#srm-open[hidden]{display:none}

/* ═══════ Full-screen radio player (#sent-player) — immersive azure/glass ═══════
   Opened by tapping the station in the mini-player. Close with: ✕ button, tap on
   the veil, downward swipe. transform/opacity only (GPU, ~60 fps). */
#sent-player{position:fixed;inset:0;z-index:1100;display:flex;align-items:flex-end;justify-content:center;
  background:rgba(4,8,16,.42);backdrop-filter:blur(18px) saturate(1.12);-webkit-backdrop-filter:blur(18px) saturate(1.12)}
#sent-player[hidden]{display:none}
#sent-player:not([hidden]){animation:veilIn .26s ease}
#sent-player.closing{animation:spVeilOut .22s ease both}
@keyframes spVeilOut{to{opacity:0}}
.player-card{position:relative;width:min(100vw,520px);height:min(94dvh,860px);display:flex;flex-direction:column;overflow:hidden;
  padding:.4rem 1.1rem calc(env(safe-area-inset-bottom) + .8rem);border-radius:28px 28px 0 0;
  background:linear-gradient(180deg, rgba(62,162,255,.10), transparent 34%), var(--glass-2);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  border:1px solid var(--brd);border-bottom:0;box-shadow:0 -18px 60px rgba(2,6,16,.55);
  will-change:transform;touch-action:pan-y}
#sent-player:not([hidden]) .player-card{animation:spCardIn .44s cubic-bezier(.22,1.12,.34,1)}
#sent-player.closing .player-card{animation:spCardOut .24s ease both}
@keyframes spCardIn{from{transform:translateY(9%);opacity:.6}to{transform:none;opacity:1}}
@keyframes spCardOut{to{transform:translateY(12%);opacity:0}}
.player-card.drag{animation:none!important;transition:none!important}
.player-card.settle{transition:transform .3s cubic-bezier(.22,1.12,.34,1)}
.player-grip{display:flex;justify-content:center;padding:0.5rem 0 .2rem;cursor:grab}
.player-grip i{width:42px;height:5px;border-radius:999px;background:var(--track)}
.player-close{position:absolute;top:.85rem;right:.85rem;z-index:3}
/* ── Hero: large cover + identity + current track ── */
.player-hero{flex:none;display:flex;flex-direction:column;align-items:center;text-align:center;padding:0.25rem 0 .2rem}
.player-art{position:relative;width:clamp(96px,30vw,148px);aspect-ratio:1;border-radius:30px;overflow:hidden;flex:none;
  border:1px solid var(--brd);background:var(--glass);box-shadow:0 16px 44px rgba(2,6,16,.45),0 0 0 6px rgba(62,162,255,.07)}
.player-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:16%;background:#fff;box-sizing:border-box}
.player-art img[hidden]{display:none}
.player-ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#fff;font-size:2rem;font-weight:800;letter-spacing:.02em}
body.radio-on .player-art{border-color:rgba(62,162,255,.5);box-shadow:0 16px 44px rgba(2,6,16,.45),0 0 26px rgba(62,162,255,.30)}
.player-name-row{display:flex;align-items:center;gap:0.5rem;margin-top:0.75rem;max-width:100%}
#spl-stname{font-size:1.35rem;font-weight:800;letter-spacing:.01em;color:var(--txt);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#spl-fav{flex:none;border:0;background:transparent;color:var(--txt-dim);width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:color .2s,transform .16s}
#spl-fav:active{transform:scale(.9)}
#spl-fav[aria-pressed="true"]{color:var(--s-accent)}
#spl-fav[aria-pressed="true"] .hz{fill:currentColor}
.player-genre{font-size:.78rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--txt-dim);margin-top:.15rem}
/* Current track (ICY metadata, if broadcast by the station): fade on change */
.player-np{display:flex;align-items:center;justify-content:center;gap:.5rem;margin-top:0.5rem;min-height:1.25rem;max-width:92%;opacity:0;transition:opacity .35s}
.player-np.show{opacity:1}
#spl-np-txt{font-size:.9rem;font-weight:700;color:var(--txt);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.player-np.swap #spl-np-txt{animation:stSwap .45s cubic-bezier(.22,.9,.32,1)}
.np-eq{flex:none;display:flex;align-items:flex-end;gap:2px;height:11px}
.np-eq i{width:2.5px;height:4px;border-radius:2px;background:var(--s-accent)}
body.radio-on .np-eq i{animation:srm-eq 1.05s ease-in-out infinite}
body.radio-on .np-eq i:nth-child(2){animation-delay:.24s;animation-duration:1.2s}
body.radio-on .np-eq i:nth-child(3){animation-delay:.5s;animation-duration:.9s}
/* Discreet message (station unreachable…) — never a harsh error */
.player-msg{margin-top:.5rem;font-size:.78rem;font-weight:700;color:var(--s-warn)}
.player-msg[hidden]{display:none}
/* ── Large touch controls ── */
.player-ctrl{flex:none;display:flex;align-items:center;justify-content:center;gap:1.5rem;padding:1rem 0 .2rem}
#spl-prev,#spl-next{width:58px;height:58px;border:0;border-radius:50%;background:var(--hi);color:var(--txt);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .15s}
#spl-prev:active,#spl-next:active{transform:scale(.92)}
#spl-toggle{position:relative;width:78px;height:78px;border:0;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;
  color:#04101f;background:var(--tint);box-shadow:0 10px 30px rgba(62,162,255,.42);transition:transform .15s,box-shadow .3s}
#spl-toggle:active{transform:scale(.94)}
body.radio-on #spl-toggle{box-shadow:0 10px 36px rgba(62,162,255,.58)}
#spl-toggle .spl-ic-pause{display:none}
body.radio-on #spl-toggle .spl-ic-pause{display:block}
body.radio-on #spl-toggle .spl-ic-play{display:none}
/* Buffering: spinning ring IN PLACE of the icons (state visible at a glance) */
.spl-spin{display:none;width:30px;height:30px;border-radius:50%;border:3.5px solid rgba(4,16,31,.25);border-top-color:#04101f;animation:spSpin .8s linear infinite}
@keyframes spSpin{to{transform:rotate(360deg)}}
body.radio-buf #spl-toggle .spl-ic-play,body.radio-buf #spl-toggle .spl-ic-pause{display:none}
body.radio-buf #spl-toggle .spl-spin{display:block}
body.radio-buf #srm-toggle .srm-ic-play,body.radio-buf #srm-toggle .srm-ic-pause{display:none}
.srm-spin{display:none;width:15px;height:15px;border-radius:50%;border:2.5px solid rgba(4,16,31,.25);border-top-color:#04101f;animation:spSpin .8s linear infinite}
body.radio-buf #srm-toggle .srm-spin{display:block}
/* ── Volume (min = true silence) ── */
.player-vol{flex:none;display:flex;align-items:center;gap:0.75rem;padding:.75rem 0.5rem 0.5rem;color:var(--txt-dim)}
.player-vol svg{flex:none}
#srm-vol{flex:1;min-width:0;accent-color:var(--s-accent);height:26px}
/* ── Library: search + categories + stations (favorites pinned at the top) ── */
.player-lib{flex:1;min-height:0;display:flex;flex-direction:column;gap:0.5rem;margin-top:0.5rem;padding-top:0.75rem;border-top:1px solid var(--brd-soft)}
.lib-search{flex:none;display:flex;align-items:center;gap:0.5rem;padding:.15rem 0.75rem;border-radius:14px;background:var(--hi);border:1px solid var(--brd-soft);color:var(--txt-dim)}
#spl-search{flex:1;min-width:0;border:0;background:transparent;color:var(--txt);font-size:.9rem;font-weight:600;padding:0.5rem 0;outline:none;-webkit-appearance:none;appearance:none}
#spl-search::placeholder{color:var(--txt-dim);opacity:.75}
#spl-search::-webkit-search-cancel-button{-webkit-appearance:none}
.lib-cats{flex:none;display:flex;gap:0.5rem;overflow-x:auto;scrollbar-width:none;padding-bottom:.1rem;-webkit-overflow-scrolling:touch}
.lib-cats::-webkit-scrollbar{display:none}
.lib-cats button{flex:none;border:1px solid var(--brd-soft);background:var(--hi);color:var(--txt-dim);font-size:.76rem;font-weight:800;letter-spacing:.01em;padding:0.5rem 0.75rem;border-radius:999px;cursor:pointer;white-space:nowrap;transition:background .2s,color .2s,border-color .2s}
.lib-cats button.on{background:var(--tint);border-color:transparent;color:#fff}
#srm-list{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;display:flex;flex-direction:column;padding:.1rem .1rem 0.25rem}
.lib-group{flex:none;font-size:.68rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--txt-dim);padding:0.5rem .5rem 0.25rem}
.lib-group[hidden]{display:none}
.lib-row{flex:none;display:flex;align-items:center;gap:.15rem;border-radius:14px}
.lib-row[hidden]{display:none}
.lib-main{flex:1;min-width:0;display:flex;align-items:center;gap:0.75rem;border:0;background:transparent;color:var(--txt);text-align:left;padding:.5rem .5rem;border-radius:14px;cursor:pointer;-webkit-tap-highlight-color:transparent}
.lib-main:active{background:var(--hi)}
.lib-ph{flex:none;width:36px;height:36px;border-radius:12px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:.72rem;font-weight:800;letter-spacing:.02em;background:hsl(210,52%,44%)}
.lib-tx{flex:1;min-width:0;display:flex;flex-direction:column}
.lib-tx b{font-size:.88rem;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lib-tx small{font-size:.72rem;color:var(--txt-dim);margin-top:.05rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lib-eq{flex:none;display:none;align-items:flex-end;gap:2px;height:12px;margin-right:.15rem}
.lib-eq i{width:2.5px;height:4px;border-radius:2px;background:var(--s-accent)}
.lib-row.on .lib-eq{display:flex}
body.radio-on .lib-row.on .lib-eq i{animation:srm-eq 1.05s ease-in-out infinite}
body.radio-on .lib-row.on .lib-eq i:nth-child(2){animation-delay:.24s;animation-duration:1.2s}
body.radio-on .lib-row.on .lib-eq i:nth-child(3){animation-delay:.5s;animation-duration:.9s}
.lib-row.on{background:rgba(62,162,255,.14)}
.lib-row.on .lib-tx b{color:var(--s-accent)}
.lib-fav{flex:none;width:42px;height:42px;border:0;background:transparent;color:var(--txt-dim);opacity:.7;display:flex;align-items:center;justify-content:center;border-radius:50%;cursor:pointer;transition:color .2s,transform .16s;-webkit-tap-highlight-color:transparent}
.lib-fav:active{transform:scale(.88)}
.lib-fav[aria-pressed="true"]{color:var(--s-accent);opacity:1}
.lib-fav[aria-pressed="true"] .hz{fill:currentColor}
@media (prefers-reduced-motion: reduce){
  #sent-player:not([hidden]),#sent-player:not([hidden]) .player-card,#sent-player.closing,#sent-player.closing .player-card{animation:none!important}
  .player-np.swap #spl-np-txt{animation:none!important}
  .np-eq i,.lib-eq i{animation:none!important;height:7px}
}

/* ---- Incitation « activer la voix » (jusqu'au premier geste) ---- */
#sent-voice-cta{position:fixed;top:calc(env(safe-area-inset-top) + .6rem);left:50%;transform:translateX(-50%);z-index:555;display:flex;align-items:center;gap:.5rem;
  border:1px solid var(--brd);border-radius:999px;padding:.5rem 1rem;background:var(--glass-2);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  color:var(--txt);font-size:.8rem;font-weight:700;box-shadow:var(--shadow);cursor:pointer;max-width:92vw;white-space:nowrap}
#sent-voice-cta[hidden]{display:none}
#sent-voice-cta svg{color:var(--s-accent);flex:none}
#sent-voice-cta span{overflow:hidden;text-overflow:ellipsis}
/* Engaging but discreet reminder: slight azure breathing until voice is unlocked */
#sent-voice-cta{animation:vcta-breathe 2.6s ease-in-out infinite}
@keyframes vcta-breathe{0%,100%{box-shadow:var(--shadow),0 0 0 0 rgba(62,162,255,.34)}50%{box-shadow:var(--shadow),0 0 0 7px rgba(62,162,255,0)}}
@media (prefers-reduced-motion: reduce){#sent-voice-cta{animation:none}}

/* Start screen: one gesture = permissions + voice (restrained, azure, glass) ---- */
#sent-boot{position:fixed;inset:0;z-index:940;display:flex;align-items:center;justify-content:center;
  padding:max(1rem, env(safe-area-inset-top)) 1rem max(1rem, env(safe-area-inset-bottom));
  background:linear-gradient(180deg, var(--bg1), var(--bg2));transition:opacity .45s ease}
#sent-boot[hidden]{display:none}
#sent-boot.boot-out{opacity:0;pointer-events:none}
/* Polished entrance/exit: the card lands with a soft spring, then fades with a slight retreat */
#sent-boot:not([hidden]) .boot-card{animation:cardPop .5s cubic-bezier(.22,1.14,.34,1) backwards}   /* backwards (not both): the animation hands back to the exit transition */
#sent-boot .boot-card{transition:opacity .4s ease,transform .45s ease}
#sent-boot.boot-out .boot-card{opacity:0;transform:scale(.97)}
.boot-card{width:min(92vw,420px);max-height:calc(100vh - 2rem);overflow-y:auto;display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:1.5rem 1.25rem 1.25rem;border-radius:var(--r-xl);border:1px solid var(--brd);
  background:var(--glass);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);box-shadow:var(--shadow)}
.boot-mark{width:58px;height:58px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--s-accent);
  background:radial-gradient(circle closest-side, rgba(62,162,255,.16) 0 72%, rgba(62,162,255,.05) 72% 100%);
  border:1px solid rgba(62,162,255,.28)}
.boot-title{margin:0.75rem 0 0;font-size:1.3rem;font-weight:800;letter-spacing:.01em;color:var(--txt)}
.boot-sub{margin:0.5rem 0 0;font-size:.83rem;line-height:1.45;color:var(--txt-dim);max-width:30ch}
.boot-perms{list-style:none;margin:1rem 0 0;padding:0;width:100%;display:flex;flex-direction:column;gap:0.5rem;text-align:left}
.boot-perms li{display:flex;align-items:center;gap:0.75rem;padding:0.5rem .75rem;border-radius:13px;
  border:1px solid var(--brd-soft);background:var(--hi)}
.boot-perms li>svg{flex:none;color:var(--s-accent)}
.boot-perms li>div{min-width:0;flex:1}
.boot-perms b{display:block;font-size:.8rem;font-weight:800;color:var(--txt)}
.boot-perms span{display:block;font-size:.7rem;line-height:1.35;color:var(--txt-dim)}
/* State by permission: neutral dot -> green (granted) / crossed-out gray (denied = feature disabled, nothing breaks) */
.bp-dot{flex:none;width:9px;height:9px;border-radius:50%;background:var(--track);transition:background .25s,box-shadow .25s}
.boot-perms li[data-etat="ok"] .bp-dot{background:var(--s-ok);box-shadow:0 0 7px rgba(48,212,124,.55)}
.boot-perms li[data-etat="ok"]{border-color:rgba(48,212,124,.3)}
/* “on demand”: neither granted nor denied — permission will be requested when
   the function uses it (the microphone at startup cut off the user's music). */
.boot-perms li[data-etat="later"] .bp-dot{background:transparent;border:1.5px dashed var(--txt-dim);opacity:.8}
.boot-perms li[data-etat="off"] .bp-dot{background:transparent;border:1.5px solid var(--txt-dim);opacity:.6}
.boot-perms li[data-etat="off"]{opacity:.62}
#boot-go{margin-top:1.25rem;width:100%;padding:0.75rem 1rem;border:0;border-radius:14px;cursor:pointer;
  font-size:.95rem;font-weight:800;letter-spacing:.01em;color:#fff;
  background:var(--tint);box-shadow:0 10px 26px rgba(62,162,255,.35);
  transition:transform .15s ease,box-shadow .25s,opacity .25s;-webkit-tap-highlight-color:transparent}
#boot-go:active{transform:scale(.98)}
#boot-go:disabled{opacity:.72;cursor:default}
#boot-skip{margin-top:0.5rem;background:none;border:0;padding:.5rem 0.75rem;cursor:pointer;
  font-size:.76rem;font-weight:700;color:var(--txt-dim);-webkit-tap-highlight-color:transparent}
#boot-skip:active{opacity:.7}

/* ── Reliability: discreet status pill (GPS signal lost / data frozen) ──
   Overlaid at the top, below the road name pill; never interactive, never loud. */
/* In MAP mode, the route bar already occupies this strip. The status banner
   moves below it: two overlapping messages do not make one, they make zero. */
body.mode-map #sent-status-chip{top:var(--haut-3)}
#sent-status-chip{position:fixed;left:50%;top:var(--haut-2);transform:translateX(-50%);z-index:588;
  font-size:12px;font-weight:600;line-height:1.15;letter-spacing:.03em;color:var(--txt-dim);
  background:var(--glass-2);border:1px solid var(--brd-soft);border-radius:var(--r-s);
  padding:0.35rem 0.75rem;pointer-events:none;white-space:nowrap;
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur)}
#sent-status-chip[hidden]{display:none}
/* THREE ELEMENTS FOUGHT OVER THE TOP OF THE SCREEN with nothing organizing them:
   the road name, status banner and lesson banner. They were written
   over each other — invisible in map mode, where the road name is hidden, so the
   defect appeared ONLY in the driving view.
   The stack is declared here instead of controlled from code: the stylesheet
   OBSERVES what is present; it has nothing to synchronize. */
body:has(#sent-status-chip:not([hidden])) #sent-lesson-chip{top:var(--haut-3)}
body.gps-lost #sent-status-chip{color:#ffd9a8;border-color:rgba(255,190,120,.28)}


/* ── “Extended control zone” icon (average speed section) ── */
.tr-ic{display:inline-flex;vertical-align:-3px;margin-right:0.25rem}
.tr-ic svg{width:15px;height:15px}

/* ── Enhanced control zone (video enforcement / route): persistent azure banner ── */
#sent-renforcee{position:fixed;top:calc(env(safe-area-inset-top) + 3rem);left:50%;transform:translateX(-50%);
  z-index:589;width:min(92vw,340px);display:flex;align-items:center;gap:0.5rem;pointer-events:none;
  background:var(--glass-2);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  border:1px solid var(--brd);border-top:3px solid #1e9fe0;color:var(--txt);
  border-radius:var(--r-l);padding:0.5rem 1rem;box-shadow:var(--sh-1)}
#sent-renforcee[hidden]{display:none}
#sent-renforcee.rf-enter{animation:trIn .4s cubic-bezier(.2,.7,.3,1)}
.rf-ic{flex:none;display:inline-flex}
.rf-ic svg{width:30px;height:30px}
.rf-tx{display:flex;flex-direction:column;line-height:1.15;min-width:0}
.rf-tx b{font-size:.95rem;font-weight:800;color:var(--txt)}
.rf-tx em{font-style:normal;font-size:.75rem;font-weight:700;letter-spacing:.02em;color:var(--txt-dim)}

/* ── Centralized consent (start screen) ── */
.boot-consent{margin:1rem 0 0;font-size:.72rem;line-height:1.42;color:var(--txt-dim);text-align:left}
.boot-consent b{color:var(--txt);font-weight:700}

/* ═══ LANDSCAPE MODE — consent screen (rendering verified in WebKit) ═══ */
@media (orientation: landscape) and (max-height: 560px) {
  #sent-boot { align-items: flex-start !important; overflow-y: auto !important; -webkit-overflow-scrolling: touch; padding:10px 12px !important; }
  #sent-boot ul { display: grid !important; grid-template-columns: 1fr 1fr !important; gap:6px; margin:8px 0; }
  #sent-boot ul li { padding:7px 9px; }
  #sent-boot .boot-consent { font-size: .72rem; line-height: 1.35; margin:8px 0; }
  #boot-go { margin-top:0.5rem; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   LANDSCAPE — HUD in COCKPIT (Julien's choice 17/07: ring on the left)
   ------------------------------------------------------------------------------
   The portrait HUD is a centered COLUMN. In landscape, three defects:
     1. the ring is sized from the WIDTH (94vw capped at 430px) -> on a
        430px-high screen it takes the WHOLE height, + margin-top -> CLIPPED;
     2. About 500px of width remain empty while everything stacks in the center;
     3. the banners (install/toast), centered on the screen, overlap.
   Here: ring on the LEFT sized from the HEIGHT, information + controls on the RIGHT.
   NEVER use transform:scale — that is what made everything overlap during
   the 1st attempt. Real layout (grid), verified in the WebKit rendering.
   Targeted by body classes: #sent-dash has NO inline style (it is controlled by
   `body.mode-hud`/`body.mode-map`) -> no !important, so there is no risk of
   forcing it visible when it must be hidden.
   ══════════════════════════════════════════════════════════════════════════════ */
@media (orientation: landscape) and (max-height: 560px) {

  /* Ring side = available height (bounded by width on a very
     short screen). Set on `body`: the banners, which live OUTSIDE #sent-dash,
     need it to sit to the right of the ring. */
  body { --anneau: min(76vh, 36vw, 328px); }

  /* ── 2 columns: left RESERVED for the ring, right = everything else ── */
  body.mode-hud #sent-dash {
    display: grid;
    grid-template-columns: calc(var(--anneau) + 1.5rem) minmax(0, 1fr);
    align-content: center;
    justify-items: center;
    padding:.75rem 1rem;
    gap:0.5rem 1.25rem;
  }
  body.mode-hud #sent-dash > * { grid-column: 2; max-width: 100%; }

  /* ── The ring: out of flow, fixed to the left, vertically centered explicitly.
     Its position therefore does NOT depend on the right column (often empty: no road
     name or alert). `grid-column:auto` is ESSENTIAL: an absolute child
     of a grid is positioned within ITS CELL — without it, `left` would start from the
     edge of column 2 and the ring would land on the information. ── */
  body.mode-hud #sent-dash > .dash-hero {
    grid-column: auto;
    position: absolute;
    left: 2.35rem;
    top: calc((100% - var(--anneau)) / 2);
    width: var(--anneau);
    height: var(--anneau);
    margin:0;
  }

  body.mode-hud #sent-dash > #sent-card { width: 100%; }
  body.mode-hud #sent-dash > #sent-road { max-width: 100%; }

  /* The alert tile takes 100% of column 2, THEN body.alert-active applies
     scale(1.09): it needs a 24 px margin on each side with 14.4 px of available padding
     -> it overflowed by 7.7 px on the right (rounded corner clipped). Reduce the
     base width so the alert enlargement fits inside the screen. */
  body.mode-hud.alerting #sent-dash > #sent-card { width: 90%; }
  body.mode-hud.alert-active #sent-dash > #sent-card { width: 68%; }

  /* ── Limit Dialogs in LANDSCAPE ─────────────────────────────────────────────
     They live at the <body> level (outside #sent-dash) and had NO landscape
     adaptation: the card was 516 px high inside 430 px -> title clipped at the top,
     `Annuler` clipped at the bottom, with no scrolling to reach it. Widen the
     card (the landscape screen is 932 px wide, so there is room), switch the grid to
     5 columns in it -> 2 rows instead of 3, while keeping overflow as a safeguard. ── */
  .limedit-card { max-width: min(96vw, 720px); padding:0.5rem 1rem;
    max-height: calc(100vh - .8rem); overflow-y: auto; -webkit-overflow-scrolling: touch; }
  .limedit-title { font-size: 1.05rem; margin-bottom:.5rem; }
  .limedit-grid { gap:.5rem 2.5%; }
  .limedit-grid button { flex: 0 0 20%; font-size: 9.4cqi; }
  .limedit-cancel { margin-top:0.5rem; padding:0.75rem; }

  /* Carte button: centered, it landed in the right column -> to the left of the
report button. */
  body.mode-hud #sent-mode { left: auto; right: 5.6rem; transform: none; }

  /* The confirmation lives in the right reading lane, above the two bottom
     controls. It no longer crosses the instrument and stays entirely within the height. */
  body.mode-hud #sent-passconfirm {
    left:auto;right:1rem;transform:none;
    width:min(calc(100vw - var(--anneau) - 3.25rem),430px);
    bottom:calc(env(safe-area-inset-bottom,0px) + 5.8rem);
  }
  body.mode-hud #sent-passconfirm .lv-card{padding:.75rem}
  body.mode-hud #sent-passconfirm .lv-head{margin-bottom:.6rem}
  body.mode-hud #sent-passconfirm .lv-actions button{min-height:56px}
  body.mode-hud:has(#sent-passconfirm:not([hidden])) #sent-road{display:none!important}

  body.mode-map #sent-passconfirm{
    left:auto;right:5.6rem;transform:none;
    width:min(54vw,430px);bottom:calc(env(safe-area-inset-bottom,0px) + 1rem);
  }
  body.mode-map #sent-passconfirm .lv-card{padding:.75rem}
  body.mode-map #sent-passconfirm .lv-head{margin-bottom:.6rem}
  body.mode-map #sent-passconfirm .lv-actions button{min-height:56px}

  /* Trip-related banners are confined to the same right lane. */
  body.mode-hud #sent-troncon,
  body.mode-hud #sent-renforcee{
    left:auto;right:1rem;transform:none;
    width:min(calc(100vw - var(--anneau) - 3.25rem),340px);
    top:calc(env(safe-area-inset-top) + .75rem);
  }

  /* In Map, the view selector joins the bottom row and leaves the vertical
     column of map controls. */
  body.mode-map #sent-mode{
    left:auto;right:5.6rem;bottom:calc(env(safe-area-inset-bottom) + 1rem);transform:none;
  }

  /* The slow-down instruction occupies the right lane, below the alert card. The
     panel and its target stay outside the instrument and fully on screen. */
  body.mode-hud #sent-slowdown{
    justify-content:flex-start;
    padding:0 0 calc(env(safe-area-inset-bottom) + 3.8rem) calc(var(--anneau) + 4.5rem);
  }
  body.mode-hud:is(.zone-over,.zone-crit) #sent-road{display:none!important}
  body.mode-hud:is(.zone-over,.zone-crit) #sent-dash > #sent-card{
    position:fixed;left:calc(var(--anneau) + 5.75rem);right:1.5rem;top:calc(env(safe-area-inset-top) + 10rem);
    width:auto;max-width:none;margin:0;transform:none;
  }
  body.mode-map #sent-slowdown{align-items:flex-end;padding-bottom:calc(env(safe-area-inset-bottom) + 3.8rem)}

  /* ── Banners: centred on the SCREEN (left:50% + translateX(-50%)), they
     crossed the ring -> confined to the right column. The selector must
     include `body.mode-hud`: a rule with this specificity already exists for
     #sent-install (otherwise it wins and nothing moves). ── */
  body.mode-hud #sent-install {
    left: auto;
    right: 1rem;
    transform: none;
    max-width: calc(100vw - var(--anneau) - 3rem);
  }
  /* The toast landed EXACTLY on the installation banner -> placed at the bottom of the
     right column, bounded so it cannot reach the Carte button. */
  body.mode-hud #sent-toast {
    left: calc(var(--anneau) + 3.3rem);
    right: auto;
    bottom: calc(env(safe-area-inset-bottom) + .8rem);
    max-width: calc(100vw - var(--anneau) - 17.5rem);
    transform: translateY(12px);
  }
  body.mode-hud #sent-toast.show { transform: translateY(0); }
  /* Status pill (“GPS signal lost” / “Data frozen”): centered on screen by default,
     it overlapped the ring in the cockpit -> confined to the right column like the banners. */
  body.mode-hud #sent-status-chip {
    left: calc(var(--anneau) + 3.3rem);
    right: auto;
    top:auto;
    bottom:calc(env(safe-area-inset-bottom) + 4.8rem);
    transform: none;
    max-width: calc(100vw - var(--anneau) - 17.5rem);
  }
}

/* ══════════════════════════════════════════════════════════════════════════════
   “Install Sentinelle” pop-up: BLURS THE BACKGROUND (Julien's request 17/07).
   Full-screen blurred veil BEHIND the card -> the pop-up becomes a real
   modal instead of a banner placed in the middle of the dial.
   It must return ABOVE the HUD: it had z-index 60 while
   #sent-dash is at 480 — otherwise the blur would not cover the dial.
   Safety: the existing rule `body.alerting #sent-install{display:none}`
   continues to hide it as soon as an alert appears -> never a blurred background during
   a full alert while driving.
   ══════════════════════════════════════════════════════════════════════════════ */
#sent-install:not([hidden]) { z-index: 1200; }
body:has(#sent-install:not([hidden]))::after {
  /* BLURRED veil (without darkening) placed at body level: a ::before with
     z-index:-1 INSIDE the pop-up is not composited by WebKit -> blur ignored.
     Here the veil lives outside the pop-up's stacking context, below it (1199 < 1200). */
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1199;
  backdrop-filter: blur(18px) saturate(1.04);
  -webkit-backdrop-filter: blur(18px) saturate(1.04);
  pointer-events: none;
}

/* ── ACTIVE ALERT (we are on it): larger + blurred background (Julien 17/07) ── */
/* Full-screen blurred veil BEHIND the alert card (no heavy darkening);
   placed at body level so backdrop-filter composites (an internal ::before
   is not composited by WebKit). The alert card remains above it, enlarged. */
body.alert-active::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 460;
  background: rgba(10, 16, 28, .06);
  backdrop-filter: blur(18px) saturate(1.03);
  -webkit-backdrop-filter: blur(18px) saturate(1.03);
  pointer-events: none;
}
body.alert-active #sent-card {
  transform: scale(1.09);
  position: relative;
  z-index: 470;
  box-shadow: 0 18px 50px -12px rgba(8, 14, 26, .5), var(--shadow);
  transition: transform .35s cubic-bezier(.22,.61,.36,1);
}
body.alert-active #sent-alert { z-index: 620; transform: scale(1.06) translateY(0); }

/* Age of a report, discreet on the alert label (never on the distance line -> no more overflow onto the buttons). */
.card-age{font-size:.72em;font-weight:600;opacity:.6;letter-spacing:.01em}

/* YES/NO buttons (v/x) removed from the alert (Julien 17/07: not while driving). */
#card-act{display:none!important}

/* ── Post-passage confirmation — PREMIUM design (Julien 17/07) ── */
/* After-passage confirmation: STRICTLY the same styling as the limit vote card
   (#lim-vote / .lv-card) -- Julien: both pop-ups must be identical. Only the badge
   changes (hazard icon instead of a speed number). */
#sent-passconfirm{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(env(safe-area-inset-bottom,0px) + 6.4rem);z-index:601;width:calc(100% - 1.6rem);max-width:430px;pointer-events:auto}
#sent-passconfirm[hidden]{display:none}
body.mode-hud #sent-passconfirm{bottom:calc(env(safe-area-inset-bottom,0px) + 7.2rem)}
/* In portrait Carte, the panel and inset occupied the same 20 px at the bottom of
   the screen throughout the prompt. The panel keeps its size: it moves
   just above the inset, with an 8 px gap at both measured heights
   (720 px of usable page and 932 px in full screen). */
@media (orientation:portrait){
  body.mode-map:has(#sent-passconfirm:not([hidden])) .dash-hero{
    bottom:calc(env(safe-area-inset-bottom,0px) + 18.6rem)
  }
}
#sent-passconfirm .lv-sign{background:rgba(56,189,248,.16);box-shadow:var(--sh-1)}
#sent-passconfirm .lv-sign svg{width:30px;height:30px}
#sent-passconfirm .pc-btns button:active{transform:scale(.93)}
#sent-passconfirm .pc-yes:active{filter:brightness(1.06)}
/* slightly blurred background behind the inset to separate it (like a true soft modal) */
/* THE VEIL APPEARED IN FRONT OF THE CARD IT WAS MEANT TO HIGHLIGHT: veil at 1149,
   card at 601. It therefore blurred exactly what had to be read. It moves
   below it — a veil hides the background, never the subject. */
body:has(#sent-passconfirm:not([hidden]))::before{content:"";position:fixed;inset:0;z-index:600;background:rgba(255,255,255,.01);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);pointer-events:none;opacity:0;animation:pcVeil .34s ease forwards}
@keyframes pcVeil{to{opacity:1}}

/* B14 proportions on the mini limit-editing panels (Julien 17/07):
   constant digit height, condensed 3-digit values -> no longer touch the circle. */
.limedit-grid button b{display:inline-block;font-weight:900;line-height:1}
.limedit-grid button[data-v="110"] b,
.limedit-grid button[data-v="130"] b{transform:none}

/* OFFICIAL sign (Wikimedia SVG): replaces the custom rendering when a standard value/zone is available. */
#limit-official{position:absolute;inset:6%;display:none;pointer-events:none}
.limit-sign.has-official #limit-official{display:block}
#limit-official svg{width:100%;height:100%;display:block}
.limit-sign.has-official{background:none!important;-webkit-mask-image:none!important;mask-image:none!important;box-shadow:none!important;left:14%!important;top:14%!important;width:72%!important;height:auto!important;aspect-ratio:1!important}
.limit-sign.has-official #limit-big,.limit-sign.has-official #limit-cap{display:none!important}
/* SQUARE signs (B30 zone 30, B52 meeting, B51/B53 ends): smaller than round signs to fit INSIDE the ring (Julien 17/07). */
.limit-sign.has-official.off-square{left:23%!important;top:23%!important;width:54%!important}

@font-face{font-family:'Roboto';src:url('/sentinelle/fonts/roboto-400.woff2') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:'Roboto';src:url('/sentinelle/fonts/roboto-500.woff2') format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:'Roboto';src:url('/sentinelle/fonts/roboto-700.woff2') format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:'Roboto';src:url('/sentinelle/fonts/roboto-900.woff2') format('woff2');font-weight:900;font-display:swap}
/* Digits with the OFFICIAL stroke of road signs (Caracteres L1, taken from Wikimedia public-domain SVGs):
   speed and limits now use the SAME typeface as speed-limit signs. */
.hero-core b,#dash-speed,#limit-big,#limit-big .lb-strip i,#limit-val,.lv-sign b,#limconfirm-v,.limedit-grid button b,.tr-avg b,#pk-spd{font-family:'Roboto',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;font-weight:900;letter-spacing:-.02em}


/* ===== Copilot mini-player (card) - clean redesign (overrides the old pill style) ===== */
#sent-radio-mini{flex-direction:column;align-items:stretch;gap:0.5rem;max-width:min(92vw,360px);padding:0.75rem;border-radius:var(--r-l)}
.srm-top{display:flex;align-items:center;gap:0.75rem;width:100%}
#sent-radio-mini #srm-name{flex:1 1 auto!important;max-width:none!important;width:auto;display:flex;align-items:center;gap:0.75rem;min-width:0;text-align:left;background:transparent;padding:0;border:0!important;box-shadow:none!important;outline:0}
#sent-radio-mini .srm-art{position:relative;flex:none;width:56px;height:56px;border-radius:14px;overflow:hidden;border:0;background:#12203a}
#sent-radio-mini .srm-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:5px;background:#fff;box-sizing:border-box}
#sent-radio-mini .srm-ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#cfe0ff;font-size:1.15rem;font-weight:800}
#sent-radio-mini .srm-tx{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:.15rem}
#sent-radio-mini #srm-stname{color:var(--txt)!important;font-size:1.08rem;font-weight:700;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
#sent-radio-mini .srm-np{display:flex;align-items:center;gap:0.5rem;font-size:.86rem;color:var(--txt-dim);min-width:0;max-width:100%}
#sent-radio-mini .srm-np #srm-np-txt{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#srm-fav{flex:none;width:56px;height:56px;border-radius:50%;background:rgba(255,255,255,.07);color:var(--txt-dim);display:flex;align-items:center;justify-content:center;transition:color .15s,transform .1s}
#srm-fav[aria-pressed=true]{color:#ff4d6d}
#srm-fav:active{transform:scale(.9)}
.srm-bottom{display:flex;align-items:center;gap:0.5rem;width:100%;margin-top:.15rem}
.srm-bottom > button{flex:none;display:flex;align-items:center;justify-content:center;border:0;background:transparent;cursor:pointer;padding:0;color:var(--txt)}
#sent-radio-mini #srm-prev,#sent-radio-mini #srm-next{width:56px;height:56px;border-radius:50%;color:var(--txt);background:rgba(255,255,255,.07)}
#sent-radio-mini #srm-prev:active,#sent-radio-mini #srm-next:active{color:var(--txt);transform:scale(.92)}
#sent-radio-mini #srm-toggle{width:70px;height:70px;border-radius:50%!important;background:var(--s-accent)!important;color:#04101f!important;box-shadow:var(--sh-1);margin:0}
#sent-radio-mini #srm-toggle:active{transform:scale(.92)}
.srm-volrow{flex:1 1 auto;display:flex;align-items:center;gap:.5rem;min-width:0;padding-left:.5rem}
.srm-volic{flex:none;opacity:.6;color:var(--txt-dim)}
#srm-vol-mini{flex:1;min-width:0;height:44px;-webkit-appearance:none;appearance:none;background:transparent;outline:none;accent-color:var(--s-accent);cursor:pointer}
#srm-vol-mini::-webkit-slider-runnable-track{height:6px;border-radius:99px;background:var(--track)}
#srm-vol-mini::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:24px;height:24px;margin-top:-9px;border-radius:50%;background:#fff;cursor:pointer;border:2px solid var(--tint);box-shadow:var(--sh-1)}


/* Player: while searching, collapse the hero + volume to move the field + list above the keyboard */
#sent-player.searching .player-hero, #sent-player.searching .player-vol, #sent-player.searching .player-ctrl{display:none!important}
#sent-player.searching .player-lib{margin-top:0;border-top:0;padding-top:0.25rem}

/* Panneaux limite a 3 chiffres (110/130) reduits */
.limedit-grid button[data-v="110"] b, .limedit-grid button[data-v="130"] b{font-size:.78em;letter-spacing:-.03em}


/* DEBUG flags while driving (STAGING only): adds a marker + capture (position + state) at that moment */
#dbg-flags{position:fixed;left:10px;top:50%;transform:translateY(-50%);z-index:70;display:flex;flex-direction:column;gap:9px;pointer-events:auto}
#dbg-flags button{background:rgba(190,30,45,.92);color:#fff;border:0;border-radius:13px;padding:0 14px;min-height:54px;min-width:118px;font:800 .92rem/1.1 system-ui,sans-serif;box-shadow:0 5px 16px rgba(0,0,0,.4);cursor:pointer;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);transition:transform .1s,background .2s}
#dbg-flags button:active{transform:scale(.94)}
#dbg-flags button.flashed{background:#16a34a}
body.mode-map #dbg-flags, body.alerting #dbg-flags{opacity:.55}
body:is(:has(#sent-sheet:not([hidden])),:has(#sent-player:not([hidden])),:has(#sent-settings:not([hidden])),:has(#sent-limedit:not([hidden]))) #dbg-flags{display:none!important}
