@font-face{font-family:Manrope;src:url("/assets/fonts/manrope-latin.woff2?v=101877a7a9") format("woff2");
  font-weight:200 800;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Manrope;src:url("/assets/fonts/manrope-latin-ext.woff2?v=623714ac1d") format("woff2");
  font-weight:200 800;font-display:swap;unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}

  /* Palette taken from the product, not from a template:
     the brand red is the real #e4382b, and the secondary is the yellow of the
     route line inside the app. The dark is a warm charcoal rather than the
     navy every app site uses. */
  :root{
    /* white / gray / red. The only saturated colour is the brand red, used as
       a signal rather than as decoration. Dark notes come from the product
       screenshots themselves, so the page never needs a heavy dark band. */
    --bg:#f4f5f6;        /* cool gray canvas */
    --card:#ffffff;      /* panels */
    --gray:#eceef0;      /* secondary fill */
    --line:#e0e3e6;      /* hairlines */
    --ink:#16181b;       /* text */
    --mute:#656c72;      /* secondary text */
    --red:#e4382b; --red-soft:rgba(228,56,43,.08);
    --sans:Manrope,-apple-system,system-ui,Arial,sans-serif;
    --mono:ui-monospace,"SF Mono",Menlo,monospace;
  }
  *{box-sizing:border-box}
  html{scroll-behavior:smooth}
  html,body{overflow-x:clip}
  body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans);
    -webkit-font-smoothing:antialiased}
  a{color:inherit;text-decoration:none}
  img{max-width:100%;display:block}
  .shell{max-width:1240px;margin:0 auto;padding:0 30px}
  .kicker{font:500 11px/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--red)}
  h2{font-size:clamp(32px,4.2vw,58px);line-height:1.03;letter-spacing:-.055em;margin:14px 0 0;
    text-wrap:balance}

  /* ---------- masthead ---------- */
  header{position:sticky;top:0;z-index:40;background:rgba(244,245,246,.86);
    backdrop-filter:blur(18px);border-bottom:1px solid var(--line)}
  .mast{display:flex;align-items:center;gap:26px;height:66px}
  .brand{display:flex;align-items:center;gap:10px;font-weight:800;letter-spacing:-.035em;font-size:15px}
  .brand img{width:26px;height:26px;border-radius:8px}
  .mast nav{display:flex;gap:24px;font-size:13.5px;color:var(--mute)}
  .mast nav a:hover{color:var(--ink)}
  .mast .sp{margin-left:auto}
  .btn{display:inline-flex;align-items:center;gap:7px;background:var(--red);color:#fff;
    padding:11px 17px;border-radius:8px;font-size:13px;font-weight:800;transition:.2s;border:0;
    cursor:pointer;font-family:var(--sans)}
  .btn:hover{transform:translateY(-2px);box-shadow:0 12px 26px -10px rgba(228,56,43,.6)}

  /* ---------- section scaffolding ---------- */
  section{padding:112px 0;position:relative}
  .stop{display:flex;align-items:baseline;gap:14px}
  .stop b{font:700 11px var(--mono);letter-spacing:.16em;color:var(--red)}
  .stop i{flex:1;height:1px;background:var(--line);font-style:normal}

  /* ---------- hero backdrop -------------------------------------------
     The real photograph sits behind the hero, scrimmed hard from the left so
     the headline keeps full contrast while the right side opens onto actual
     street. Depth from our own asset rather than a bought texture.
     The scrim is a gradient, not a flat overlay, so the image is strongest
     exactly where there is no text. */
  .hero{position:relative;isolation:isolate;overflow:hidden}
  .hero__bg{position:absolute;inset:0;z-index:-2;background-image:image-set(url("/assets/images/photo-hero.webp?v=d3e6923d7c") type("image/webp"),url("/assets/images/photo-hero.jpg?v=0d37ac97f3") type("image/jpeg"));
    background-size:cover;background-position:58% 58%;
    transform:scale(1.06);will-change:transform}
  .hero:before{content:"";position:absolute;inset:0;z-index:-1;
    background:
      linear-gradient(100deg,var(--bg) 0%,rgba(244,245,246,.97) 30%,rgba(244,245,246,.86) 46%,
                      rgba(244,245,246,.50) 66%,rgba(244,245,246,.34) 100%),
      linear-gradient(to bottom,rgba(244,245,246,.55) 0%,transparent 22%,transparent 74%,var(--bg) 100%)}

  /* ---------- HERO ---------- */
  .hero{padding:64px 0 96px}
  .hero-grid{display:grid;grid-template-columns:1.06fr .94fr;gap:56px;align-items:center}
  h1{font-size:clamp(46px,6vw,86px);line-height:.95;letter-spacing:-.06em;margin:18px 0 0}
  h1 em{font-style:normal;color:var(--red)}
  .lede{font-size:17.5px;line-height:1.62;color:var(--mute);max-width:46ch;margin:24px 0 0}
  .stores{display:flex;gap:11px;margin:30px 0 0;flex-wrap:wrap}
  .stores a{transition:transform .2s,filter .2s}
  .stores img{height:48px;width:auto}
  .stores a:hover{transform:translateY(-3px);filter:brightness(1.12)}
  .trust{display:flex;gap:18px;flex-wrap:wrap;margin:20px 0 0;font:11px var(--mono);color:var(--mute)}
  .trust b{color:var(--red);font-weight:400}

  /* vehicle picker */
  .vsel{display:flex;gap:7px;flex-wrap:wrap;margin:28px 0 0}
  .vsel button{background:var(--card);border:1px solid var(--line);color:var(--mute);border-radius:8px;
    padding:8px 14px;font:700 12px var(--sans);cursor:pointer;transition:.18s;
    display:inline-flex;align-items:center;gap:7px}
  /* Material Symbols ship as filled paths on a 0 -960 960 960 box, not strokes,
     so this is fill rather than stroke. currentColor is the point either way:
     one copy of each glyph tracks the button through resting, hover and
     selected instead of three coloured variants. flex:none stops the icon being
     squeezed when the labels wrap on a narrow screen. */
  .vsel__ico{width:19px;height:19px;flex:none;fill:currentColor;stroke:none}
  .vsel button:hover{border-color:rgba(228,56,43,.5);color:var(--ink)}
  .vsel button[aria-pressed=true]{background:var(--red);border-color:var(--red);color:#fff}
  .vnote{margin:18px 0 0;font-size:13.5px;line-height:1.55;color:var(--mute);max-width:44ch;min-height:40px}
  .vnote b{color:var(--red);font-weight:700}

  .stage{position:relative;display:grid;place-items:center;min-height:600px}
  .halo{position:absolute;width:460px;aspect-ratio:1;border-radius:50%;
    background:radial-gradient(circle,rgba(228,56,43,.10),transparent 64%)}

  /* ---------- device frame ---------- */
  .dev{position:relative;display:block;border-radius:var(--dr,30px);
    background:linear-gradient(158deg,#3a3733 0%,#191715 44%,#0c0b0a 100%);padding:var(--dp,3%);
    box-shadow:inset 0 0 0 1px rgba(255,255,255,.15),inset 0 0 0 3px #070605,
      0 30px 56px -24px rgba(0,0,0,.7)}
  .dev img{display:block;width:100%;height:auto;background:#000;
    border-radius:calc(var(--dr,30px) - var(--dg,8px))}
  .dev:after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
    background:linear-gradient(150deg,rgba(255,255,255,.12),rgba(255,255,255,.02) 20%,transparent 44%)}
  .dev--watch{--dr:28px;--dp:6%;--dg:8px}
  .hero-dev{position:relative;z-index:1;width:min(100%,300px);
    transition:opacity .3s,transform .5s cubic-bezier(.22,1,.36,1)}
  .chip{position:absolute;z-index:3;right:2px;top:76px;background:var(--card);
    border:1px solid var(--line);border-radius:10px;padding:11px 14px;font-size:11px;
    transform:rotate(-3deg);box-shadow:0 16px 34px -18px rgba(22,24,27,.35)}
  .chip span{display:block;font:9px var(--mono);color:var(--mute)}
  .chip b{display:block;margin-top:4px}
  .chip i{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--red);margin-right:5px}

  /* ---------- the proof: car vs Urban Rider ---------- */
  .proof{margin-top:44px;display:grid;grid-template-columns:.86fr 1.14fr;gap:44px;align-items:center;
    background:var(--card);border:1px solid var(--line);border-radius:20px;padding:40px;
    box-shadow:0 26px 54px -34px rgba(22,24,27,.3)}
  .proof h3{font-size:25px;letter-spacing:-.045em;line-height:1.15;margin:12px 0 10px}
  .proof p{font-size:14.5px;line-height:1.6;color:var(--mute);margin:0;max-width:40ch}
  .seg{display:inline-flex;margin:22px 0 0;border:1px solid var(--line);border-radius:9px;overflow:hidden}
  .seg button{background:transparent;border:0;color:var(--mute);padding:10px 17px;
    font:800 12px var(--sans);cursor:pointer;transition:.18s}
  .seg button[aria-pressed=true]{background:var(--red);color:#fff}
  .pfacts{display:flex;gap:26px;border-top:1px solid var(--line);margin-top:24px;padding-top:16px}
  .pfacts b{display:block;font-size:19px;letter-spacing:-.03em}
  .pfacts b.warn{color:var(--red)}
  .pfacts span{font:10px var(--mono);color:var(--mute);letter-spacing:.09em;text-transform:uppercase}
  .map{width:100%;height:auto;border-radius:12px;background:var(--gray);border:1px solid var(--line)}
  .rd{fill:none;stroke:#dcdfe2;stroke-linecap:round}
  .mway{fill:none;stroke:#c9ced3;stroke-width:13;stroke-linecap:round}
  .mway-c{fill:none;stroke:#eceef0;stroke-width:1.6;stroke-dasharray:9 9}
  #rCar,#rScoot{fill:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round}
  #rCar{stroke:#98a0a8}
  #rScoot{stroke:var(--red)}
  .banned{opacity:0;transition:opacity .35s}
  .banned.on{opacity:1}

  /* ---------- features ---------- */
  .feat{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:46px}
  .card{background:var(--card);border:1px solid var(--line);border-radius:15px;padding:24px;
    min-height:196px;position:relative;overflow:hidden;
    transition:transform .3s cubic-bezier(.22,1,.36,1),border-color .3s}
  .card:hover{transform:translateY(-5px);border-color:rgba(228,56,43,.38);
    box-shadow:0 24px 46px -26px rgba(22,24,27,.32)}
  .card:after{content:"";position:absolute;inset:0;opacity:0;transition:opacity .3s;pointer-events:none;
    background:radial-gradient(300px circle at var(--fx,50%) var(--fy,50%),rgba(228,56,43,.07),transparent 60%)}
  .card:hover:after{opacity:1}
  .card .m{width:38px;height:38px;border-radius:10px;display:grid;place-items:center;
    background:var(--red-soft);color:var(--red);font-weight:800;margin-bottom:30px;
    transition:transform .3s}
  .card:hover .m{transform:scale(1.1) rotate(-5deg)}
  .card h3{margin:0 0 8px;font-size:16px;letter-spacing:-.03em;color:var(--ink)}
  .card p{margin:0;font-size:13.5px;line-height:1.58;color:var(--mute)}

  /* ---------- light band ---------- */
  .light{background:var(--card)}
  .light .kicker{color:var(--red)}
  
  .light .stop i{background:var(--line)}
  .lead{font-size:16.5px;line-height:1.65;color:var(--mute);max-width:56ch;margin:20px 0 0}

  /* ---------- settings showcase ----------------------------------------
     Was three small phones side by side: each got clipped by its card, all
     three read as the same dark screen with blue toggles, and at that width
     the settings text was illegible. One larger phone you switch between
     fixes all three, and gives each screen room to actually be read. */
  .tabs{display:grid;grid-template-columns:1fr 340px;gap:56px;align-items:center;margin-top:44px}
  /* Section 03 used to read as two half-empty halves. The headline ran the full
     1180px shell on one line, leaving the phone column blank beside it, and
     align-items:center then floated the numbered list 209px below the lead.

     Capping the headline turns it into two lines that fill the left column, and
     the phone rises into the space that opens next to them. The list starts at
     the top of the row instead of being centred against a phone twice its
     height, which is what closes the gap.

     Two breakpoints, not one. Above 1000px the grid is two columns, so starting
     the list at the top of the row is safe and is what closes the gap. The lift
     itself waits for 1160px: the phone column is a fixed 340px off the right
     edge, so at 1001px its left edge lands 39px inside a headline capped at
     660px and the two collide. By 1160px there is 100px of clear air between
     them. Measured, not guessed. */
  #bike h2{max-width:min(100%,660px)}
  @media(min-width:1001px){ #bike .tabs{align-items:start} }
  @media(min-width:1160px){ #bike .tabstage{margin-top:-190px} }
  .tablist{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--line)}
  .tabrow{display:grid;grid-template-columns:34px 1fr;gap:16px;align-items:start;width:100%;
    text-align:left;background:none;border:0;border-bottom:1px solid var(--line);
    padding:22px 4px 22px 0;cursor:pointer;font-family:var(--sans);position:relative;
    transition:padding-left .25s}
  .tabrow:before{content:"";position:absolute;left:-16px;top:18px;bottom:18px;width:2px;
    background:var(--red);border-radius:2px;opacity:0;transition:opacity .25s}
  .tabrow[aria-selected=true]{padding-left:16px}
  .tabrow[aria-selected=true]:before{opacity:1}
  .tabrow .n{font:600 10px var(--mono);letter-spacing:.13em;color:var(--mute);padding-top:4px;
    transition:color .25s}
  .tabrow[aria-selected=true] .n{color:var(--red)}
  .tabrow h3{margin:0;font-size:19px;letter-spacing:-.035em;color:var(--mute);transition:color .25s}
  .tabrow[aria-selected=true] h3{color:var(--ink)}
  .tabrow p{margin:7px 0 0;font-size:14px;line-height:1.55;color:var(--mute);max-width:46ch;
    max-height:0;opacity:0;overflow:hidden;transition:max-height .35s,opacity .3s,margin .35s}
  .tabrow[aria-selected=true] p{max-height:90px;opacity:1}
  .tabstage{position:relative;display:grid;place-items:center}
  .tabstage .dev{width:100%;max-width:300px;transition:opacity .28s,transform .45s cubic-bezier(.22,1,.36,1)}
  @media(max-width:1000px){
    .tabs{grid-template-columns:1fr;gap:30px}
    .tabrow p{max-height:90px;opacity:1}
    .tabstage .dev{max-width:250px}
  }

  /* ---------- android ---------- */
  .two{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center;margin-top:44px}
  .two p{font-size:16px;line-height:1.68;color:var(--mute);margin:18px 0 26px}
  .gal{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;align-items:end}
  .gal .dev{transition:transform .45s cubic-bezier(.22,1,.36,1),filter .45s}
  .gal .dev:nth-child(2){transform:translateY(-30px)}
  .gal .dev:nth-child(3){transform:translateY(-8px)}
  .gal:hover .dev{filter:brightness(.82) saturate(.85)}
  .gal .dev:hover{filter:none;z-index:2}
  .gal .dev:nth-child(1):hover{transform:translateY(-12px) scale(1.06)}
  .gal .dev:nth-child(2):hover{transform:translateY(-44px) scale(1.06)}
  .gal .dev:nth-child(3):hover{transform:translateY(-22px) scale(1.06)}

  /* ---------- electric ---------- */
  .elec{display:grid;grid-template-columns:1.02fr .98fr;gap:52px;align-items:center}
  /* No panel here. The devices sit straight on the canvas against the battery
     mark and a soft glow, so nothing boxes them in. isolation:isolate keeps the
     glow's blend from reaching the section behind it. */
  .elec-art{position:relative;isolation:isolate;padding:20px 0 8px;
    display:flex;flex-direction:column;align-items:center}

  /* The glow gives the phone something to sit against now that the white card
     is gone. Sized off the container so it scales with the column. */
  .elec-art::before{content:"";position:absolute;z-index:0;
    left:50%;top:52%;transform:translate(-50%,-50%);
    width:118%;aspect-ratio:1;border-radius:50%;
    background:radial-gradient(circle,rgba(228,56,43,.13) 0%,rgba(228,56,43,.05) 42%,transparent 68%)}

  /* The mark sits in the upper right, the one part of this column the phone and
     watch leave empty, so the bolt is never occluded. Centring it behind the
     devices hid the bolt completely and flattened the battery into a blur.
     Scaled off the container width so it holds its position as the column
     reflows, and allowed to bleed off the right edge. */
  .elec-mark{position:absolute;z-index:0;pointer-events:none;
    right:-9%;top:-4%;width:74%;height:auto;
    transform:rotate(-12deg);transform-origin:70% 30%;
    fill:none;stroke:rgba(22,24,27,.13);stroke-width:6;stroke-linejoin:round}
  .elec-mark__nub{fill:rgba(22,24,27,.13);stroke:none}
  /* Alpha lives in the colours, not in a parent opacity: opacity on the <svg>
     multiplies into every child, which pinned the bolt to a tenth of its value
     and turned the brand red into pale pink. Kept well below the red used for
     buttons and accents, so this stays decoration and the signal red stays a
     signal. */
  .elec-mark__bolt{fill:rgba(228,56,43,.22);stroke:none}

  /* phone and watch share a baseline instead of one floating over the other,
     and nothing is clipped: the panel sizes to its contents */
  .elec-devs{position:relative;z-index:1;
    display:flex;align-items:flex-end;justify-content:center;gap:30px}
  .elec-art .dev{width:244px;flex:none;transition:transform .45s cubic-bezier(.22,1,.36,1)}
  /* The watch is a real product render with its band, not a screenshot in a CSS
     bezel, so it carries its own frame and .dev would draw a second one around
     it. Width is set from the face rather than the image: the screen is 374 of
     the render's 520px, so 186px here keeps the face at the ~132px it has always
     been while the band adds the extra height around it.

     Rotation is transform-only, so the flex row still reserves the upright box
     and the tilted corners paint outside it. That is what keeps the phone beside
     it from being pushed over. margin-bottom drops to 6px because the band now
     fills the space the old lift was faking. */
  .elec-art .w{width:186px;height:auto;flex:none;margin:0 0 6px 38px;
    transform:rotate(30deg);transform-origin:50% 46%;
    /* drop-shadow, not box-shadow: the render is a transparent PNG whose
       silhouette is a watch, and box-shadow would trace its rectangular box
       instead. The offset is counter-rotated (9px across, 16px down inside the
       element) because filters are applied before the transform, so a plain
       0/18px would tilt 30deg with the watch and fall in a different direction
       from the phone's shadow. This lands straight down, like the phone's. */
    filter:drop-shadow(9px 16px 18px rgba(0,0,0,.32));
    transition:transform .45s cubic-bezier(.22,1,.36,1)}
  .elec-art:hover .dev{transform:translateY(-6px)}
  .elec-art:hover .w{transform:rotate(30deg) translateY(-6px)}
  .elec-art .note{position:relative;z-index:1;align-self:flex-start}
  .note{display:inline-flex;flex-direction:column;gap:2px;margin:0 0 24px;
    border-left:2px solid var(--red);padding:2px 0 2px 12px;
    font:10px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--mute)}
  .note b{font:700 14px var(--sans);letter-spacing:-.02em;color:var(--ink);text-transform:none}

  /* ---------- FAQ ---------- */
  .faq{display:grid;grid-template-columns:.82fr 1.18fr;gap:64px;margin-top:40px}
  .qs{border-top:1px solid var(--line)}
  .qs details{border-bottom:1px solid var(--line)}
  .qs summary{list-style:none;cursor:pointer;padding:18px 0;font-size:15px;font-weight:700;
    display:flex;justify-content:space-between;gap:16px;align-items:center;color:var(--ink)}
  .qs summary::-webkit-details-marker{display:none}
  .qs summary:after{content:"+";font-weight:400;font-size:20px;color:var(--mute);transition:transform .28s}
  .qs details[open] summary:after{transform:rotate(45deg)}
  .qs .a{padding:0 0 18px;font-size:14px;line-height:1.65;color:var(--mute);max-width:62ch}
  /* The global reset strips link colour and underline, so a link inside an
     answer was indistinguishable from the sentence around it. */
  .qs .a a{color:var(--ink);font-weight:700;text-decoration:underline;
    text-decoration-color:rgba(228,56,43,.45);text-underline-offset:3px;
    transition:text-decoration-color .2s,color .2s}
  .qs .a a:hover{color:var(--red);text-decoration-color:var(--red)}

  /* ---------- arrive ---------- */
  .arrive{background:var(--red);color:#fff;padding:96px 0}
  .arrive .kicker{color:rgba(255,255,255,.72)}
  .arrive h2{color:#fff;max-width:16ch}
  .arrive-row{display:flex;justify-content:space-between;align-items:end;gap:40px;flex-wrap:wrap;margin-top:26px}
  .arrive p{margin:0 0 16px;max-width:32ch;font-size:15px;line-height:1.6;color:rgba(255,255,255,.86)}
  .sig{display:flex;align-items:center;gap:12px;font-size:14px}

  /* ---------- scroll motion --------------------------------------------
     Directional rather than one generic fade: content enters from the side it
     belongs to, groups stagger, and a few elements keep moving with scroll so
     the page does not feel like a stack of things that already landed.
     Everything is transform/opacity, so it composites on the GPU. */
  .rv,[data-rv]{opacity:0;transition:opacity .8s cubic-bezier(.22,1,.36,1),
    transform .8s cubic-bezier(.22,1,.36,1)}
  .rv{transform:translateY(26px)}
  [data-rv="left"]{transform:translateX(-38px)}
  [data-rv="right"]{transform:translateX(38px)}
  [data-rv="scale"]{transform:scale(.94)}
  [data-rv="rise"]{transform:translateY(44px) scale(.97)}
  .rv.in,[data-rv].in{opacity:1;transform:none}
  /* parallax targets: driven from JS, kept as a variable so CSS owns the rest */
  .par{transform:translate3d(0,var(--py,0),0)}
  @media(prefers-reduced-motion:reduce){
    .rv,[data-rv],.par{opacity:1!important;transform:none!important;transition:none}
  }

  /* ---------- shorts ----------------------------------------------------
     Real embeds, loaded on click. The poster is self-hosted and the iframe
     only appears once someone presses play, so a visitor who never watches
     never contacts Google. youtube-nocookie for the same reason. Costs one
     click and saves the whole third-party payload on first paint. */
  /* A shelf, not a carousel: native scroll-snap means every clip is reachable
     by touch, trackpad, keyboard and scrollbar, and nothing auto-advances away
     from the reader. Arrows are an affordance for mouse users, not the only
     way in. */
  .shelf{position:relative;margin-top:44px}
  .shorts{display:flex;gap:22px;overflow-x:auto;scroll-snap-type:x mandatory;
    scroll-behavior:smooth;padding:4px 4px 14px;margin:-4px -4px 0;
    scrollbar-width:none;-ms-overflow-style:none}
  .shorts::-webkit-scrollbar{display:none}
  .short{margin:0;flex:0 0 268px;scroll-snap-align:start}
  .shelf__nav{position:absolute;top:-52px;right:0;display:flex;gap:8px}
  .shelf__nav button{width:38px;height:38px;border-radius:10px;border:1px solid var(--line);
    background:var(--card);color:var(--ink);cursor:pointer;display:grid;place-items:center;
    transition:.18s}
  .shelf__nav button:hover:not(:disabled){border-color:var(--red);color:var(--red)}
  .shelf__nav button:disabled{opacity:.35;cursor:default}
  @media(max-width:1000px){.shelf__nav{display:none}.short{flex-basis:calc(80vw - 40px);max-width:268px}}
  .short{margin:0}
  .short__frame{position:relative;aspect-ratio:9/16;border-radius:18px;overflow:hidden;
    background:#111;border:1px solid var(--line);cursor:pointer;display:block;width:100%;padding:0}
  .short__frame img{width:100%;height:100%;object-fit:cover;transition:transform .5s cubic-bezier(.22,1,.36,1),filter .3s}
  .short__frame:hover img{transform:scale(1.04);filter:brightness(.92)}
  .short__frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
  .short__play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
    width:58px;height:58px;border-radius:50%;background:var(--red);display:grid;place-items:center;
    box-shadow:0 12px 30px -8px rgba(228,56,43,.7);transition:transform .3s;pointer-events:none}
  .short__frame:hover .short__play{transform:translate(-50%,-50%) scale(1.09)}
  .short__play svg{margin-left:3px}
  .short__more{background:var(--card);border:1px solid var(--line);cursor:pointer;
    display:grid;place-items:center;text-align:center;text-decoration:none;
    transition:border-color .25s,background .25s}
  .short__more:hover{border-color:var(--red);background:var(--red-soft)}
  .short__moreinner{display:grid;justify-items:center;gap:14px;padding:24px}
  .short__morearrow{display:grid;place-items:center;width:44px;height:44px;border-radius:50%;
    border:1px solid var(--line);color:var(--red);transition:border-color .25s,transform .25s}
  .short__more:hover .short__morearrow{border-color:var(--red);transform:translate(2px,-2px)}
  .short__moretxt{font-size:14px;line-height:1.5;color:var(--ink);max-width:16ch}
  .short__morelab{font:10px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--mute)}
  .short figcaption{margin-top:14px;font-size:14.5px;line-height:1.5;color:var(--ink);max-width:34ch}
  .short figcaption span{display:block;margin-top:5px;font:10px var(--mono);letter-spacing:.12em;
    text-transform:uppercase;color:var(--mute)}

  /* ---------- maker ------------------------------------------------------
     No portrait, so the layout carries it: a pull-quote against a red rule on
     the left, the story on the right, and a signature that ends on a real
     email address. "One rider reads every email" is the strongest trust signal
     a one-person app has, so it gets to be a link rather than a claim. */
  .maker{background:var(--gray);padding:96px 0}
  .maker .kicker{color:var(--red)}
  .maker-grid{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:start;margin-top:18px}
  .quote{position:relative;font-size:clamp(28px,3.9vw,50px);letter-spacing:-.05em;line-height:1.05;
    margin:0;padding-left:24px;border-left:3px solid var(--red);max-width:15ch;color:var(--ink)}
  .maker-body p{margin:0 0 18px;font-size:16.5px;line-height:1.68;color:var(--mute);max-width:52ch}
  .maker-body p:last-of-type{margin-bottom:0}
  .maker-body a{color:var(--red);border-bottom:1px solid rgba(228,56,43,.35);transition:.18s}
  .maker-body a:hover{border-bottom-color:var(--red)}
  .sig{display:flex;align-items:center;gap:12px;margin-top:34px;padding-top:22px;
    border-top:1px solid var(--line)}
  .sig img{width:36px;height:36px;border-radius:10px}
  .sig b{display:block;font-size:14.5px;letter-spacing:-.01em;color:var(--ink)}
  .sig span{display:block;font-size:12.5px;color:var(--mute);margin-top:2px}
  @media(max-width:1000px){.maker-grid{grid-template-columns:1fr;gap:30px}}

  /* ---------- footer ----------------------------------------------------
     Real columns, real links, and the language switcher: the site runs 11
     locales and the footer is where people look for them. Social icons are
     SVG for the same reason the feature icons are, glyphs render differently
     on every machine. */
  footer{background:var(--card);border-top:1px solid var(--line);padding:64px 0 30px;
    color:var(--mute);font-size:13.5px}
  .fgrid{display:grid;grid-template-columns:1.6fr repeat(3,1fr) 1.1fr;gap:40px}
  .fbrand .brand{margin-bottom:14px;color:var(--ink)}
  .ftag{margin:0 0 20px;line-height:1.6;max-width:34ch}
  .fstores{display:flex;gap:9px;flex-wrap:wrap}
  .fstores img{height:38px;width:auto;transition:transform .2s}
  .fstores a:hover img{transform:translateY(-2px)}
  footer h4{margin:0 0 14px;font:600 11px var(--mono);letter-spacing:.14em;text-transform:uppercase;
    color:var(--ink)}
  footer ul{list-style:none;margin:0;padding:0;display:grid;gap:10px}
  footer ul a{color:var(--mute);transition:color .18s}
  footer ul a:hover{color:var(--red)}
  .fsoc{display:flex;gap:10px;margin-top:4px}
  .fsoc a{width:34px;height:34px;border:1px solid var(--line);border-radius:9px;display:grid;
    place-items:center;color:var(--mute);transition:.2s}
  .fsoc a:hover{color:var(--red);border-color:rgba(228,56,43,.45);transform:translateY(-2px)}
  .flang{display:flex;flex-wrap:wrap;gap:6px}
  .flang a{border:1px solid var(--line);border-radius:7px;padding:5px 9px;font-size:12px;
    color:var(--mute);transition:.18s}
  .flang a:hover{color:var(--ink);border-color:var(--mute)}
  .flang a[aria-current]{background:var(--ink);border-color:var(--ink);color:#fff}
  .fbase{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;
    border-top:1px solid var(--line);margin-top:48px;padding-top:22px;font-size:12.5px}
  @media(max-width:1000px){.fgrid{grid-template-columns:1fr 1fr;gap:32px}
    .fbrand{grid-column:1/-1}}

  /* reveal */
  @media(prefers-reduced-motion:reduce){
    html{scroll-behavior:auto}
  }
  @media(max-width:1000px){
    .hero-grid,.proof,.two,.elec,.faq{grid-template-columns:1fr;gap:30px}
    .feat,.trio,.gal{grid-template-columns:1fr}
    .gal{grid-template-columns:repeat(3,1fr)}
    section{padding:74px 0}
    .proof{padding:26px}
    .stage{min-height:520px}
    /* Single column now, so the art has the full width: hold the mark back so it
       does not run the full bleed of the page. */
    .elec-mark{width:46%;right:-2%}
    .elec-art::before{width:86%}
  }
  /* The phone and watch are a fixed pair; below roughly 460px they stop fitting
     side by side, so scale both off the viewport rather than letting them
     overflow. 244 and 150 are the desktop sizes, held as the ceiling. */
  @media(max-width:520px){
    .elec-art .dev{width:min(244px,54vw)}
    /* The 38px nudge and the full 30deg both exist to buy lateral room, and a
     phone screen has none: rotating a 122px watch by 30deg spreads its painted
     box to 163px, which at 360px wide would sit on the phone and clip at the
     right edge. Smaller and flatter here, and the left nudge goes away. */
  .elec-art .w{width:min(126px,32vw);margin:0 0 2vw 0;transform:rotate(14deg)}
  .elec-art:hover .w{transform:rotate(14deg) translateY(-6px)}
    /* justify-content centres the layout boxes, but the tilted watch paints
       past its own box, so on a phone the right edge clipped. The padding
       shifts the pair left by half of it, which is enough to bring the
       overhang back inside. */
    .elec-devs{gap:5vw;padding-right:18px}
    .elec-mark{width:56%;right:-6%;top:-2%}
  }

/* ---------- language switcher (production; the comp had none) ---------- */
.lang{position:relative}
.lang__btn{display:flex;align-items:center;gap:6px;font:600 13px var(--sans);color:var(--mute);
  background:none;border:0;cursor:pointer;padding:6px 2px;letter-spacing:.02em}
.lang__btn:hover,.lang__btn[aria-expanded="true"]{color:var(--ink)}
.lang__btn svg{transition:transform .2s}
.lang__btn[aria-expanded="true"] svg{transform:rotate(180deg)}
.lang__menu{position:absolute;top:calc(100% + 10px);right:0;min-width:172px;z-index:60;
  background:var(--card);border:1px solid var(--line);border-radius:14px;padding:6px;
  box-shadow:0 18px 40px -18px rgba(0,0,0,.28);
  opacity:0;visibility:hidden;transform:translateY(-6px);transition:opacity .18s,transform .18s,visibility .18s}
.lang__menu.open{opacity:1;visibility:visible;transform:none}
.lang__menu a{display:block;padding:8px 12px;border-radius:9px;font-size:13.5px;color:var(--mute)}
.lang__menu a:hover{background:var(--gray);color:var(--ink)}
.lang__menu a[aria-current="true"]{color:var(--red);font-weight:700}
/* (the old rule hiding .lang under 720px is gone: the mobile panel carries it) */
/* Launchpadly badge sits with the footer brand block */
.fbadge{display:inline-block;margin-top:18px}
.fbadge img{display:block;border:0}

/* ---------- CJK type scale ----------
   Han and kana are full-width, so a scale tuned for Latin overflows: at 86px
   the eight glyphs of the Japanese hero line need ~690px in a 596px column and
   wrapped a single character onto its own line. Chinese and Japanese also break
   at any character, so there is no word boundary to protect the line. Smaller
   display sizes and slacker tracking fix both. */
html:lang(ja) .hero h1,
html:lang(zh-Hans) .hero h1,
html:lang(zh-Hant) .hero h1{font-size:clamp(30px,4.4vw,62px);letter-spacing:-.01em;line-height:1.14}
html:lang(ja) h2,
html:lang(zh-Hans) h2,
html:lang(zh-Hant) h2{font-size:clamp(26px,3.4vw,44px);letter-spacing:-.01em;line-height:1.2}
html:lang(ja) .kicker,
html:lang(zh-Hans) .kicker,
html:lang(zh-Hant) .kicker{letter-spacing:.08em}
/* no hanging punctuation mid-line */
html:lang(ja) .hero h1, html:lang(zh-Hans) .hero h1, html:lang(zh-Hant) .hero h1,
html:lang(ja) h2, html:lang(zh-Hans) h2, html:lang(zh-Hant) h2{line-break:strict}

/* ---------- mobile navigation ----------
   The bar had no mobile rule at all, so five links plus the switcher and CTA
   simply overflowed. Below the breakpoint the header becomes two rows: brand
   and toggle on the first, everything else collapsing into a panel underneath.
   Nothing is duplicated, so the links stay single source. */
.navtoggle{display:none;width:40px;height:40px;padding:0;border:1px solid var(--line);
  border-radius:10px;background:var(--card);cursor:pointer;
  flex-direction:column;align-items:center;justify-content:center;
  margin-left:auto;transition:border-color .2s}
.navtoggle:hover{border-color:var(--mute)}
.navtoggle span{display:block;width:17px;height:1.5px;background:var(--ink);border-radius:2px;
  transition:transform .26s cubic-bezier(.22,1,.36,1),opacity .18s}
.navtoggle span + span{margin-top:4px}
.navtoggle span{flex:none}
header.nav-open .navtoggle span:nth-child(1){transform:translateY(5.5px) rotate(45deg)}
header.nav-open .navtoggle span:nth-child(2){opacity:0}
header.nav-open .navtoggle span:nth-child(3){transform:translateY(-5.5px) rotate(-45deg)}

@media(max-width:860px){
  .navtoggle{display:flex}
  .mast{flex-wrap:wrap;gap:0 14px;height:auto;min-height:60px;padding-top:10px;padding-bottom:10px}
  .mast .sp{display:none}
  /* each collapsible child takes its own full-width row */
  .mast nav,.mast .lang,.mast .btn{width:100%;order:3}
  .mast nav{flex-direction:column;gap:0;margin-top:8px;
    border-top:1px solid var(--line);padding-top:6px}
  .mast nav a{padding:11px 2px;font-size:15px;color:var(--ink);
    border-bottom:1px solid var(--line)}
  .mast .lang{order:4;margin-top:14px}
  .mast .btn{order:5;justify-content:center;margin:14px 0 6px;padding:13px 17px;font-size:14px}
  /* the language dropdown becomes a plain chip row inside the panel */
  .lang__btn{display:none}
  .lang__menu{position:static;opacity:1;visibility:visible;transform:none;min-width:0;
    background:none;border:0;border-radius:0;padding:0;box-shadow:none;
    display:flex;flex-wrap:wrap;gap:6px}
  .lang__menu a{border:1px solid var(--line);border-radius:999px;padding:6px 11px;font-size:12.5px}
  .lang__menu a:hover{background:var(--gray)}
  /* collapsed state */
  header:not(.nav-open) .mast nav,
  header:not(.nav-open) .mast .lang,
  header:not(.nav-open) .mast .btn{display:none}
  header.nav-open .mast nav{display:flex}
  header.nav-open .mast .lang{display:block}
  header.nav-open .mast .btn{display:inline-flex}
}

/* ---------- the cost argument ----------
   Two verified figures carry this, so they are set as the loudest thing in the
   block. The prose sits beside them rather than under them, because the numbers
   are the argument and the sentence is only the explanation. */
.cost{background:var(--card);border-top:1px solid var(--line);padding:clamp(64px,8vw,104px) 0}
.costgrid{display:grid;grid-template-columns:repeat(2,auto) 1fr;gap:clamp(26px,4vw,56px);
  align-items:start;margin-top:clamp(34px,4vw,52px)}
.costfact b{display:block;font-size:clamp(38px,5vw,64px);line-height:1;letter-spacing:-.055em;
  color:var(--red);font-variant-numeric:tabular-nums}
.costfact span{display:block;margin-top:12px;font-size:12.5px;line-height:1.5;color:var(--mute);
  max-width:24ch}
.costnote{border-left:1px solid var(--line);padding-left:clamp(26px,3vw,44px)}
.costnote p{margin:0;font-size:15.5px;line-height:1.7;color:var(--ink);max-width:44ch}
@media(max-width:900px){
  .costgrid{grid-template-columns:1fr 1fr;gap:30px}
  .costnote{grid-column:1/-1;border-left:0;padding-left:0;padding-top:26px;
    border-top:1px solid var(--line)}
}
@media(max-width:520px){
  .costgrid{grid-template-columns:1fr}
  .costfact span{max-width:none}
}

/* ---------- reach map ----------
   The map is one inline SVG so the dots can inherit the brand red and carry
   per-country tooltips. Land geometry is Natural Earth (public domain) baked
   into a path at build time: the CSP blocks every external request, so a map
   has to ship inside the document rather than fetch tiles or a library. */
.reachfacts{display:flex;flex-wrap:wrap;gap:clamp(30px,6vw,84px);margin:34px 0 8px}
.reachfact b{display:block;font-size:clamp(38px,5vw,58px);line-height:1;letter-spacing:-.05em;
  color:var(--red);font-variant-numeric:tabular-nums}
.reachfact span{display:block;margin-top:8px;font:600 11px var(--mono);letter-spacing:.13em;
  text-transform:uppercase;color:var(--mute);max-width:22ch}

  /* No overflow:visible here. Land north of 74N and south of 48S falls
     outside the viewBox, and letting it paint spilled Greenland and
     Antarctica over the figures above the map. */
.reach__map{display:block;width:100%;height:auto;margin:8px 0 0}
  /* --gray is only a shade off --bg and the continents nearly vanished.
     --line is the next step down and still inside the palette. */
.reach__land{fill:var(--line);stroke:none}
.reach__grid line{stroke:var(--ink);stroke-width:1;opacity:.045}
.reach__dots circle{fill:var(--red);fill-opacity:.72}

/* The dots fade up in the order the generator emitted them, which is busiest
   first, so the map resolves outward from its centres of gravity rather than
   appearing all at once. Purely decorative, so it is skipped outright when
   the visitor asks for reduced motion. */
@media(prefers-reduced-motion:no-preference){
  .reach__dots circle{opacity:0;animation:reachIn .5s ease-out forwards;
    animation-delay:calc(var(--i) * 26ms)}
  @keyframes reachIn{from{opacity:0;transform:scale(.3)}to{opacity:1;transform:none}}
  .reach__dots circle{transform-box:fill-box;transform-origin:center}
}

.reachnote{margin:22px 0 0;max-width:78ch;font-size:13px;line-height:1.65;color:var(--mute)}

@media(max-width:720px){
  /* Below about this width the long tail of single dots is unreadable anyway,
     and the graticule only adds noise at that scale. */
  .reach__grid{display:none}
  .reachfacts{gap:26px 34px}
}

/* ---------- speed sign flip (cost section) ----------
   Fills the empty upper right of the cost block with the two signs the section
   is about: the limit and the camera. A Y-axis flip rather than a crossfade,
   because the two faces are the same object seen from either side, which is how
   the pair reads on the road too.

   position:absolute inside .cost .shell, so it cannot disturb the grid below
   it. Hidden under 1000px, where the headline wraps into this exact space. */
.cost .shell{position:relative}
/* The headline has to be kept out of the sign's corner. Without a max-width it
   sets on one line above roughly 1400px and runs straight under the sign, which
   is how the first version covered the words "Urban Rider". Capping it forces
   the two-line set the block was designed around, so the corner is reliably
   free at every width instead of only narrow ones. */
.cost h2,.cost .lead{max-width:min(100%,680px)}
/* Sits beside the two-line headline rather than up in the corner against the
   divider rule, with clearance on both sides so it reads as a placed object and
   not as something that drifted into the margin. */
.signflip{position:absolute;top:clamp(30px,3.4vw,54px);right:clamp(26px,3.6vw,56px);
  width:clamp(118px,10.5vw,164px);aspect-ratio:1;perspective:1000px;pointer-events:none}
.signflip__inner{position:relative;width:100%;height:100%;transform-style:preserve-3d;
  animation:signflip 9s ease-in-out infinite}
.signflip__face{position:absolute;inset:0;width:100%;height:100%;
  backface-visibility:hidden;filter:drop-shadow(0 12px 26px rgba(22,24,27,.20))}
.signflip__face--cam{transform:rotateY(180deg)}

/* Long holds, short turns: the sign should read as a sign most of the time and
   only occasionally turn over. */
@keyframes signflip{
  0%,44%   {transform:rotateY(0deg)}
  50%,94%  {transform:rotateY(180deg)}
  100%     {transform:rotateY(360deg)}
}

/* No motion means no flip. The limit sign alone still fills the space and still
   says what the section is about. */
@media(prefers-reduced-motion:reduce){
  .signflip__inner{animation:none}
  .signflip__face--cam{display:none}
}

@media(max-width:1000px){
  .signflip{display:none}
}
