/* ============================================================================
   RF-SHELL — the one design layer every public Refuelia page shares.
   19 September 2026.

   WHY THIS FILE EXISTS.

   Counted from the working tree on the day it was written, across 544 public
   HTML files:

       6  different  <nav class="site-nav">  implementations
      13  different  <footer class="site-footer">  implementations
       2  different mobile bottom-navigation systems

   That is the whole of the "new homepage plus old site" feeling, and most of it
   predates the homepage rebuild: 418 city and country pages carry one footer,
   104 other pages carry a second, and eleven pages have one each of their own.
   No amount of work on individual pages fixes that. One shell does.

   WHAT IS IN HERE, AND WHAT IS DELIBERATELY NOT.

   IN:  the tokens, the header, the mobile drawer, the footer, breadcrumbs, and
        the three button styles — the chrome that wraps every page.

   NOT: anything that touches a page's own body. This file must be safe to drop
        onto a page whose content is still styled entirely by site.css, and the
        way it stays safe is by never setting a colour, a font or a spacing on
        anything outside the shell's own components. It does not restyle `body`,
        it does not touch headings, it does not redefine site.css's variables.
        A page adopting the shell gets a new frame around unchanged content.

   That restriction is what makes a 544-page migration a shell migration rather
   than a redesign nobody reviewed.

   TOKENS ARE DEFINED ONCE, HERE. home.css used to carry its own copy under the
   --rfh-* prefix; it now reads these. Two token systems is how a design system
   starts disagreeing with itself.
   ========================================================================= */

:root{
  /* ---- ground & surfaces ------------------------------------------------ */
  /* RF-ROAD-MARKING (23 September 2026). The owner, looking at his own site
     next to a Telegram feed full of the same mint-green pill buttons on dark
     navy: "нейрослоп". He was right — #07131B navy-teal plus a #20D6A0 pill is
     the default look of a generated landing page. The ground is now asphalt:
     neutral, very slightly warm, no blue in it. */
  --rf-bg:          #121314;
  --rf-bg-2:        #17181A;
  --rf-surface:     #1B1C1F;
  --rf-raised:      #232428;
  --rf-raised-2:    #2B2C31;

  /* ---- lines ------------------------------------------------------------ */
  --rf-line:        rgba(255,255,255,.10);
  --rf-line-strong: rgba(255,255,255,.17);
  --rf-line-faint:  rgba(255,255,255,.055);

  /* ---- ink -------------------------------------------------------------- */
  --rf-ink:         #F2F1EC;
  --rf-ink-2:       #A8A7A0;   /* 7.71 on --rf-bg */
  --rf-ink-3:       #8A8983;   /* 5.30 on --rf-bg (was 4.51) */

  /* ---- brand ------------------------------------------------------------ */
  /* Road-marking yellow. It is the colour of the line on the road a driver
     already follows, and — the reason it beats orange and red-orange — it is
     none of the five status colours: green means "fuel confirmed" and only
     that, so the brand may no longer be green. Measured:
         #FFC928 on --rf-bg          12.08
         #16140F on #FFC928          11.95   (text on a primary button)
         #16140F on #FFD659 (hover)  13.16   hover moves away from the ink */
  --rf-brand:       #FFC928;
  --rf-brand-hover: #FFD659;
  --rf-brand-ink:   #16140F;   /* text ON marking yellow */
  --rf-brand-dim:   rgba(255,201,40,.12);
  --rf-brand-edge:  rgba(255,201,40,.36);

  /* ---- status. Never decorative: each one means one thing. --------------- */
  --rf-ok:          #20D6A0;
  --rf-limited:     #F0A43A;
  --rf-out:         #E85B5B;
  --rf-unknown:     #7D8B94;
  --rf-ev:          #4D8CFF;
  --rf-ok-dim:      rgba(32,214,160,.14);
  --rf-limited-dim: rgba(240,164,58,.14);
  --rf-out-dim:     rgba(232,91,91,.14);
  --rf-unknown-dim: rgba(125,139,148,.16);
  --rf-ev-dim:      rgba(77,140,255,.14);

  /* ---- type ------------------------------------------------------------- */
  /* RF-ONE-TYPE-VOCABULARY (22 September 2026, Refuelia 2.0 phase 1).
     COUNTED before writing this, across the six stylesheets:

         three typefaces
         six token names for them
         47 rules naming a family literally, in four different spellings
           of the same mono stack

     --mono and --rf-mono were the same face reached by two names; --font,
     --sans and --rf-sans were a third and fourth name for Inter. A rule that
     spells out "'IBM Plex Mono',monospace" is not wrong, it is unreachable:
     changing the mono face meant finding 47 places, which is the same reason
     nobody ever changed it.

     THREE NAMES NOW, and they say what the type is FOR rather than what it is:
     a display face can be swapped without every heading rule mentioning
     Fraunces. Everything else below is an alias, kept because sweeping 47
     rules and six names in one pass is how a visual regression ships unseen —
     and an alias cannot drift.

     Custom properties resolve at USE time, so it does not matter that site.css
     loads first and refers forward to these. */
  /* RF-NOT-GENERATED (23 September 2026): ONE family. IBM Plex Sans for the
     interface and the headings — technical without being robotic, dense, made
     for tables and maps; Plex Mono (same superfamily) only for data: times,
     coordinates, codes. Inter and the Fraunces serif are gone. */
  --rf-display: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  --rf-text:    "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  --rf-mono:    "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --rf-sans: var(--rf-text);   /* alias */

  --rf-t-h1:    clamp(30px, 2.6vw, 44px);   /* RF-NOT-GENERATED: no billboard headlines */
  --rf-t-h2:    clamp(24px, 1.9vw, 32px);
  --rf-t-h3:    19px;
  --rf-t-body:  16px;
  --rf-t-lead:  17.5px;
  --rf-t-sm:    14px;
  --rf-t-xs:    13px;
  --rf-t-label: 11px;

  /* ---- spacing ---------------------------------------------------------- */
  --rf-1: 4px;  --rf-2: 8px;  --rf-3: 12px; --rf-4: 16px;
  --rf-5: 20px; --rf-6: 24px; --rf-7: 32px; --rf-8: 40px;
  --rf-9: 56px; --rf-10: 72px; --rf-11: 96px;

  /* ---- radius ----------------------------------------------------------- */
  /* RF-NOT-GENERATED: the owner's standard — small controls 6-8px, panels
     8-12px, a pill only for a control that behaves like a chip. A primary
     button is an 8px rectangle, never a capsule. */
  --rf-r-chip:  6px;
  --rf-r-ctl:   8px;
  --rf-r-card:  10px;
  --rf-r-panel: 12px;
  --rf-r-pill:  999px;

  /* ---- shadow: three levels, no more ------------------------------------ */
  --rf-sh-1: 0 1px 2px rgba(0,0,0,.30);
  --rf-sh-2: 0 8px 24px -8px rgba(0,0,0,.55);
  --rf-sh-3: 0 24px 60px -20px rgba(0,0,0,.70);

  /* ---- motion ----------------------------------------------------------- */
  /* One curve for everything. Refuelia has no bounce, no elastic and no
     overshoot: the product is about arriving, not about springing.
     Three bands, and nothing runs longer than the third — a one-second
     transition is not elegant, it is a wait. See GUIDELINES §H5. */
  /* RF-ONE-CLOCK-FOR-MOTION (22 September 2026). Counted across the six
     stylesheets before writing this: 60 distinct durations and 14 distinct
     easing curves, with a bare `ease` used 162 times. Three token sets existed
     — these, motion.css's --rf-m-ease, and whatever each rule reached for.
     Three sets is the same defect as three tab bars: a thing that should have
     one answer, answered in three places.

     The names below are the owner's, from the brief's motion section. The
     older --rf-fast / --rf-mid / --rf-slow stay as aliases rather than being
     swept out of 200-odd rules in one pass: an alias cannot drift, and a
     rename that touches every sheet at once is how a visual regression gets
     in without anyone seeing it.

     DIRECTIONAL EASING, and why it is not decoration. A surface arriving and a
     surface leaving are not the same event: a panel that slides in decelerates
     into place, because the eye needs to find it; the same panel leaving
     accelerates away, because the eye is already elsewhere. One symmetric
     curve for both makes an exit feel like a hesitation. --rf-ease-route is
     separate again: a route line is drawn, not moved, and a drawn line reads
     as machine work — near-linear, with only the last fraction eased. */
  --rf-ease-standard: cubic-bezier(.4,0,.2,1);    /* state, in place          */
  --rf-ease-enter:    cubic-bezier(.22,.61,.36,1); /* arriving: decelerate     */
  --rf-ease-exit:     cubic-bezier(.4,0,1,1);      /* leaving: accelerate away */
  --rf-ease-route:    cubic-bezier(.65,0,.35,1);   /* a line being drawn       */

  --rf-motion-fast:   .18s;   /* interaction: button, chip, tab, focus */
  --rf-motion-medium: .24s;   /* surface: drawer, sheet, panel swap    */
  --rf-motion-slow:   .38s;   /* composition: reveal, pin              */
  --rf-motion-route:  1.6s;   /* the route line, drawn once            */

  /* Aliases. One curve for everything was the old rule and it is still the
     default; Refuelia has no bounce, no elastic and no overshoot, because the
     product is about arriving, not about springing. Nothing runs longer than
     the third band — a one-second transition is not elegant, it is a wait.
     See GUIDELINES §H5. */
  --rf-ease:   var(--rf-ease-standard);
  --rf-fast:   var(--rf-motion-fast) var(--rf-ease-standard);
  --rf-mid:    var(--rf-motion-medium) var(--rf-ease-standard);
  --rf-slow:   var(--rf-motion-slow) var(--rf-ease-standard);

  /* ---- layout ----------------------------------------------------------- */
  --rf-wrap:    1320px;
  /* RF-WIDE-SCREEN (20 September 2026). 1320px is right on a laptop and looks
     abandoned on a desktop monitor. Measured on the owner's own screen while
     reviewing /guides:

         viewport   2560px
         container  1180px      46% used, 1380px of empty margin

     That is the "узкая колонка текста посреди огромного пустого экрана" in the
     brief, and it is not a stray min-height or an empty grid column — those were
     measured at zero on every page. It is simply a container sized for a 1440
     screen being shown on a 2560 one.

     The reading measure does NOT move with it. --rf-wrap-rd stays at 720px,
     because a 90-character line is unreadable at any screen size; what widens is
     the container that holds grids, directories, tables and map components, so
     three columns of guides become four instead of floating in the middle.
     Raising it at 1700px and above leaves every laptop exactly as it was. */
  --rf-wrap-wide: 1560px;
  /* Reading measure. Was 860px, which runs past 90 characters at 16px — past
     the point where the eye reliably finds the next line. 720px sits in the
     middle of the 680–780px band the guidelines fix (§30). Wide data, tables
     and map components use --rf-wrap, not this. */
  --rf-wrap-rd: 720px;
  --rf-header:  68px;
  --rf-gutter:  clamp(16px, 2.4vw, 32px);

  /* ---- PAPER: the reading surface ---------------------------------------
     RF-PAPER-IS-A-SURFACE-NOT-A-THEME (19 September 2026).

     Read docs/DESIGN_SYSTEM.md → "One site" before touching any of this. On
     8 September three pages were forced to data-theme="light" while 534 stayed
     dark, and the site changed colour when you clicked a tab. It was reversed
     on 9 September. The mistake was never light; it was a THEME per route.

     So this is a surface, not a theme. No page sets data-theme. A paper band
     is a section treatment inside whichever theme the visitor resolved, it is
     full-bleed so it reads as a change of ground rather than a white box
     dropped on a dark page, and the header, the footer and every route keep
     one identity.

     Contrast measured, not estimated, against --rf-paper:
         ink       #14202B   13.65
         ink-2     #3D4D5C    7.19
         ink-3     #525F69    5.42
         accent    #14202B   13.65   (ink; the marking yellow is 1.4 here — never text)
     ------------------------------------------------------------------------ */
  --rf-paper:        #F2F3F5;   /* RF-NOT-GENERATED: cool, never cream */
  --rf-paper-2:      #E8EAED;
  --rf-paper-ink:    #14202B;
  --rf-paper-ink-2:  #3D4D5C;
  --rf-paper-ink-3:  #525F69;
  --rf-paper-line:   rgba(20,32,43,.16);
  --rf-paper-line-2: rgba(20,32,43,.09);
  --rf-paper-accent: #14202B;
  --rf-paper-edge:   #26272A;   /* the hairline that joins paper to the dark */
}

/* RF-ONE-SURFACE (RF-2.0, 22 September 2026). site.css still defines the
   old dark palette under the legacy names: --surface-2 #182642 navy, --line-2
   at 40% blue, --brand #2EE6A8. Every component that was never migrated —
   the closing call to action on 15 pages, the FAQ items, the chat panel, the
   profile rows — painted itself navy on a green-black page, and that second
   palette is what made those pages look like a different product. The old
   names now resolve to the shell's tokens, so an unmigrated component takes
   the product's surface without being rewritten. The light theme and the
   paper band keep their own, more specific, mappings. */
:root:not([data-theme="light"]){
  --bg:var(--rf-bg); --bg-2:var(--rf-bg-2);
  --surface:var(--rf-surface); --surface-2:var(--rf-raised);
  --ink:var(--rf-ink); --ink-2:var(--rf-ink-2); --ink-3:var(--rf-ink-3);
  --line:var(--rf-line); --line-2:var(--rf-line-strong);
  --brand:var(--rf-brand); --brand-ink:var(--rf-brand-ink);
}

/* RF-PHONE-TYPE (20 September 2026). The brief said the phone was carrying
   desktop type. Measured on production at 375px BEFORE changing anything, and
   it is the opposite:

       section h2   27px     asked for 30-36
       card prose   14px     asked for 16-18
       lead         17.5px   already in range
       body         16px     already in range

   Nothing had been scaled down from desktop. --rf-t-h2 is
   clamp(30px, 2.4vw, 40px) and 2.4vw is nine pixels on a phone, so every phone
   sits on the clamp FLOOR: the smallest size the scale can produce, on the
   narrowest screen, where it is hardest to read. Raising the floor is the fix,
   and it is the only change the measurement supports.

   Scoped to the phone on purpose. Editing the token in :root would drag every
   laptop from 27px to 30px as a side effect of a mobile brief; here the desktop
   clamp is left exactly as it was. */
@media (max-width:767px){
  :root{ --rf-t-h2: clamp(24px, 1.9vw, 32px); }
}

/* Light theme — THE DEFAULT since 23 September 2026.
   RF-NOT-GENERATED (23 September 2026), the owner's written standard: "REFUELIA
   MUST NOT LOOK AI-GENERATED". Real white, not cream: #FFFFFF canvas and one
   cool neutral #F6F7F8. Graphite ink. Yellow is the BRAND (the logo, primary
   actions, selection, the active-nav mark) and never a text colour — it is
   1.54 on white. Status colours are DATA and a different system (§8 of the
   guidelines): no status is ever yellow, and the brand is never green.
   Measured:
       ink    #16181D on #FFFFFF   17.76      on #F6F7F8 16.5
       ink-2  #4A5059               8.13                  7.58
       ink-3  #646B75               5.38                  5.02
       #16181D on the #FFC928 button  11.53   hover #FFD659 12.70 */
:root[data-theme="light"]{
  --rf-bg:          #FFFFFF;
  --rf-bg-2:        #F6F7F8;
  --rf-surface:     #FFFFFF;
  --rf-raised:      #FFFFFF;
  --rf-raised-2:    #F6F7F8;
  --rf-line:        rgba(22,24,29,.12);
  --rf-line-strong: rgba(22,24,29,.22);
  --rf-line-faint:  rgba(22,24,29,.07);
  --rf-ink:         #16181D;
  --rf-ink-2:       #4A5059;
  --rf-ink-3:       #646B75;
  /* --rf-brand is what components use for TEXT, rules and outlines, so on white
     it is graphite; the yellow plate lives in --rf-cta-* and --rf-mark. */
  --rf-brand:       #16181D;
  --rf-brand-hover: #000000;
  --rf-brand-ink:   #FFFFFF;
  --rf-brand-dim:   rgba(255,201,40,.30);   /* selection: a yellow tint, graphite text */
  --rf-brand-edge:  rgba(22,24,29,.30);
  --rf-mark:        #FFC928;
  --rf-ok:          #0C8E69;
  --rf-limited:     #B4720C;
  --rf-out:         #C8332F;
  --rf-unknown:     #5E6E78;
  --rf-ev:          #2F63C7;
  --rf-ok-dim:      rgba(12,142,105,.11);
  --rf-limited-dim: rgba(180,114,12,.12);
  --rf-out-dim:     rgba(200,51,47,.10);
  --rf-unknown-dim: rgba(94,110,120,.12);
  --rf-ev-dim:      rgba(47,99,199,.10);
  /* Shadows only where a surface floats over the map and must separate from
     it; a section on the page gets a rule, not a shadow. */
  --rf-sh-1: 0 1px 2px rgba(22,24,29,.06);
  --rf-sh-2: 0 1px 3px rgba(22,24,29,.10);
  --rf-sh-3: 0 6px 20px -10px rgba(22,24,29,.22);
  --rf-cta-bg:       #FFC928;
  --rf-cta-bg-hover: #FFD659;   /* lighter = away from the graphite ink */
  --rf-cta-ink:      #16181D;
  --rf-cta-shadow:   none;

  /* The reading surface is the cool neutral, not paper-cream. */
  --rf-paper:        #F6F7F8;
  --rf-paper-2:      #EEF0F2;
  --rf-paper-ink:    #16181D;
  --rf-paper-ink-2:  #4A5059;
  --rf-paper-ink-3:  #646B75;
  --rf-paper-line:   rgba(22,24,29,.12);
  --rf-paper-line-2: rgba(22,24,29,.07);
  --rf-paper-accent: #16181D;
  --rf-paper-edge:   rgba(22,24,29,.10);
}

/* ---------------------------------------------------------------------------
   .rfs-paper — the reading surface, as one class.

   It repaints the ground AND remaps the ink variables the page's own
   components read, so a card, a link or a rule inside a paper band comes out
   right without a single component being rewritten for it. That remap is the
   whole trick: without it every .cp-card inside would keep its dark-theme ink
   and vanish.

   Full-bleed by design. A paper band that stops at the wrap's edge is a white
   box on a dark page; one that runs edge to edge is a change of ground.
   --------------------------------------------------------------------------- */
.rfs-paper{
  background:var(--rf-paper);
  color:var(--rf-paper-ink);
  border-top:1px solid var(--rf-paper-edge);
  border-bottom:1px solid var(--rf-paper-edge);

  /* shell vocabulary */
  --rf-bg:var(--rf-paper); --rf-bg-2:var(--rf-paper-2);
  --rf-surface:var(--rf-paper); --rf-raised:var(--rf-paper-2); --rf-raised-2:var(--rf-paper-2);
  --rf-ink:var(--rf-paper-ink); --rf-ink-2:var(--rf-paper-ink-2); --rf-ink-3:var(--rf-paper-ink-3);
  --rf-line:var(--rf-paper-line); --rf-line-strong:var(--rf-paper-line); --rf-line-faint:var(--rf-paper-line-2);
  --rf-brand:var(--rf-paper-accent); --rf-brand-hover:var(--rf-paper-accent); --rf-brand-ink:#FFFFFF;
  /* On paper the primary button is the same yellow plate with graphite ink
     (11.53); text and rules take the graphite accent. */
  --rf-cta-bg:#FFC928; --rf-cta-bg-hover:#FFD659; --rf-cta-ink:#16181D;
  --rf-brand-dim:rgba(255,201,40,.30); --rf-brand-edge:rgba(20,32,43,.30);

  /* RF-STATUS-ON-PAPER (22 September 2026). The band remapped every surface,
     ink and line token and left the STATUS colours behind, so a freshness ring
     inside a paper band kept its dark-ground green. Measured against
     --rf-paper #F4F1EA:

         --rf-ok       #20D6A0 (dark)   1.66      #0C8E69 (light)   3.66
         --rf-unknown  #7D8B94 (dark)   3.11      #5E6E78 (light)   4.68

     1.66 for the ring that means "a driver confirmed this" — the single most
     load-bearing colour in the product — against a 3.0 floor for a non-text
     indicator. Both light values already exist in the light-theme :root of
     this file; they were simply never carried into the band. */
  --rf-ok:var(--rf-ok-on-paper,#0C8E69); --rf-ok-dim:rgba(12,142,105,.11);
  --rf-unknown:var(--rf-unknown-on-paper,#5E6E78); --rf-unknown-dim:rgba(94,110,120,.12);

  /* site.css vocabulary — the older names the content pages still read */
  --bg:var(--rf-paper); --bg-2:var(--rf-paper-2);
  --surface:var(--rf-paper); --surface-2:var(--rf-paper-2);
  --ink:var(--rf-paper-ink); --ink-2:var(--rf-paper-ink-2); --ink-3:var(--rf-paper-ink-3);
  --ink-soft:var(--rf-paper-ink-3);
  --line:var(--rf-paper-line); --line-2:var(--rf-paper-line-2);
  --atlas-line:var(--rf-paper-line); --atlas-line-2:var(--rf-paper-line-2);
  --brand:var(--rf-paper-accent); --brand-2:var(--rf-paper-accent); --brand-deep:var(--rf-paper-accent);
  --brand-ink:#FFFFFF;
  --paper:var(--rf-paper); --paper-2:var(--rf-paper-2); --paper-3:var(--rf-paper-2);
  --shadow-color:rgba(20,32,43,.14);
}
/* Cards on paper are outlined, not filled: a filled card on a filled band is
   two surfaces doing one job, and that is the "card inside a card" the project
   already caught once on the city pages. */
.rfs-paper .cp-card,.rfs-paper .card,.rfs-paper .glass{
  background:transparent; backdrop-filter:none; -webkit-backdrop-filter:none;
  border:1px solid var(--rf-paper-line); box-shadow:none;
}
.rfs-paper .cp-card:hover,.rfs-paper .card:hover{
  border-color:var(--rf-paper-accent); box-shadow:none; transform:none;
}

/* ============================================================================
   SHELL PRIMITIVES
   Prefixed .rfs-* so they cannot collide with site.css or with the homepage's
   own .rfh-* components.
   ========================================================================= */
.rfs-wrap{width:100%; max-width:var(--rf-wrap); margin:0 auto; padding-inline:var(--rf-gutter); box-sizing:border-box}
.rfs-sr{position:absolute!important; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0}

/* ---- buttons ------------------------------------------------------------
   Moved to the RF-ONE-BUTTON block below, where .rfs-* shares its selector
   with .rf-btn rather than repeating it. Two definitions of one control was
   how the radius drifted: this block said --rf-r-ctl and the overlay said
   --rf-cta-radius, and the overlay's !important meant nobody saw it. */

/* ============================================================================
   RF-ONE-BUTTON (22 September 2026, Refuelia 2.0 phase 2)

   COUNTED first: 34 distinct button classes across the public pages, for what
   is three controls. Four of them already resolved to one look through the
   --rf-cta-* overlay further down this file — an overlay written with
   !important on four selectors, which is not a design decision, it is the
   scar left by four classes doing one job.

   .rf-btn is the component. Every legacy name is listed IN THE SAME SELECTOR,
   not redefined beside it: an alias that shares a rule cannot drift from it,
   while an alias that copies a rule is just the 35th button class. Pages move
   to .rf-btn at their own pace and look identical either way, which is the
   only safe way to touch 34 classes at once.

   THREE VARIANTS, and the brief's three jobs:
     --primary    the action the page exists for   (Open map, Search)
     --secondary  a real alternative               (Learn more, Details)
     --ghost      navigation and dismissal         (Cancel, Back, menu items)

   The overlay below still wins on primary, because it carries the measured
   contrast work (9.79:1 ink, hover that lightens rather than darkens). It
   comes out when the last page stops using .btn.primary, not before.
   ========================================================================= */
.rf-btn,
.rfs-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  min-height:var(--rf-cta-h,44px); padding:0 18px;
  border-radius:var(--rf-cta-radius,999px);
  font:600 15px/1 var(--rf-text); letter-spacing:-.008em;
  border:1px solid transparent; cursor:pointer; white-space:nowrap;
  text-decoration:none; box-sizing:border-box;
  transition:background var(--rf-motion-fast,.18s) var(--rf-ease-standard),
             border-color var(--rf-motion-fast,.18s) var(--rf-ease-standard),
             color var(--rf-motion-fast,.18s) var(--rf-ease-standard);
}
/* One optical size for the glyph in every button, at the icon family's own
   grid. A 22px icon in a 44px control is the difference nobody can name. */
.rf-btn svg,
.rfs-btn svg{ width:18px; height:18px; flex:0 0 auto }

.rf-btn--primary,
.rfs-btn--primary{ background:var(--rf-cta-bg,var(--rf-brand)); color:var(--rf-cta-ink,var(--rf-brand-ink)) }
.rf-btn--primary:hover,
.rfs-btn--primary:hover{ background:var(--rf-cta-bg-hover,var(--rf-brand-hover)) }

.rf-btn--secondary,
.rfs-btn--secondary{ background:transparent; color:var(--rf-ink); border-color:var(--rf-line-strong) }
.rf-btn--secondary:hover,
.rfs-btn--secondary:hover{ background:var(--rf-raised); border-color:var(--rf-brand-edge) }

/* Ghost carries no border at rest. It is for controls that must be reachable
   and must not compete: a border here would make every menu item an object. */
.rf-btn--ghost{ background:transparent; color:var(--rf-ink-2); border-color:transparent }
.rf-btn--ghost:hover{ background:var(--rf-raised); color:var(--rf-ink) }

.rf-btn--block, .rfs-btn--block{ width:100% }
.rf-btn--sm, .rfs-btn--sm{ min-height:var(--rf-cta-h-md,38px); padding:0 15px; font-size:var(--rf-t-sm) }

/* Focus is one ring for all three, and it is never removed — the brief's
   accessibility line, and the reason :focus-visible is not left to the page. */
.rf-btn:focus-visible,
.rfs-btn:focus-visible{ outline:2px solid var(--rf-brand); outline-offset:2px }

/* ============================================================================
   RF-ONE-ICON-LANGUAGE (22 September 2026, Refuelia 2.0 phase 3)

   COUNTED on the 24x24 grid, across the public pages: 123 inline icons wearing
   EIGHT stroke weights.

       1.8 x70   2 x34   2.2 x22   1.75 x20   1.9 x18   2.1 x4   2.6 x2   1.7 x2

   None of them was chosen. Somebody typed 2.2 on map.html twelve times and 1.75
   on guides.html eight times, and two icons side by side at those weights read
   as two different products while nobody can say why. It is the plainest single
   cause of the "different visual languages" in the brief.

   WHY THIS IS ONE RULE AND NOT 123 EDITS. An SVG presentation attribute —
   stroke-width="2.2" written on the path itself — sits BELOW every CSS rule in
   the cascade, including a rule of zero specificity. So one :where() block
   corrects every icon already on every page, with no file touched, no sweep to
   run and nothing to re-stamp. :where() rather than a plain selector so a page
   that has a real reason to differ can still say so with one ordinary class.

   WHAT IT DELIBERATELY DOES NOT TOUCH. The map pin's glyph is drawn inside
   viewBox="0 0 34 40" and scaled 0.62, where stroke-width 2.1 renders as 1.3 —
   tuned against the pin, not against this grid. Scoping to the 24x24 viewBox
   leaves it alone, which is why the selector names the viewBox and not `svg`.
   ========================================================================= */
:root{ --rf-icon-stroke: 1.8; }

:where(svg[viewBox="0 0 24 24"]){
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: var(--rf-icon-stroke);
}
/* The weight is usually written on the paths, not on the svg, and an inherited
   value loses to an attribute on the child. Both ends, one number. */
:where(svg[viewBox="0 0 24 24"]) :where(path, line, polyline, polygon, circle, rect, ellipse){
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: var(--rf-icon-stroke);
}

/* The family itself: <svg class="rf-i"><use href="#rf-i-fuel"/></svg>.
   Three optical sizes, because an icon beside 15px button text and an icon
   leading a section heading are not the same size even when they are the same
   shape. currentColor throughout — an icon never carries a colour of its own. */
.rf-i{
  width:20px; height:20px; flex:0 0 auto; display:inline-block;
  fill:none; stroke:currentColor; color:inherit; vertical-align:-.22em;
}
.rf-i--sm{ width:18px; height:18px }
.rf-i--lg{ width:24px; height:24px }
/* The sprite is a <defs> carrier and must never occupy space or be read out. */
.rf-i-sprite{ position:absolute; width:0; height:0; overflow:hidden }

/* RF-SEVEN-FAMILIES — a fuel family, named, wherever it is named.
   One dot, one colour, one spelling, on the station page and anywhere else a
   fuel is written out in prose. It is the legend's swatch at text size, on
   purpose: a driver who learned the violet dot on the map reads the same dot
   here. The grades that are not families — octane numbers, E85, AdBlue — stay
   plain text rather than borrowing a colour that would imply they are one. */
.rf-fuelfam{ display:inline-flex; align-items:center; gap:6px; white-space:nowrap }
.rf-fuelfam i{ width:8px; height:8px; border-radius:50%; flex:0 0 auto; background:var(--pin-unknown) }
.rf-fuelfam--petrol i{ background:var(--pin-petrol) }
.rf-fuelfam--diesel i{ background:var(--pin-diesel) }
.rf-fuelfam--lpg i{ background:var(--pin-lpg) }
.rf-fuelfam--cng i{ background:var(--pin-cng) }
.rf-fuelfam--lng i{ background:var(--pin-lng) }
.rf-fuelfam--hydrogen i{ background:var(--pin-hydrogen) }
.rf-fuelfam--ev i{ background:var(--pin-ev) }
/* The popup's availability row is already a laid-out row in site.css. It takes
   the DOT from this vocabulary and none of the layout — writing
   display:inline-flex onto it would collapse a three-column row into a line.
   Found by reading .fa-row before adding the class, which is the lesson from
   the .rfh-trust collision three days ago: a shared class name is a shared
   layout unless you say otherwise. */
.fa-row.rf-fuelfam{ display:flex; white-space:normal }

/* ============================================================================
   RF-ONE-MARKER (22 September 2026, Refuelia 2.0 phase 4)

   The stylesheet half of assets/js/marker.js. One component, three sizes, and
   the same two sentences at every size: the BODY says what the station sells,
   the COLLAR says who checked it. Neither ever overwrites the other.

   The legacy names (.pin-ring, .rfh-pin, .rf-pin-core) are emitted on the same
   elements and keep their existing rules in site.css and home.css. They are not
   duplicated here; this block styles the new names and the states, and the two
   sets share one element until the old names come out.
   ========================================================================= */
.rf-mk{ position:relative; display:block; line-height:0 }
.rf-mk svg{ display:block; overflow:visible }

/* The body. Colour arrives from the tint-* class, which both maps already use
   and which resolves to a --pin-* token. */
.rf-mk .rf-mk-core{ fill:var(--pin-core) }
.rf-mk .rf-mk-core--split{ fill:none }

/* WHICH TINT PAINTS WHICH COLOUR — and why it had to move here.
   Until today this mapping existed once, in site.css, written as
   `.pin-ring.tint-petrol .rf-pin-core`. `pin-ring` is a legacy class that
   marker.js emits ONLY on the lg variant, for the cluster counter's anchored
   regex. So /map was coloured and any other size resolved to the
   --pin-core fallback above: one dark neutral for every station.

   Found by reading the stylesheet before wiring the home map, not after —
   the sm variant would have shipped 400 identical charcoal pins and looked
   like a data outage. The component owns its own colours now, at every size.
   The site.css block stays: same tokens, same values, different selector, and
   it is what a cached map.js still matches. Identical declarations, so which
   one wins is not a question that has to have an answer.

   tint-multi is absent on purpose: two fuels are painted by the two
   rf-mk-half paths, and --split above keeps the collar circle hollow. */
.rf-mk.tint-petrol  .rf-mk-core{ fill:var(--pin-petrol) }
.rf-mk.tint-diesel  .rf-mk-core{ fill:var(--pin-diesel) }
.rf-mk.tint-lpg     .rf-mk-core{ fill:var(--pin-lpg) }
.rf-mk.tint-cng     .rf-mk-core{ fill:var(--pin-cng) }
.rf-mk.tint-ev      .rf-mk-core{ fill:var(--pin-ev) }
.rf-mk.tint-service .rf-mk-core{ fill:var(--pin-service) }
.rf-mk.tint-parking .rf-mk-core{ fill:var(--pin-parking) }
.rf-mk.tint-lng     .rf-mk-core{ fill:var(--pin-lng) }
.rf-mk.tint-hydrogen .rf-mk-core{ fill:var(--pin-hydrogen) }
.rf-mk.tint-station .rf-mk-core{ fill:var(--pin-station) }
.rf-mk .rf-mk-glyph{ color:#04231A }
/* LNG joins the white-glyph group on 22 September 2026: measured, the dark
   ink scores 2.39 on #7E22CE and white scores 6.98. Hydrogen keeps the dark
   ink at 9.95 and is therefore absent from this list on purpose. */
.rf-mk.tint-lng     .rf-mk-glyph,
.rf-mk.tint-station .rf-mk-glyph,
.rf-mk.tint-service .rf-mk-glyph,
.rf-mk.tint-parking .rf-mk-glyph{ color:#FFFFFF }

/* The collar — status, and the one rule that must stay weakest for `scheduled`.
   A timetable is not a driver check, so it is thinner AND dashed, and its tail
   stays grey. If those two treatments ever converge the refusal is gone. */
/* RF-RING-IS-NOT-THE-BODY (22 September 2026): the collar is its own circle
   (.rf-mk-ring, drawn by marker.js outside the body), separated from the body
   by a hairline of ground, and painted with the §8 status tokens — the same
   four the legend, the cards and the stamps use. Before this the collar was a
   stroke on the body in the old --green/--amber/--red, which disagreed with
   the legend swatches and disappeared on a green petrol body. */
.rf-mk .rf-mk-ring{ fill:none; stroke:none }
.rf-mk .rf-mk-core{ stroke:var(--rf-bg); stroke-width:1.2 }
.rf-mk.is-available   .rf-mk-ring{ stroke:var(--rf-ok);      stroke-width:2.4 }
.rf-mk.is-limited     .rf-mk-ring{ stroke:var(--rf-limited); stroke-width:2.4 }
.rf-mk.is-unavailable .rf-mk-ring{ stroke:var(--rf-out);     stroke-width:2.4 }
/* A timetable is weaker than any check: thinner, dashed, and in no status
   colour at all, because "the posted hours say open" is not "available". */
.rf-mk.is-scheduled   .rf-mk-ring{ stroke:var(--rf-ink-2);   stroke-width:1.4; stroke-dasharray:2.4 2.4 }
.rf-mk.is-unknown     .rf-mk-ring{ stroke:none }

.rf-mk .rf-mk-tail{ fill:var(--pin-unknown) }
.rf-mk.is-available   .rf-mk-tail{ fill:var(--rf-ok) }
.rf-mk.is-limited     .rf-mk-tail{ fill:var(--rf-limited) }
.rf-mk.is-unavailable .rf-mk-tail{ fill:var(--rf-out) }

/* site.css still sizes every svg inside the legacy .pin-badge (which the lg pin
   carries for map.js's cluster counter) as the old 14px rotated square. The lg
   pin is the one pin now, on / as on /map, so its geometry is stated once here
   rather than overridden page by page. */
.rf-mk--lg.pin-badge > svg{ transform:none; width:34px; height:40px }
.rf-mk--lg.pin-badge .rf-mk-glyph{ transform:none; width:14.9px; height:14.9px }

/* RF-CARD-PIN-SYNC (H6.A): a station hovered or focused in a list, or opened,
   and its pin, emphasise together. A half step of scale and a halo of the
   brand ring, 180ms in and out. Nothing moves, nothing zooms. */
.rf-mk::after{ content:""; position:absolute; left:50%; top:var(--rf-mk-cy,15px); width:var(--rf-mk-halo,32px); height:var(--rf-mk-halo,32px);
  border-radius:50%; transform:translate(-50%,-50%) scale(.6); opacity:0; pointer-events:none;
  box-shadow:0 0 0 2px var(--rf-brand), 0 0 0 7px var(--rf-brand-dim);
  transition:opacity var(--rf-motion-fast,.18s) var(--rf-ease-standard), transform var(--rf-motion-fast,.18s) var(--rf-ease-standard) }
.rf-mk--sm{ --rf-mk-cy:11.5px; --rf-mk-halo:25px }
.rf-mk--card{ --rf-mk-cy:10px; --rf-mk-halo:22px }
.rf-mk.is-hot, .rf-mk.is-linked{ transform:translateY(-2px) scale(1.14); z-index:2 }
.rf-mk.is-hot::after, .rf-mk.is-linked::after{ opacity:1; transform:translate(-50%,-50%) scale(1) }
.leaflet-marker-icon:has(.rf-mk.is-hot), .leaflet-marker-icon:has(.rf-mk.is-linked){ z-index:100000 !important }
/* the list half of the same object: /map's result rows and the home cards */
.explore-result-item.is-linked, .rfh-st.is-linked{ box-shadow:inset 3px 0 0 var(--rf-brand); background:var(--rf-surface-2, rgba(127,127,127,.06)) }
/* scheduled keeps the grey tail on purpose — see above. */

/* Freshness is a SECOND axis, not a fourth status: a report can be available
   and ageing at once. It fades the pin; it never changes what the pin says. */
.rf-mk.fresh-fading{ opacity:.72 }
.rf-mk.fresh-expired{ opacity:.55 }

/* ---- motion ------------------------------------------------------------
   Four states, each explaining something that happened. Every one is finite:
   the resting state of a map is still, and a map that breathes is a map you
   cannot read. All of it runs on transform and opacity only, so it never
   costs the map a layout while panning. */

/* 1. arriving. A pin that appears without a transition reads as a glitch when
      four hundred of them land at once. 140ms, and it is over. */
@keyframes rfMkIn{ from{ opacity:0; transform:scale(.82) } to{ opacity:1; transform:scale(1) } }
.rf-mk--enter{ animation:rfMkIn var(--rf-motion-fast,.18s) var(--rf-ease-enter) both }

/* 2. a fresh report landing. TWO pulses, then still — the ripple says
      "this just changed", and an infinite pulse would say "look here" forever. */
@keyframes rfMkPulse{
  0%{ box-shadow:0 0 0 0 color-mix(in srgb, var(--green) 55%, transparent) }
  70%{ box-shadow:0 0 0 10px transparent }
  100%{ box-shadow:0 0 0 0 transparent }
}
.rf-mk--pulse{ border-radius:50%; animation:rfMkPulse .9s var(--rf-ease-exit) 2 }

/* 3. pointer. Desktop only: a hover state on a touch screen fires on tap and
      then sticks, which is how a map ends up with a stuck highlighted pin. */
@media (hover:hover) and (pointer:fine){
  .rf-mk{ transition:transform var(--rf-motion-fast,.18s) var(--rf-ease-standard) }
  .rf-mk:hover{ transform:translateY(-2px) scale(1.06) }
}
/* 4. touch. The finger covers the pin, so the feedback has to outlive the tap
      by a moment and be visible around the fingertip rather than under it. */
.rf-mk--tap{ animation:rfMkIn .12s var(--rf-ease-exit) both }

/* Clusters grow and shrink rather than jumping between counts. */
.rf-mk--cluster{ transition:transform var(--rf-motion-medium,.24s) var(--rf-ease-enter) }

@media (prefers-reduced-motion:reduce){
  .rf-mk--enter, .rf-mk--pulse, .rf-mk--tap{ animation:none }
  .rf-mk, .rf-mk--cluster{ transition:none }
  .rf-mk:hover{ transform:none }
  .rf-mk::after{ transition:none }
}
/* the hot state needs its transform transition on touch screens too */
.rf-mk{ transition:transform var(--rf-motion-fast,.18s) var(--rf-ease-standard) }
@media (prefers-reduced-motion:reduce){ .rf-mk{ transition:none } .rf-mk.is-hot, .rf-mk.is-linked{ transform:none } }

/* ============================================================================
   GLOBAL HEADER
   The class hooks (.site-nav, .nav-links, .nav-toggle, .nav-close, .nav-right)
   are the LEGACY names on purpose: assets/js/main.js binds the mobile drawer to
   them on every page, and this migration is not the moment to also rewrite the
   script that opens the menu. New look, same hooks, one implementation.
   ========================================================================= */
body .site-nav.rfs-nav{
  position:sticky; top:0; z-index:60;
  height:var(--rf-header); display:flex; align-items:center;
  /* Slightly more present than the first pass: at 88% the bar dissolved into
     the hero and read as floating text rather than a header. 94% plus a real
     hairline is a surface without becoming a heavy band. No glow, no gradient,
     no shadow — GUIDELINES §7. */
  background:color-mix(in srgb, var(--rf-bg) 94%, transparent);
  -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
  border-bottom:1px solid var(--rf-line);
  padding:0; margin:0; box-shadow:none; border-top:0; border-inline:0;
  font-family:var(--rf-text);

  /* RF-THE-HEADER-CAN-BE-CLICKED (20 September 2026). THE BUG THIS FILE
     SHIPPED, and it was mine.

     site.css still carries the OLD header's rule:

         .site-nav{ ... pointer-events:none }
         .site-nav .wrap{ pointer-events:auto; ... }

     That pair was correct for a floating pill: the <nav> spanned the full width
     but was transparent, so clicks fell through to the page, and the pill —
     .wrap — took them back. A1 renamed the inner wrapper to .rfs-wrap. The
     second rule stopped matching anything, the first kept applying, and the
     whole header inherited pointer-events:none.

     Measured on production with document.elementFromPoint at each control's own
     centre:

         brand            -> BODY.rfh     dead
         Open the map     -> BODY.rfh     dead   <- the primary CTA
         account button   -> BODY.rfh     dead
         Map / Fuel prices / Guides / How it works / Sign in  -> SELF

     The five that worked are the ones inside .nav-links, which re-enables
     pointer-events on its own. Everything else had been unclickable on all 538
     pages since A1 shipped — including the button the whole homepage points at.

     The shell header is a full-width bar now, not a floating pill, so nothing
     should be falling through it at all. */
  pointer-events:auto;
}
.rfs-nav .rfs-wrap{display:flex; align-items:center; gap:var(--rf-6); pointer-events:auto}
.rfs-nav .rfs-wrap > *{pointer-events:auto}
.rfs-nav .brand{
  display:inline-flex; align-items:center; gap:10px;
  font:600 18px/1 var(--rf-sans); letter-spacing:-.03em; color:var(--rf-ink);
  /* The whole brand area is the link — mark and wordmark together — and it is
     a real <a href="/">, so middle-click and "open in new tab" behave. The
     padding is the hit area: the text box alone measured 109x30, and 30px is
     under the 44px a thumb needs. GUIDELINES §19. */
  margin:0; padding:7px 10px 7px 0; text-decoration:none; flex:0 0 auto;
  min-height:44px; pointer-events:auto;
}
.rfs-nav .brand:hover{color:var(--rf-ink)}
.rfs-nav .brand .mark{width:30px; height:30px; border-radius:8px; flex:0 0 auto}
.rfs-nav .nav-right{display:flex; align-items:center; gap:var(--rf-3); margin-left:auto}
.rfs-nav .nav-links{
  display:flex; align-items:center; gap:2px; list-style:none; margin:0; padding:0;
  background:none; border:0; box-shadow:none; position:static; transform:none;
  width:auto; height:auto; max-height:none; inset:auto; visibility:visible;
  pointer-events:auto; border-radius:0; backdrop-filter:none; -webkit-backdrop-filter:none;
}
.rfs-nav .nav-links > li{margin:0; padding:0; list-style:none}/* :not(.rfs-btn) is load-bearing. Without it this rule — one class more
   specific than .rfs-btn--primary — stripped the background off the drawer's
   "Open the map" button and rendered the site's only phone CTA as grey text.
   Seen on the first 390px screenshot of the drawer. */
.rfs-nav .nav-links a:not(.rfs-btn),
/* :not(.rfs-btn) is load-bearing. Without it this rule — one class more
   specific than .rf-btn--primary — stripped the background off the drawer's
   "Open the map" button and rendered the site's only phone CTA as grey text.
   Seen on the first 390px screenshot of the drawer. */
.rfs-nav .nav-links a:not(.rfs-btn){
  display:block; padding:9px 12px; border-radius:var(--rf-r-chip);
  font:500 var(--rf-t-sm)/1.2 var(--rf-sans); color:var(--rf-ink-2);
  text-decoration:none; border:0; background:none; box-shadow:none;
  transition:color var(--rf-fast), background var(--rf-fast);
}
.rfs-nav .nav-links a:not(.rfs-btn):hover{color:var(--rf-ink); background:var(--rf-raised)}
/* Active page. Colour plus a weight change, so it is not carried by hue alone. */
.rfs-nav .nav-links a[aria-current="page"]:not(.rfs-btn){color:var(--rf-ink); font-weight:650; background:var(--rf-raised)}
.rfs-nav .nav-signin a{color:var(--rf-ink-2)}

/* RF-ONE-AUTH-STATE (20 September 2026). Measured on production, signed in:
   the header showed the static "Sign in" link AND the account avatar at the
   same time — the site telling a signed-in driver to sign in, next to his own
   photograph. GUIDELINES §4 forbids exactly this pair.

   auth.js injects .auth-slot into .nav-right and it is the authority on auth
   state: a sign-in button when signed out, an avatar and its menu when signed
   in. The static link is the fallback for the case where auth is not
   configured at all, and it stands down as soon as the real control exists.

   Desktop only. In the drawer the slot is not rendered, so that item stays —
   auth.js relabels it instead, because "Sign in" is a lie once you are. */
/* RF-ONE-AUTH-STATE, corrected (20 September 2026).

   This rule stands the static "Sign in" row down once auth.js has injected the
   real control, so a signed-in driver is not told to sign in next to his own
   photograph. That was right on desktop and WRONG everywhere else, and it was
   my own regression from the header pass.

   Measured on production, 375px, signed OUT, drawer open:

       .auth-slot            display:none   0x0   (it lives in .nav-right,
                                                   which is hidden on phones)
       .auth-signin-btn      0x0            inside that hidden slot
       li.nav-signin         display:none         ← stood down for a control
                                                    that is not on screen

   .nav-links is inside .nav-right, so :has(.auth-slot) matched the drawer's row
   too. The result: on a phone there was no way to sign in or reach an account
   at all — the drawer showed Map, Fuel prices, Guides, How it works and Open
   the map, and nothing else.

   A rule that hides one control because another exists has to be scoped to
   where that other control is actually VISIBLE. Below the drawer breakpoint the
   drawer's own row is the only auth control there is. */
@media (min-width:768px){
  .rfs-nav .nav-right:has(.auth-slot) .nav-signin{display:none}
}
/* The drawer's CTA is an <a> inside .nav-links, so site.css's own link rules
   reach it and were painting near-white text on the emerald fill — about 1.9:1,
   which fails AA by a wide margin and is the one control on a phone that has to
   be readable. Stated here at a specificity that wins; #04231A on #20D6A0 is
   roughly 10:1. */
.rfs-nav .nav-links a.rfs-btn--primary,
.rfs-nav .nav-links a.rf-btn--primary{color:var(--rf-brand-ink); font-weight:600}
.rfs-nav .nav-links a.rfs-btn--primary:hover,
.rfs-nav .nav-links a.rf-btn--primary:hover{color:var(--rf-brand-ink)}
.rfs-nav .nav-drawer-head,.rfs-nav .nav-close,.rfs-nav .nav-drawer-cta{display:none}
.rfs-nav .rfs-nav-cta{min-height:38px; padding:0 15px; font-size:var(--rf-t-sm)}
/* RF-NO-CTA-TO-WHERE-YOU-ARE. "Open the map" is the site's primary call to
   action and it is pointless on /map: a driver already looking at the map does
   not need a button that reloads it. The page marks its own nav item with
   aria-current, so the header can tell without a per-page class. */
.rfs-nav .nav-links a[data-nav="map"][aria-current="page"] ~ * .rfs-nav-cta,
body:has(.rfs-nav a[data-nav="map"][aria-current="page"]) .rfs-nav .rfs-nav-cta,
body:has(.rfs-nav a[data-nav="map"][aria-current="page"]) .rfs-nav .nav-drawer-cta{display:none}
.rfs-nav .nav-toggle{
  display:none; width:44px; height:44px; padding:0; border-radius:var(--rf-r-ctl);
  background:transparent; border:1px solid var(--rf-line); cursor:pointer;
  flex-direction:column; align-items:center; justify-content:center; gap:4px;
}
.rfs-nav .nav-toggle span{
  display:block; width:17px; height:1.7px; border-radius:2px; background:var(--rf-ink);
  transition:transform var(--rf-mid), opacity var(--rf-fast);
}

/* ============================================================================
   BREADCRUMBS — content pages only. The map is a product screen and has none.
   ========================================================================= */
.rfs-crumbs{
  font:500 var(--rf-t-xs)/1.5 var(--rf-sans); color:var(--rf-ink-3);
  padding-block:var(--rf-4) 0; margin:0;
}
.rfs-crumbs ol{display:flex; flex-wrap:wrap; align-items:center; gap:6px; list-style:none; margin:0; padding:0}
.rfs-crumbs li{display:inline-flex; align-items:center; gap:6px}
.rfs-crumbs li + li::before{content:"›"; color:var(--rf-ink-3); opacity:.7}
.rfs-crumbs a{color:var(--rf-ink-2); text-decoration:none}
.rfs-crumbs a:hover{color:var(--rf-brand); text-decoration:underline; text-underline-offset:2px}
.rfs-crumbs [aria-current="page"]{color:var(--rf-ink-3)}

/* ============================================================================
   GLOBAL FOOTER — four columns, not a sitemap
   ========================================================================= */
body .site-footer.rfs-footer{
  background:var(--rf-bg-2); border-top:1px solid var(--rf-line);
  padding-block:var(--rf-9) var(--rf-6); margin:0;
  font-family:var(--rf-text); color:var(--rf-ink-2);
}
/* RF-FOOTER-2.0 (22 September 2026). Replaces RF-FOOTER-CENTRED of 20
   September, and that note is worth keeping because it was right about the
   fault it fixed and wrong about the fix.

   It read: the tracks were 1.6fr 1fr 1fr 1fr, so on a wide monitor the brand
   column got a slot far wider than the 36ch inside it — brand hard left, a
   hole, three columns pushed right. True. The answer taken was to size the
   columns to their content and CENTRE the group.

   MEASURED at 1440 two days later:

       grid-template-columns   343px 108px 104px 130px
       justify-content         center
       wrap                    1320px
       width actually used     901px
       brand starts at         x269

   419px of the wrap unused, the whole block floating in the middle, and the
   three columns ragged at 108 / 104 / 130 because max-content sizes each list
   to its longest link. Meanwhile every scene of the 2.0 homepage begins hard
   against the wrap's left edge at x92. The page walks down one axis and the
   footer steps into the middle of the road: that single declaration is most of
   what the owner called "an old website footer".

   The real problem in the earlier note was never the fractions — it was that
   1.6fr promised the brand more room than it had words for. So: the brand
   keeps a larger share because it holds a sentence AND a button, the three
   link columns are equal because they are peers, and the group starts where
   the page starts. 1256 of 1320px used, columns 241 / 241 / 241.

   Nothing in footer.tpl changed. Same 27 links, same class names, same order —
   this is a stylesheet change, so all 548 pages take it without a sweep, and
   shell-parity has nothing new to compare. */
.rfs-footer .footer-grid{
  display:grid;
  /* RF-FOOTER-B: brand + four intent columns (Use, Learn, Take part, Refuelia). */
  grid-template-columns:minmax(0,1.35fr) repeat(4, minmax(0,1fr));
  justify-content:start; gap:var(--rf-7) clamp(var(--rf-6), 4vw, 72px);
  align-items:start;
  padding:0; border:0; margin:0;
}
/* Stated, not inherited. A left-aligned grid above a centred compliance row is
   the same mixed-axis fault one line further down the page. */
.rfs-footer .footer-legal,
.rfs-footer .footer-base{justify-content:flex-start; text-align:left}

/* THE ROAD LANDS — homepage only, and deliberately so.
   The 2.0 homepage carries one line from under the hero's map through five
   scenes; scene 05 ends it at this footer's top edge, and these 96px are the
   last of it turning horizontal. On /map, /about, /contact or /rewards there
   is no such line, and drawing its ending there would be a decoration
   pretending to be a continuation. body.rfh is the homepage and only the
   homepage — checked, one file out of 548. */
body.rfh .site-footer.rfs-footer{position:relative}
/* RF-NOT-GENERATED (23 September 2026): the 96px stub is gone. The owner
   circled it on production as a bug — a dark dash on the footer's top edge,
   joined to nothing at his screen width, right under the Google card. An
   ending that only lines up at one viewport is decoration, and the standard
   bans decoration that pretends to be structure. */
body.rfh .site-footer.rfs-footer::before{content:none; display:none}
.rfs-footer .footer-brand .brand{
  display:inline-flex; align-items:center; gap:9px;
  font:600 17px/1 var(--rf-sans); letter-spacing:-.03em; color:var(--rf-ink); text-decoration:none;
}
.rfs-footer .footer-brand .brand .mark{width:26px; height:26px; border-radius:7px}
.rfs-footer .footer-brand p{
  color:var(--rf-ink-2); font-size:var(--rf-t-xs); line-height:1.6;
  margin:var(--rf-3) 0 0; max-width:36ch;
}
/* h2 is kept alongside .footer-col-h only so a browser holding a cached copy of
   an older page does not lose the label styling for one revalidation. The
   markup ships .footer-col-h; see footer.tpl, RF-FOOTER-OUTLINE. */
.rfs-footer .footer-col h2,
.rfs-footer .footer-col .footer-col-h{
  font:600 var(--rf-t-label)/1 var(--rf-mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--rf-ink-3); margin:0 0 var(--rf-4); padding:0; border:0;
}
.rfs-footer .footer-col ul{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:9px}
.rfs-footer .footer-col li{margin:0}
.rfs-footer .footer-col a,.rfs-footer .footer-col button{
  font:400 var(--rf-t-xs)/1.4 var(--rf-sans); color:var(--rf-ink-2);
  background:none; border:0; padding:0; cursor:pointer; text-align:left;
  text-decoration:none; transition:color var(--rf-fast);
}
.rfs-footer .footer-col a:hover,.rfs-footer .footer-col button:hover{color:var(--rf-brand)}
.rfs-footer .footer-brand .footer-cta{margin-top:var(--rf-4)}
/* RF-OWNER-NAMED: the two official profiles, one quiet line under the pitch. */
.rfs-footer .footer-brand .footer-follow{display:flex; flex-wrap:wrap; gap:4px 12px; align-items:baseline}
.rfs-footer .footer-brand .footer-follow a{color:var(--rf-ink-2); text-decoration:underline; text-underline-offset:2px}
.rfs-footer .footer-brand .footer-follow a:hover{color:var(--rf-ink)}

/* The compliance row. Eight policies, one wrapping line — see
   RF-FOOTER-FIVE-IN-FOUR in footer.tpl for why this stopped being a column. */
.rfs-footer .footer-legal{
  display:flex; flex-wrap:wrap; gap:var(--rf-2) var(--rf-5);
  margin-top:var(--rf-8); padding-top:var(--rf-5);
  border-top:1px solid var(--rf-line-faint);
}
.rfs-footer .rfs-trust + .footer-legal{margin-top:0}
.rfs-footer .footer-legal a,
.rfs-footer .footer-legal button{
  font:400 var(--rf-t-xs)/1.4 var(--rf-sans); color:var(--rf-ink-3);
  background:none; border:0; padding:0; cursor:pointer;
  text-decoration:none; transition:color var(--rf-fast);
}
.rfs-footer .footer-legal a:hover,
.rfs-footer .footer-legal button:hover{color:var(--rf-brand)}

/* RF-TRUST-ROW (26 September 2026) — where the numbers come from, and how the
   one payment on the site is taken. A list with rules, not cards (the
   RF-NOT-GENERATED standard); mono labels like the column heads above; the
   payment names are set as neutral plates in the site's own type, never as the
   card networks' logos. See footer.tpl for what may be listed here. */
.rfs-footer .rfs-trust{margin-top:var(--rf-8)}
/* RF-FOOTER-B (26 September 2026): two single lines under the columns, each
   with its label on the left, the facts in the middle and its one link on the
   right - "where the numbers come from" as a row of flags, each flag a link to
   that official source, and "payments" as three plates. The full table with
   schedules and licences lives at /fuel-prices#sources. */
.rfs-footer .rfs-trust-line{
  /* The same tracks and gap as .footer-grid (1.35fr + four 1fr), so the flags
     and the plates start exactly where the link columns start. */
  display:grid; grid-template-columns:minmax(0,1.35fr) repeat(4, minmax(0,1fr));
  column-gap:clamp(var(--rf-6), 4vw, 72px); row-gap:var(--rf-3); align-items:center;
  padding:var(--rf-5) 0; border-top:1px solid var(--rf-line-faint);
}
.rfs-footer .rfs-trust-mid{grid-column:2 / -1; display:flex; flex-wrap:wrap; align-items:center; gap:var(--rf-3) var(--rf-6); min-width:0}
.rfs-footer .rfs-trust-mid > .rfs-src-all{margin-left:auto}
.rfs-footer .rfs-trust-h{
  font:600 var(--rf-t-label)/1 var(--rf-mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--rf-ink-3); margin:0;
}
.rfs-footer .rfs-src{list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; align-items:center; gap:10px 22px}
.rfs-footer .rfs-src li{display:flex; align-items:center; margin:0; line-height:1.3}
.rfs-footer .rfs-src a{
  display:inline-flex; align-items:center; gap:8px; font:600 13px/1.3 var(--rf-sans); color:var(--rf-ink);
  text-decoration:none; transition:color var(--rf-fast);
}
.rfs-footer .rfs-src a:hover{color:var(--rf-brand)}
.rfs-footer .rfs-src .rf-flag{flex:none; transform:none}
.rfs-footer .rfs-src-sym{display:inline-flex; align-items:center; justify-content:center; flex:none; width:18px; height:13px; border-radius:2px;
  background:var(--rf-raised); box-shadow:inset 0 0 0 1px var(--rf-line); font:600 9.5px/1 var(--rf-sans); color:var(--rf-ink-2)}
.rfs-footer .rfs-src-all{
  white-space:nowrap; font:600 var(--rf-t-xs)/1.4 var(--rf-sans); color:var(--rf-ink);
  text-decoration:underline; text-decoration-color:var(--rf-mark, #FFC928); text-decoration-thickness:2px; text-underline-offset:4px;
}
.rfs-footer .rfs-src-all:hover{text-decoration-color:currentColor}
.rfs-footer .rfs-pay{list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:8px}
.rfs-footer .rfs-paymark{
  display:inline-flex; align-items:center; justify-content:center; gap:7px; height:34px; min-width:64px; padding:0 12px 0 10px;
  border:1px solid var(--rf-line); border-radius:6px; background:var(--rf-surface);
  font:600 12.5px/1 var(--rf-sans); letter-spacing:-.005em; color:var(--rf-ink); white-space:nowrap;
}
.rfs-footer .rfs-paymark svg{flex:none; color:var(--rf-ink-3)}
/* RF-PAY-ORDER: the plates arrive one after another, once, when the footer
   comes into view (the inline script after the list adds .is-waiting, then
   .is-in). Nothing moves after that, and reduced motion keeps them still. */
.rfs-footer .rfs-pay.is-waiting .rfs-paymark{opacity:0; transform:translateY(8px)}
.rfs-footer .rfs-pay.is-in .rfs-paymark{opacity:1; transform:none;
  transition:opacity .45s ease, transform .5s cubic-bezier(.2,.8,.2,1)}
.rfs-footer .rfs-pay.is-in .rfs-paymark:nth-child(2){transition-delay:.09s}
.rfs-footer .rfs-pay.is-in .rfs-paymark:nth-child(3){transition-delay:.18s}
@media (prefers-reduced-motion:reduce){
  .rfs-footer .rfs-pay.is-waiting .rfs-paymark{opacity:1; transform:none}
}
.rfs-footer .rfs-pay-safe{display:flex; flex-direction:column; gap:2px; margin:0; font-size:12.5px; line-height:1.45; color:var(--rf-ink-3)}
.rfs-footer .rfs-pay-safe span{display:inline-flex; align-items:center; gap:6px}
.rfs-footer .rfs-pay-safe svg{flex:none}
@media (max-width:900px){
  .rfs-footer .rfs-trust-line{grid-template-columns:1fr; align-items:start}
  .rfs-footer .rfs-trust-mid{grid-column:auto}
  .rfs-footer .rfs-trust-mid > .rfs-src-all{margin-left:0; flex-basis:100%}
}

/* RF-LEGAL-IS-TAPPABLE (21 September 2026). "Cookie preferences вообще не
   открывается" — and the button is not broken: clicked in a real browser it
   opens the modal, and elementFromPoint at each of the eight legal items
   returns that item. What it IS, measured on a phone, is 18px tall.

   Eighteen pixels, in a row of eight items that wraps onto three lines, is
   below every tap-target guideline there is — and this is the row carrying
   Privacy, Cookies and the consent control, which are the links that must
   never be the hard ones to hit.

   The height is added as padding on an inline-flex box, so the text keeps its
   place on the line and only the HIT AREA grows. Phone only: the desktop row
   is a compact single line and a 44px rule there would just be a gap. */
@media (max-width:767px){
  .rfs-footer .footer-legal{gap:0 var(--rf-4)}
  .rfs-footer .footer-legal a,
  .rfs-footer .footer-legal button{
    display:inline-flex; align-items:center; min-height:44px;
  }
}

.rfs-footer .footer-base{
  display:flex; flex-wrap:wrap; gap:var(--rf-2) var(--rf-5);
  margin-top:var(--rf-5); font-size:12px; color:var(--rf-ink-3); line-height:1.6;
}
.rfs-footer .footer-base a{color:var(--rf-ink-2); text-decoration:underline; text-underline-offset:2px}

/* RF-PSRC-IS-A-UTILITY — the Google preferred-source block, injected by
   _worker.js into .footer-brand. It arrives as markup from the edge, so it is
   styled here by its own hook rather than positioned by the template. */
.rfs-footer .rf-psrc-foot{
  margin-top:var(--rf-6); padding:var(--rf-4);
  border:1px solid var(--rf-line); border-radius:var(--rf-r-ctl);
  background:var(--rf-surface); max-width:36ch;
}
.rfs-footer .rf-psrc-h{
  margin:0; font:600 var(--rf-t-xs)/1.3 var(--rf-sans); color:var(--rf-ink);
}
.rfs-footer .rf-psrc-p{
  margin:6px 0 0; font-size:12px; line-height:1.5; color:var(--rf-ink-3);
}
.rfs-footer .rf-psrc-cta{
  display:inline-block; margin-top:var(--rf-3);
  font:600 var(--rf-t-xs)/1 var(--rf-sans); color:var(--rf-brand);
  text-decoration:none; transition:color var(--rf-fast);
}
.rfs-footer .rf-psrc-cta:hover{color:var(--rf-brand-hover)}

/* ============================================================================
   PHONE
   ========================================================================= */
@media (max-width:900px){
  /* RF-FOOTER-B: four columns make an even 2 x 2 under the brand - the old
     three-column footer needed a special case for the odd one out. */
  .rfs-footer .footer-grid{grid-template-columns:1fr 1fr; gap:var(--rf-7) var(--rf-5)}
  .rfs-footer .footer-brand{grid-column:1 / -1}
}

@media (max-width:767px){
  :root{--rf-header:56px; --rf-gutter:16px}

  .rfs-nav .nav-toggle{display:flex}
  .rfs-nav .rfs-nav-cta{display:none}
  .rfs-nav .nav-links{
    position:fixed; top:0; right:0; bottom:0; left:auto; width:min(320px,86vw); z-index:120;
    /* HEIGHT, EXPLICITLY, and this is the whole bug.
       The desktop rule above sets height:auto so the menu is a row in a 68px
       bar. That rule has no media query, so it still applies here — and an
       absolutely positioned box with height:auto IGNORES `bottom`. The drawer
       therefore opened at content height and rendered as a 55px strip across
       the top of the phone with no items visible, which is what the first
       screenshot of it showed. Measured, not guessed: getComputedStyle said
       top:0, bottom:0, height:55px, and the rule list said where auto came
       from. dvh so an iOS address bar cannot cut the last item off. */
    height:100vh; height:100dvh; max-height:100dvh;
    flex-direction:column; align-items:stretch; gap:2px; overflow-y:auto;
    overscroll-behavior:contain;
    background:var(--rf-surface); border-left:1px solid var(--rf-line);
    box-shadow:var(--rf-sh-3); padding:var(--rf-4);
    padding-top:max(var(--rf-4), env(safe-area-inset-top));
    padding-bottom:max(var(--rf-4), env(safe-area-inset-bottom));
    transform:translateX(100%); transition:transform var(--rf-mid); visibility:hidden;
  }
  /* BOTH hooks, and this is not belt-and-braces — it is the bug.
     site.css opens the drawer with `.nav-links.open` and main.js sets
     `body.nav-open`; on a page carrying only one of the two the menu
     animates its hamburger and never slides in. The shell answers to
     either, so it cannot depend on which script version a page loads. */
  body.nav-open .rfs-nav .nav-links,
  .rfs-nav .nav-links.open{transform:none; visibility:visible}
  .rfs-nav .nav-links a:not(.rfs-btn){padding:13px 12px; font-size:15px; color:var(--rf-ink)}
  .rfs-nav .nav-drawer-head{
    display:flex; align-items:center; justify-content:space-between;
    padding:4px 4px var(--rf-4); margin:0;
  }
  .rfs-nav .nav-drawer-brand{
    display:inline-flex; align-items:center; gap:9px;
    font:600 16px/1 var(--rf-sans); letter-spacing:-.03em; color:var(--rf-ink);
  }
  .rfs-nav .nav-drawer-brand .mark{width:24px; height:24px; border-radius:7px}
  .rfs-nav .nav-close{
    display:inline-flex; align-items:center; justify-content:center; width:38px; height:38px;
    border-radius:var(--rf-r-chip); border:1px solid var(--rf-line); background:transparent;
    color:var(--rf-ink-2); font:400 22px/1 var(--rf-sans); cursor:pointer;
  }
  .rfs-nav .nav-close:hover{background:var(--rf-raised); color:var(--rf-ink)}
  .rfs-nav .nav-drawer-cta{display:block; margin-top:auto; padding-top:var(--rf-4)}
}

/* ============================================================================
   ACCESSIBILITY & MOTION
   ========================================================================= */
.rfs-nav :focus-visible,.rfs-footer :focus-visible,.rfs-crumbs :focus-visible{
  outline:2px solid var(--rf-brand); outline-offset:2px; border-radius:4px;
}
@media (prefers-reduced-motion:reduce){
  .rfs-nav *,.rfs-footer *{transition-duration:.001ms!important; animation-duration:.001ms!important}
}
@media print{
  .rfs-nav{display:none!important}
}

/* ============================================================================
   RF-ONE-TABBAR — the mobile product navigation, defined once.
   19 September 2026.

   The component CSS used to exist three times, inline: 22 rules in map.html,
   17 in chat.html, 17 in account.html, all of them the same bar. It lives here
   now, once, so the homepage can carry the same bar without a fourth copy.

   map.html keeps its own inline block on purpose and it loads after this one,
   so /map's pinned desktop column geometry — .rf-tabbar docked at
   left:var(--rf-col-x), width:var(--rf-col-w) — still wins there and nothing
   about that screen moves. This file owns the PHONE bar and the item styling;
   that file owns where the bar sits on a desktop /map.

   Who gets it: the homepage and /map, written in by apply-shell.py and
   stripped from everything else. A content page has a header, not an app bar.
   ========================================================================= */
/* ONE FLOATING-ACTION SYSTEM (GUIDELINES §12-§14).

   RF-FIVE-OPINIONS (20 September 2026). The first version of this block
   declared the tokens and trusted every other file to read them. It did not
   work, and the measurement says so plainly — production, 375px wide, scrolled
   into the editorial content:

       chat button   bottom  72px   height 56   occupies   72 -> 128
       back to top   bottom  92px   height 44   occupies   92 -> 136
       OVERLAP                                             36px

   FIVE places were positioning the same two buttons:

       site.css:161   --rf-fab-base: 16px + safe
       site.css:542   --rf-fab-base: 16px + safe + 66px     html.rf-sticky-on,
                                                            a class nothing sets
       home.css:608   --rf-fab-base: 16px + safe + tabbar   body.rfh, which
                                                            outranks :root
       shell.css      --rf-fab-base: safe + tabbar + gap    this file
       assistant.js   .back-to-top{right:22px;bottom:92px}  !important, and
                                                            INJECTED at runtime,
                                                            so it lands after
                                                            every stylesheet

   Proved rather than argued: setting --rf-fab-base on <body> moved the chat
   button to 300px and left back-to-top sitting at 92px — a control that was not
   reading the token at all. assistant.js explains itself honestly in its own
   comment: it was written on 19 July 2026, just after the bottom tab bar was
   REMOVED, and 92px was the correct answer in a world with no bar. The bar came
   back on 19 September and nothing told that file.

   So this block positions the stack itself, at a specificity the other files do
   not reach, and the numbers were DELETED from assistant.js rather than nudged
   until they looked right. /map keeps its own floor on purpose: html.rfa-map is
   (0,2,1) and still outranks html body at (0,1,2), because there the bubble
   parks beside the map controls.

       --rf-tabbar-h    the bar's height, 0 when there is no bar ON SCREEN
       --rf-safe-bottom the phone's home indicator
       --rf-fab-size    one floating button
       --rf-fab-gap     the space between two of them, and above the bar
       --rf-fab-floor   where the stack starts. One name, declared once.

   The stack, bottom-up:  [ bar ] [ gap ] [ chat ] [ gap ] [ back to top ]
   so no two of them can occupy the same place. */
:root{
  --rf-tabbar-h:0px;
  /* RF-CONSENT-IS-PART-OF-THE-STACK (22 September 2026). --rf-cc-h is the
     consent banner's measured height, published by cookie-consent.js while
     the banner is open and removed when it closes. It was a variable only
     JavaScript had ever heard of: eight floating widgets in site.css read it,
     the stack vocabulary above did not list it, and the tab bar — which
     arrived on 19 September, three days ago — was never added to either.

     MEASURED AT 390px BEFORE THE FIX, on / and on /map: banner top 674,
     height 170; tab bar top 787, so the bar sat 113px INSIDE the banner.
     elementFromPoint on the centre of Chat, Stations, Route and More returned
     `button.btn` — the banner's own buttons — for all four. The banner is
     z-index 2147483100 and the bar is 1400, so a first-time visitor could not
     reach the product's primary navigation at all until they answered it.

     Declared here with a 0px default so it is part of the vocabulary rather
     than an undefined name with a fallback written at eight call sites. */
  --rf-cc-h:0px;
  --rf-safe-bottom:env(safe-area-inset-bottom, 0px);
  --rf-fab-size:56px;
  --rf-fab-gap:12px;
  /* NOT added into this sum, and that is deliberate. site.css already lifts
     every floating widget by --rf-cc-h with a transform; adding it to the
     floor as well would move each of them twice the banner's height. The
     banner is accounted for once, by the transform, and the bar below now
     joins the same mechanism so the whole stack travels together. */
  --rf-fab-floor:calc(var(--rf-safe-bottom) + var(--rf-tabbar-h) + var(--rf-fab-gap));
}
/* RF-THE-END-OF-THE-PAGE-CLEARS-THE-BANNER (23 September 2026). Measured on
   every public page for a first visit, scrolled to the very end: the last
   footer line (the OpenStreetMap credit) and, on short pages at 375-430px,
   Community guidelines, Editorial & data policy and Cookie preferences sat
   UNDER the consent banner — elementFromPoint returned the banner's <p>.
   Cookie preferences is the one link a visitor looks for while that banner is
   open. The page reserves the banner's height at its end; --rf-cc-h is 0 once
   the banner is answered, so nothing moves for a returning visitor. */
html.cc-banner-open body{padding-bottom:var(--rf-cc-h,0px)}
@media (max-width:767px){
  :root:has(nav[data-rf-tabbar]){--rf-tabbar-h:56px}
  /* RF-FOOTER-CLEARS-THE-BAR (24 September 2026). Belt to main.js's braces:
     even in a moment when the bar is on screen at the page end (the owner's
     iPhone showed it over the copyright line), the footer's own grey carries
     on underneath it, so no line of it is ever under the bar and no white
     strip opens between the footer and the bar. */
  /* And the back-to-top arrow: measured at 360px on every content page, it
     parked on the last line ("Map data © OpenStreetMap contributors" read
     "con[arrow]"). So the footer ends with room for the arrow (12 + 44 + 8)
     and, on pages with the bar, for the bar under it as well (the arrow
     then floats at bar + 12 .. bar + 56). */
  body .site-footer.rfs-footer{
    padding-bottom:calc(var(--rf-6) + 64px + env(safe-area-inset-bottom, 0px));
  }
  :root:has(nav[data-rf-tabbar]) body .site-footer.rfs-footer{
    padding-bottom:calc(var(--rf-6) + 56px + 64px + env(safe-area-inset-bottom, 0px));
  }

  /* RF-THE-BAR-BELONGS-TO-THE-PRODUCT. Measured on production at 390px: the
     home page is 12,691px tall and its product area ends at 805px — six per
     cent. The bar was fixed over the other 94%, which is reading. main.js
     watches the product area and sets .rf-content-view once it leaves; the
     height collapses with it, so the floating buttons drop to the viewport
     edge instead of hovering above a bar that is no longer there.

     SPECIFICITY, and this one cost a full measurement to find: the rule above
     is :root:has(nav[data-rf-tabbar]) = (0,2,1). The collapse below was
     :root.rf-content-view = (0,2,0). It LOST. Live proof: the bar had already
     translated off screen with pointer-events:none, and --rf-tabbar-h still
     read 56px, so every floating button went on reserving room for it.
     Matching the :has() shape takes the state to (0,3,1), which wins. The plain
     pair is kept underneath for browsers without :has(), where the rule above
     never applied either and (0,2,0) is enough. */
  :root.rf-content-view:has(nav[data-rf-tabbar]),
  :root.rf-typing:has(nav[data-rf-tabbar]){--rf-tabbar-h:0px}
  :root.rf-content-view,
  :root.rf-typing{--rf-tabbar-h:0px}
  .rf-content-view .rf-tabbar,
  .rf-typing .rf-tabbar{transform:translateY(110%); pointer-events:none}

  /* THE BAR CLEARS THE CONSENT BANNER. Same mechanism and the same easing as
     the eight widgets in site.css, so the whole floating stack moves as one
     object rather than the bar arriving separately.

     The :not() pair is load-bearing, not tidiness. `html.cc-banner-open
     .rf-tabbar` is (0,2,1) and beats the `.rf-content-view .rf-tabbar` rule
     above at (0,2,0), so without them a banner would drag the bar back on
     screen in exactly the two states that just spent effort hiding it — the
     visitor scrolls out of the product area, the bar leaves, and the cookie
     banner brings it back. Both states are excluded, so the hiding rules keep
     the element and this one only ever adjusts a bar already on screen. */
  html.cc-banner-open:not(.rf-content-view):not(.rf-typing) .rf-tabbar{
    transform:translateY(calc(-1 * var(--rf-cc-h, 0px)));
  }

  /* The keyboard owns the bottom of the screen while a field has focus.
     Nothing floats there — it would land on the keyboard or on the field. */
  .rf-typing .rfa-btn,
  .rf-typing .back-to-top{opacity:0; pointer-events:none}

  /* THE STACK. html body is (0,1,2): above the bare class rules in site.css and
     home.css and above anything assistant.js injects without a class, below
     html.rfa-map, which is the one exception we want to keep. */
  html body .rfa-btn{right:16px!important; bottom:var(--rf-fab-floor)!important}
  html body .back-to-top{right:22px!important;
    bottom:calc(var(--rf-fab-floor) + var(--rf-fab-size) + var(--rf-fab-gap))!important}

  /* A page with no assistant bubble must not reserve 56px of empty corner for
     it — the arrow takes the floor instead. .rfa-on is set by assistant.js when
     the bubble actually exists. */
  html:not(.rfa-on) body .back-to-top{bottom:var(--rf-fab-floor)!important}

  /* Fed back to the older token names so the footer clearance in site.css
     (--rf-content-bottom) reserves the same distance this stack occupies.
     Nothing POSITIONS from these any more; --rf-fab-floor is the one name. */
  :root{
    --rf-fab-safe: var(--rf-safe-bottom);
    --rf-fab-chat: var(--rf-fab-size);
    --rf-fab-base: var(--rf-fab-floor);
  }
}

/* The same stack on desktop, where there is no tab bar and the floor is simply
   the corner. This half is not optional: assistant.js's deleted block carried
   an UNSCOPED `html.rfa-on .back-to-top{bottom:92px}` that was doing the
   desktop stacking too. Without a replacement the arrow falls back to
   site.css's `bottom:18px` and lands inside the bubble, which sits at 20px and
   is 56px tall — the same collision, moved to a bigger screen.

   Bounded by min-width on purpose: at (0,2,2) this rule would otherwise outrank
   the mobile `html body` one at (0,1,2) and follow the page down onto phones. */
@media (min-width:768px){
  html.rfa-on body .back-to-top{right:26px!important;
    bottom:calc(20px + var(--rf-fab-size) + var(--rf-fab-gap))!important}
}
/* ===========================================================================
   RF-ONE-STACK (20 September 2026) — the mobile menu, and why it looked
   translucent when nothing about it is translucent.

   Reported as "меню полупрозрачное, контент просвечивает, клики ненадёжны".
   Measured on production at 375px with the drawer open:

       drawer    background rgb(13,29,39)   opacity 1   visibility visible
                 pointer-events auto        z-index 120
       backdrop  rgba(4,8,18,.6)            z-index 1390
       tabbar                               z-index 1400
       chat FAB                             z-index 2147482000

   The panel is SOLID navy. What the eye was reading as transparency is a 60%
   black scrim painted ON TOP of it — the backdrop, which is supposed to sit
   behind the menu and dim the page.

   And the same inversion broke every click. elementFromPoint at the centre of
   the "Map" link returned DIV.nav-backdrop, whose handler is closeDrawer. So
   tapping any menu item closed the menu and navigated nowhere. Five dead links,
   and they look perfectly fine in the HTML.

   THE CAUSE IS STRUCTURAL, so bumping the drawer's z-index does not fix it.
   The drawer is a child of <nav class="site-nav">, which is position:relative
   with z-index:60 — a STACKING CONTEXT. Every z-index inside it is resolved
   against its siblings, not against the page, so the drawer's own 120 (and the
   1400 site.css also declares for it) can never lift it above a sibling of the
   nav. The backdrop and the tab bar are siblings of the nav. They win at any
   number the drawer chooses.

   So the fix raises the CONTEXT, not the child: while the drawer is open the
   whole header outranks the backdrop. And the three floating things that were
   painting over the open menu are hidden by visibility rather than out-bid on
   z-index, because the chat bubble sits at 2147482000 and that is not a
   number worth arguing with.

       tab bar   200      product chrome
       FABs      250      chat, back-to-top
       backdrop  900      dims the page
       header   1000      only while .nav-open, carrying the drawer with it

   =========================================================================== */
:root{
  --rf-z-tabbar:   200;
  --rf-z-fab:      250;
  --rf-z-backdrop: 900;
  --rf-z-drawer:  1000;
}
/* The backdrop belongs BEHIND the menu it dims. */
body .nav-backdrop{z-index:var(--rf-z-backdrop)}
/* Raising the header lifts the drawer inside it — the only move that works
   through a stacking context. Scoped to .nav-open so the header goes back to
   its normal 60 the moment the menu closes. */
body.nav-open .site-nav{z-index:var(--rf-z-drawer)}
/* Nothing floats over an open menu. visibility, not z-index: see above. */
body.nav-open .rf-tabbar,
body.nav-open .rfa-btn,
body.nav-open .back-to-top{
  opacity:0 !important; pointer-events:none !important; visibility:hidden !important;
}
/* RF-MAP-CHROME-STANDS-DOWN (22 September 2026). Reported with a screenshot
   from a phone: open the menu on /map and the map's search bar, fuel chips,
   zoom rail and station peek paint OVER the drawer, hiding Map and Fuel
   prices. Measured: the key bar sits at 1250, the rail and bottom controls at
   1200, the swipe strip at 1390, all in the root stacking context, while the
   lifted header is 1000. Same answer as the FABs above: the map's own chrome
   stands down by visibility while the menu is open. The tiles and pins stay,
   dimmed under the backdrop, so the driver keeps their place. */
body.nav-open .map-shell{visibility:hidden !important; pointer-events:none !important}
body.nav-open .map-shell .leaflet-map-pane{visibility:visible !important}
/* RF-HEADER-DIMS-TOO (24 September 2026). The owner's phone: with the menu
   open, the strip of header left of the drawer stayed bright white with a
   clipped "Ref" and a second logo right beside the drawer's own — because the
   header is lifted ABOVE the backdrop (it carries the drawer). So the header
   dims itself with the backdrop's own shade, under the drawer (120) and over
   its logo and buttons; a tap on it closes the menu (main.js). */
@media (max-width:767px){
  body.nav-open .rfs-nav::after{
    content:""; position:absolute; inset:0 0 -1px 0; z-index:110; pointer-events:auto;
    background:rgba(4,8,18,.6);
  }
}

.rf-tabbar{transition:transform var(--rf-mid)}
.rfa-btn,.back-to-top{transition:opacity var(--rf-fast), bottom var(--rf-mid)}
@media (prefers-reduced-motion:reduce){
  .rf-tabbar,.rfa-btn,.back-to-top{transition:none}
}

.rf-tabbar{display:none}

/* A station card expanded to full screen owns the screen. The bar would sit
   on top of it, which is the overlay-blocking-a-tap case the sheet rules ban.
   map.js already sets body.sheet-full for exactly this; the declaration that
   read it had been deleted from site.css years-of-appends ago, leaving the
   selector behind (see RF-CSS-PARSE there). It is implemented here, against
   the component that exists now. */
/* RF-THE-ASSISTANT-IS-NOT-THE-CHAT (21 September 2026). REVERSAL, same day.

   Yesterday I hid .rfa-btn on a phone whenever the product bar carried a Chat
   tab, and called it "one action offered twice". That was wrong, and the owner
   caught it: "верни чат, который был. Ты всё удалил."

   They are two different products that both happen to look like a speech
   bubble:

       chat.js       /api/chat       Driver messages. Real people, moderated,
                                     the Chat tab and /chat.
       assistant.js  /api/assistant  Refuelia Assistant. A model behind our own
                                     Worker proxy that answers questions about
                                     fuel types, EV connectors and planning
                                     stops. Its own rate limits, its own budget,
                                     its own error vocabulary.

   Hiding the bubble did not remove a duplicate route to the chat panel. It
   removed the assistant from every phone. The rule is deleted rather than
   narrowed, because there is nothing here to narrow: a tab that opens driver
   messages and a button that opens the assistant are not the same action at any
   screen width.

   What the owner's §12 asked for — "if Chat is in the bottom nav, the floating
   chat FAB is absent" — is satisfied already and was satisfied before this rule
   existed: there has only ever been ONE floating chat bubble on this site, and
   it belongs to the assistant. The real duplicate risk is that the two look
   alike, which is a labelling job, not a display:none one. */

body.sheet-full .rf-tabbar{display:none !important}

@media (max-width:767px){
  .rf-tabbar{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:1400;
    background:color-mix(in srgb, var(--rf-bg) 94%, transparent);
    -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
    border-top:1px solid var(--rf-line);
    padding-bottom:env(safe-area-inset-bottom);
  }
  .rf-navtab{
    flex:1 1 0; position:relative;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
    min-height:56px; padding:8px 4px; text-decoration:none;
    font:600 10.5px/1 var(--rf-sans); color:var(--rf-ink-3);
    -webkit-tap-highlight-color:transparent;
    transition:color var(--rf-fast), background-color var(--rf-fast);
  }
  .rf-navtab .rf-navtab-ic{display:flex}
  .rf-navtab .rf-navtab-ic svg{width:20px; height:20px; transition:transform var(--rf-fast)}
  .rf-navtab:active{background:var(--rf-line-faint)}
  .rf-navtab:focus-visible{outline:2px solid var(--rf-brand); outline-offset:-3px; border-radius:10px}
  /* The current tab is marked by aria-current, and the stylesheet reads it —
     one way for a tab to be current, the same rule the header follows. */
  .rf-navtab[aria-current="page"],.rf-navtab.is-on{color:var(--rf-brand)}
  .rf-navtab[aria-current="page"] .rf-navtab-ic svg,
  .rf-navtab.is-on .rf-navtab-ic svg{transform:translateY(-1px)}
  .rf-navtab[aria-current="page"]::before,.rf-navtab.is-on::before{
    content:''; position:absolute; top:0; left:50%; transform:translateX(-50%);
    width:26px; height:2px; border-radius:0 0 2px 2px; background:var(--rf-brand);
  }
}
@media (prefers-reduced-motion:reduce){
  .rf-navtab,.rf-navtab .rf-navtab-ic svg{transition:none}
}

/* RF-WIDE-SCREEN — the container breathes on a desktop monitor; the reading
   measure does not. See the note beside --rf-wrap-wide.
   1700px is the threshold on purpose: 1440 and 1536 laptops keep 1320px
   exactly, and only a genuinely wide display gets the wider container. */
@media (min-width:1700px){
  :root{--rf-wrap: var(--rf-wrap-wide)}
}

/* RF-SEND-PEOPLE-WHERE-IT-IS-HANDLED (21 September 2026). The three routes
   above the contact form: what goes to driver feedback, what goes to the
   stations page, and what the form itself is for.

   NOT CARDS, deliberately. Three bordered boxes would read as three offers of
   equal weight, and they are not — two of them exist to take work OFF this
   page. A list with a strong key line and a sentence under it reads in the
   order a person actually needs: is this me, and where do I go. Same reasoning
   as RF-NOT-EVERYTHING-IS-A-CARD on the homepage.

   The rule lives here rather than in a page <style> because /contact loads only
   site.css and shell.css; a third stylesheet for one component is how a page
   ends up with its own design. */
.ct-routes{
  list-style:none; margin:0 0 26px; padding:0;
  display:grid; gap:0;
  border-top:1px solid var(--rf-line);
}
.ct-routes li{
  padding:14px 0 15px;
  border-bottom:1px solid var(--rf-line);
}
.ct-routes-k{
  display:block; font-weight:600; font-size:var(--rf-t-base,15.5px);
  color:var(--rf-ink); margin:0 0 3px;
}
.ct-routes p{
  margin:0; font-size:var(--rf-t-sm,14px); line-height:1.6;
  color:var(--rf-ink-soft); max-width:70ch;
}
/* The link is the action in each row, so it carries the weight the row's key
   line does not spend on it.
   --rf-brand, NOT --rf-brand-ink: that token is "text ON emerald" (#04231A in
   dark, #FFFFFF in light) and is meant for the inside of a filled button. Used
   as a link colour on paper it paints near-black text in dark mode and white
   text on white in light mode — an invisible link. The comment beside its
   declaration says exactly this; it is easy to read the name as "the brand's
   ink" and reach for the wrong one. */
.ct-routes a{ color:var(--rf-brand); font-weight:600; }
.ct-routes a:hover{ text-decoration:underline; }
@media (min-width:900px){
  /* Two columns of reading, not four of scanning: these are sentences. The
     third row (the form itself) spans, because it describes what is directly
     underneath it. */
  .ct-routes{ grid-template-columns:1fr 1fr; column-gap:34px; }
  .ct-routes li:nth-child(3){ grid-column:1 / -1; }
}/* ============================================================================
   RF-ONE-PRIMARY-BUTTON (21 September 2026)
   ============================================================================
   Alex sent two photographs of the same "Open the map" button,
taken minutes
   apart,
and they are not the same button. He is right,
and it is worse than
   two: MEASURED on live /map with getComputedStyle,
there are four primary
   buttons on that one page.

       .btn.primary        linear-gradient(135deg,#2EE6A8,#22C48F)
                           ring shadow,
transform transition,
15.5px/700
       .rfs-btn--primary   flat #2EE6A8,
15.5px/700
       .rf-btn--primary   flat #2EE6A8,
glow shadow,
999px,
44px,
14.5px/700
       .rfs-nav-cta        flat #20D6A0,
NO shadow,
12px,
38px,
14px/600
       .rf-topbar-signin   flat #2EE6A8,
NO shadow,
999px,
36px,
14px/700

   Two different greens. Two different inks (#16140F and #04231A). Two radii.
   Three heights. Two weights. Three shadow treatments. Nobody decided any of
   this; each one was written next to the thing it sat beside,
and the site
   ended up with four opinions about its single most important control.

   ONE COMPONENT,
three sizes. The sizes are the only legitimate difference: a
   44px button in a footer,
a 38px one in a 68px header,
a 36px one in the map's
   44px strip. Everything that carries meaning — the green,
the ink on it,
the
   shape,
the weight,
the way it answers hover,
press and focus — is now one set
   of tokens,
and every primary button in the site reads them.

   WHY !important. site.css,
home.css and map.html each declare their own
   version of these buttons,
and several of those selectors are longer than
   anything that can be written here without describing their whole ancestry
   (`.funnel-cta .btn.primary`,
`.rfs-nav .nav-links a.rfs-btn--primary`). The
   choice is one honest ratchet or a specificity race that the next person loses
   again. Only the properties that MUST NOT drift are marked; padding,
`.rfs-nav .nav-links a.rf-btn--primary`). The
   choice is one honest ratchet or a specificity race that the next person loses
   again. Only the properties that MUST NOT drift are marked; padding,
width and
   layout are left alone so each button still fits where it lives. */
:root{
  --rf-cta-bg:        var(--rf-brand);
  /* NOT --rf-brand-hover. That token is #18BD8C, i.e. DARKER than the brand,
     and the ink on this button is near-black — so the existing hover walks the
     contrast the wrong way. Measured, ink #04231A against each ground:

         #20D6A0  resting        8.88
         #18BD8C  --rf-brand-hover   6.90   ← what hovering used to do
         #35DFAE  this token         9.77

     That drop is what the owner photographed as "ярко-зелёный фон + плохо
     читаемый серо/зелёный текст". On a dark ground the hover lightens; the
     paper block below reverses it, because there the ink is white and lighter
     would be the wrong direction again. Hover always moves AWAY from the ink. */
  --rf-cta-bg-hover:  #FFD659;   /* RF-ROAD-MARKING: lighter = away from the dark ink, 13.16 */
  --rf-cta-ink:       var(--rf-brand-ink);
  --rf-cta-radius:    var(--rf-r-ctl);   /* was 999px, the mint capsule the owner called нейрослоп */
  --rf-cta-weight:    700;
  --rf-cta-h:         44px;   /* page and footer CTAs */
  --rf-cta-h-md:      38px;   /* inside the 68px site header */
  --rf-cta-h-sm:      36px;   /* inside the map's 44px strip */
  /* RF-2.0: a green-tinted shadow under a green button is a glow by another
     name. A button sits on the page; it does not light it. */
  --rf-cta-shadow:    0 1px 0 rgba(0,0,0,.28), 0 2px 6px -3px rgba(0,0,0,.45);
}
html body .rf-btn--primary,
html body .btn.primary,
html body .rfs-btn--primary,
html body .rfs-nav-cta,
html body .rf-topbar-signin{
  background:var(--rf-cta-bg) !important;
  background-image:none !important;      /* kills the one gradient among four */
  color:var(--rf-cta-ink) !important;
  border:1px solid var(--rf-cta-bg) !important;
  border-radius:var(--rf-cta-radius) !important;
  font-weight:var(--rf-cta-weight) !important;
  box-shadow:var(--rf-cta-shadow);
  /* Press is the only transform this control makes. The gradient version
     scaled on hover, which moved the words under the cursor. */
  transition:background-color var(--rf-fast,.16s) ease,
             box-shadow var(--rf-fast,.16s) ease,
             transform .08s ease;
}
html body .btn.primary{ min-height:var(--rf-cta-h) !important; }
html body .rf-btn--primary,
html body .rfs-btn--primary{ min-height:var(--rf-cta-h) !important; }
html body .rfs-nav-cta{ min-height:var(--rf-cta-h-md) !important; }
html body .rf-topbar-signin{ min-height:var(--rf-cta-h-sm) !important; }

/* HOVER LIGHTENS, it never darkens. The ink on this button is near-black by
   design, so a darker hover walks the contrast DOWN — which is exactly what the
   owner photographed: pale text on a washed green. Lightening moves 9.79:1 the
   safe way. */
html body .rf-btn--primary:hover,
html body .btn.primary:hover,
html body .rfs-btn--primary:hover,
html body .rfs-nav-cta:hover,
html body .rf-topbar-signin:hover{
  background:var(--rf-cta-bg-hover) !important;
  border-color:var(--rf-cta-bg-hover) !important;
  box-shadow:0 1px 0 rgba(0,0,0,.28), 0 4px 10px -4px rgba(0,0,0,.5);
}
/* Physical feedback, not a glow. */
html body .rf-btn--primary:active,
html body .btn.primary:active,
html body .rfs-btn--primary:active,
html body .rfs-nav-cta:active,
html body .rf-topbar-signin:active{
  transform:translateY(1px);
  box-shadow:0 1px 0 rgba(0,0,0,.2);
}html body .btn.primary:focus-visible,
html body .rfs-btn--primary:focus-visible,
html body .rf-btn--primary:focus-visible,
html body .rfs-nav-cta:focus-visible,
html body .rf-topbar-signin:focus-visible{
  outline:2px solid var(--rf-brand) !important;
  outline-offset:3px !important;
}/* Disabled reads as disabled rather than as "green,
but sad". */
html body .btn.primary:disabled,
html body .btn.primary[aria-disabled="true"],
html body .rfs-btn--primary:disabled,
html body .rf-btn--primary:disabled{
  background:var(--rf-line) !important;
  border-color:var(--rf-line) !important;
  color:var(--rf-ink-soft) !important;
  box-shadow:none !important;
  cursor:not-allowed;
  transform:none;
}
@media (prefers-reduced-motion:reduce){html body .btn.primary,
html body .rfs-btn--primary,
html body .rf-btn--primary,
html body .rfs-nav-cta,
html body .rf-topbar-signin{ transition:none; }
  html body .rf-btn--primary:active,
  html body .btn.primary:active,
  html body .rfs-btn--primary:active,
  html body .rfs-nav-cta:active,
  html body .rf-topbar-signin:active{ transform:none; }
}

/* RF-NO-MYSTERY-CIRCLE (21 September 2026). The signed-in account control is a
   circle with a photo or an initial in it, and on a header made of words it was
   the one item you had to click to find out what it did. auth.js now renders
   the driver's first name beside it; this places it.

   Desktop only. Below 901px the header is a 40px strip with a hamburger and the
   circle, and a name there would push one of them off the edge — on a phone the
   circle sits next to nothing else, so it reads as "you", which is what it is.
   The span is aria-hidden: the button already carries aria-label="Account", and
   a screen reader announcing "Account Timofei" would be reading the same
   control twice. */
.auth-slot{ display:flex; align-items:center; gap:8px; }
.auth-avatar-t{
  display:none;
  font-size:var(--rf-t-sm); font-weight:650; color:var(--rf-ink);
  max-width:14ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
@media (min-width:901px){
  .auth-slot:has(.auth-avatar-btn) .auth-avatar-t{ display:inline-block; }
}

/* ============================================================================
   RF-2.0 CLOSING LINE. The last thing on 15 pages was a navy card with a green
   bar down its left edge: a box around one sentence and one button. It is now
   what it always was — the page's last line — set on the road: a hairline with
   a short emerald start, the heading in the display face, and the one action
   beside it rather than under it on a wide screen.
   ========================================================================= */
.funnel-cta{ padding:var(--rf-9) 0 var(--rf-10) }
.funnel-cta .fcta-panel{ background:none; background-image:none; border:0; border-radius:0; box-shadow:none;
  padding:0; display:grid; grid-template-columns:minmax(0,7fr) minmax(0,5fr); column-gap:var(--rf-8); align-items:end; overflow:visible }
/* RF-NO-STRAY-LINES (24 September 2026). The owner: "remove these lines, what is
   this bug". The hairline over the closing line and its short dark start read
   as a broken underline, not as a divider. The closing line now stands on
   spacing alone: no border, no accent bar (site.css's old left bar included). */
.funnel-cta .fcta-panel::before{ content:none !important; display:none !important }
.funnel-cta .fcta-h{ font-family:var(--rf-display); font-weight:600; font-size:var(--rf-t-h2); line-height:1.08; letter-spacing:-.015em; text-wrap:balance; grid-column:1 }
.funnel-cta .fcta-p{ grid-column:1; margin:var(--rf-3) 0 0; font-size:var(--rf-t-body); color:var(--rf-ink-2); max-width:60ch }
.funnel-cta .fcta-btns{ grid-column:2; grid-row:1 / span 2; justify-content:flex-end; align-self:end }
.funnel-cta .fcta-btns .btn{ width:auto }
@media (max-width:767px){
  .funnel-cta{ padding:var(--rf-8) 0 }
  .funnel-cta .fcta-panel{ display:block; padding-top:0 }
  .funnel-cta .fcta-btns{ margin-top:var(--rf-5); justify-content:flex-start }
  .funnel-cta .fcta-btns .btn{ width:100% }
}
.rp-wrap{ display:grid; grid-template-columns:minmax(0,760px) minmax(0,1fr); column-gap:var(--rf-9); align-items:start }
.rp-wrap > *{ grid-column:1; min-width:0 }
.rp-wrap > .rp-src{ grid-column:2; grid-row:1 / span 6; position:sticky; top:calc(var(--rf-nav-h,64px) + var(--rf-6)) }
.rp-src{ border-top:1px solid var(--rf-line); padding-top:var(--rf-4) }
.rp-src-h{ font:600 11px/1 var(--rf-mono); letter-spacing:.09em; text-transform:uppercase; color:var(--rf-ink-3); margin:0 0 var(--rf-4) }
.rp-src ol{ list-style:none; margin:0; padding:0 0 0 var(--rf-5); display:grid; gap:var(--rf-4); position:relative }
.rp-src ol::before{ content:""; position:absolute; left:4px; top:6px; bottom:6px; width:2px; background:linear-gradient(var(--rf-brand),var(--rf-line)); border-radius:2px }
.rp-src li{ position:relative; display:grid; gap:2px }
.rp-src li::before{ content:""; position:absolute; left:calc(-1 * var(--rf-5) + 1px); top:5px; width:8px; height:8px; border-radius:50%; background:var(--rf-bg); border:2px solid var(--rf-brand) }
.rp-src b{ font-size:var(--rf-t-sm); color:var(--rf-ink); font-weight:600 }
.rp-src span{ font-size:var(--rf-t-sm); line-height:1.5; color:var(--rf-ink-2) }
@media (max-width:1023px){ .rp-wrap{ display:block } .rp-wrap > .rp-src{ position:static; margin:0 0 var(--rf-7) } .rp-wrap > *{ max-width:760px } }
.rp-src span a{ color:var(--rf-brand) }

/* RF-2.0 HEADER, desktop. The active page was a grey pill, the same shape as a
   hover, so the header could not say "you are here" any louder than "you could
   go here". It is now the road line: a short emerald rule under the word, the
   same mark the journey line and the closing line use. Sign in is set apart
   from the four pages by a hairline — it is an account, not a destination. */
@media (min-width:768px){
  .rfs-nav .nav-links a[aria-current="page"]:not(.rfs-btn){ background:none; position:relative }
  .rfs-nav .nav-links a[aria-current="page"]:not(.rfs-btn)::after{ content:""; position:absolute; left:12px; right:12px; bottom:1px; height:2px; border-radius:2px; background:var(--rf-brand) }
  .rfs-nav .nav-links li.nav-signin{ margin-left:6px; padding-left:10px; border-left:1px solid var(--rf-line) }
}

/* RF-2.0 FAULT: site.css paints the OLD badge by type and status —
   `.pin-badge.ev.gray{background:#22c3d6}` among a dozen — and three classes
   outrank `.pin-badge.pin-ring{background:none}`. Every EV ring pin outside
   /map sat on a cyan square. The ring pin is an SVG and has no box at all. */
.rf-mk.pin-badge.pin-ring{ background:none !important; border:0 !important; border-radius:0 !important }
.rf-mk.pin-badge.pin-ring:not(.rf-mk--pulse){ box-shadow:none }
/* RF-2.0 FAULT (measured at 390 and 430): the route form ran 75px off the
   right edge — a 1fr track grows to its min-content, and "Use my location"
   beside a 20-character placeholder is wider than a phone. */
.rp-wrap .rp-grid{ grid-template-columns:repeat(2,minmax(0,1fr)) }
.rp-inline input{ min-width:0; flex:1 1 auto }
@media (max-width:640px){ .rp-wrap .rp-grid{ grid-template-columns:minmax(0,1fr) } }

/* RF-2.0 ADS (22 September 2026). One editorial unit per guide, mid-article.
   Height is reserved only while a unit is requested (ads.js adds is-requested),
   so the article never jumps when the ad lands; an unfilled unit collapses.
   The margin keeps it a clear thumb's width from any button or link above or
   below it - accidental clicks are what get a publisher account closed. */
/* An unrequested slot is nothing at all - no gap, no hairlines. Measured on the
   test deploy: three empty slots per guide each left a ruled gap in the text. */
.ad-slot:not(.is-requested){ display:none !important }
.ad-slot{ margin:var(--rf-9) 0; padding:var(--rf-3) 0; border-top:1px solid var(--rf-line); border-bottom:1px solid var(--rf-line) }
.ad-slot .ad-label{ font:600 10.5px/1 var(--rf-mono); letter-spacing:.12em; text-transform:uppercase; color:var(--rf-ink-3); text-align:left; margin-bottom:var(--rf-3) }
.ad-slot .ad-box{ border:0; border-radius:0 }
.ad-slot.is-requested .ad-box{ min-height:280px }
@media (max-width:767px){ .ad-slot.is-requested .ad-box{ min-height:250px } .ad-slot{ margin:var(--rf-8) 0 } }

/* RF-2.0 FAULT (seen on the test deploy, not in the harness): site.css pins
   `.leaflet-marker-icon .pin-badge.pin-ring{transform:none}` at three classes,
   which outranked the two-class lift above - the linked pin got its halo but
   never rose. Same rule, stated at the specificity it has to win at. */
.leaflet-marker-icon .rf-mk.pin-ring.is-hot,
.leaflet-marker-icon .rf-mk.pin-ring.is-linked{ transform:translateY(-2px) scale(1.14); transform-origin:50% 92% }
@media (prefers-reduced-motion:reduce){
  .leaflet-marker-icon .rf-mk.pin-ring.is-hot,
  .leaflet-marker-icon .rf-mk.pin-ring.is-linked{ transform:none }
}

/* RF-2.0 (owner, 22 September 2026: "квадратики лучше убрать по всему сайту,
   а то сразу ИИ похоже"). site.css still paints two layers behind every page:
   a 26px dot grid (body::after) and three soft green and blue glows
   (body::before) - the "glowing blobs" and graph paper the guidelines ban
   (H2). The page ground is the flat --rf-bg, nothing behind it. */
body::before, body::after{ content:none !important; display:none !important; background:none !important; animation:none !important }

/* RF-ADULTS-ONLY (23 September 2026). The 18+ confirmation on every sign-in
   surface (auth.js ageHTML). Until it is ticked the provider buttons are
   dimmed and inert; the Google button is an iframe, so its slot takes the
   press instead and auth.js answers it with one sentence. */
.auth-age{display:flex; gap:10px; align-items:flex-start; margin:14px 0 12px; font-size:13.5px; line-height:1.45;
  color:var(--rf-ink-2); cursor:pointer; text-align:left}
.auth-age input{width:20px; height:20px; margin:0; flex:none; accent-color:var(--rf-brand); cursor:pointer}
.auth-age a{color:var(--rf-brand); text-decoration:underline; text-underline-offset:3px}
.auth-gate:not(.auth-age-ok) .auth-gbtn,
.auth-signin-pop:not(.auth-age-ok) .auth-gbtn,
.auth-gate:not(.auth-age-ok) a.auth-provider,
.auth-signin-pop:not(.auth-age-ok) a.auth-provider{opacity:.45; transition:opacity .15s ease}
.auth-gate:not(.auth-age-ok) .auth-gbtn > *,
.auth-signin-pop:not(.auth-age-ok) .auth-gbtn > *{pointer-events:none}

/* RF-SIGNIN-SHEET (24 September 2026). The sign-in popover sat at z-index 400,
   under /map's search card, toast and zoom rail (photographed by the owner on
   a phone). It is lifted above every map layer everywhere; on a phone it is a
   sheet from the bottom over a dimmed page, with a close button (auth.js). */
.auth-signin-pop{z-index:1450 !important}
.auth-signin-pop .auth-pop-title{padding-right:36px}
.auth-pop-x{position:absolute; top:8px; right:8px; width:36px; height:36px; display:grid; place-items:center;
  border:0; border-radius:8px; background:transparent; color:var(--rf-ink-2); font:400 24px/1 var(--rf-sans); cursor:pointer}
.auth-pop-x:hover{background:var(--rf-bg-2); color:var(--rf-ink)}
.auth-signin-scrim{display:none}
@media (max-width:760px){
  .auth-signin-scrim{display:block; position:fixed; inset:0; z-index:1440; background:rgba(10,15,25,.45);
    animation:rfSheetFade .2s ease-out both}
  .auth-signin-pop.auth-sheet{position:fixed; left:0; right:0; top:auto; bottom:0; width:auto; max-width:none;
    max-height:88vh; max-height:88dvh; overflow-y:auto; overscroll-behavior:contain;
    border-radius:16px 16px 0 0; border-bottom:0; padding:20px 16px calc(18px + env(safe-area-inset-bottom));
    animation:rfSheetUp .24s cubic-bezier(.2,.8,.2,1) both}
  .auth-signin-pop.auth-sheet .auth-gbtn{justify-content:center}
}
@keyframes rfSheetUp{from{transform:translateY(24px); opacity:0}to{transform:none; opacity:1}}
@keyframes rfSheetFade{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce){ .auth-signin-scrim, .auth-signin-pop.auth-sheet{animation:none} }

/* RF-LANG-SWITCH (23 September 2026) — "EN ▾" in the header. A <details>, so it
   opens and closes without a script and a keyboard reaches it for free. Plain
   links inside: each language is its own document (build-locales.py). Native
   names. RF-LANG-FLAGS (25 September 2026): the owner asked for flags, so each
   name has a small DRAWN flag before it (never an emoji: Windows shows emoji
   flags as two letters). English is the UK flag. The flag is decoration; the
   name is the label. */
.rf-lang{position:relative; flex:none}
.rf-lang > summary{list-style:none; cursor:pointer; display:inline-flex; align-items:center; gap:6px;
  min-height:36px; padding:0 10px 0 12px; border:1px solid var(--rf-line-strong); border-radius:999px;
  font:600 12px/1 var(--rf-mono); letter-spacing:.08em; color:var(--rf-ink-2);
  transition:color var(--rf-fast), border-color var(--rf-fast)}
.rf-lang > summary::-webkit-details-marker{display:none}
.rf-lang > summary::after{content:""; width:5px; height:5px; margin:-3px 1px 0 0;
  border-right:1.5px solid currentColor; border-bottom:1.5px solid currentColor; transform:rotate(45deg)}
.rf-lang > summary:hover, .rf-lang[open] > summary{color:var(--rf-ink); border-color:var(--rf-brand)}
.rf-lang > summary:focus-visible{outline:2px solid var(--rf-brand); outline-offset:2px}
.rf-lang ul{position:absolute; right:0; top:calc(100% + 8px); min-width:172px; margin:0; padding:6px;
  list-style:none; background:var(--rf-surface); border:1px solid var(--rf-line-strong);
  border-radius:12px; box-shadow:var(--rf-sh-3); z-index:1100}
.rf-lang a{display:flex; align-items:center; gap:10px; padding:10px 12px; border-radius:8px; color:var(--rf-ink); text-decoration:none;
  font-size:14px; line-height:1.2}

/* RF-FLAG-SIZE (24 September 2026): every flag is drawn 3:2 at 30x20 and
   stretched to the box. It used to be "cover", and iOS Safari cropped Spain's
   portrait drawing down to its yellow band (the owner's phone). */
.rf-flag{display:inline-block; flex:none; width:20px; height:14px; border-radius:3px; background:var(--rf-raised) 50% 50%/100% 100% no-repeat;
  box-shadow:inset 0 0 0 1px rgba(22,24,29,.14); vertical-align:middle}
.rf-flag--en{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 60 30' preserveAspectRatio='xMidYMid slice'%3E%3CclipPath id='t'%3E%3Cpath d='M30,15h30v15zv15h-30zh-30v-15zv-15h30z'/%3E%3C/clipPath%3E%3Cpath d='M0,0v30h60v-30z' fill='%23012169'/%3E%3Cpath d='M0,0 60,30M60,0 0,30' stroke='%23fff' stroke-width='6'/%3E%3Cpath d='M0,0 60,30M60,0 0,30' clip-path='url(%23t)' stroke='%23C8102E' stroke-width='4'/%3E%3Cpath d='M30,0v30M0,15h60' stroke='%23fff' stroke-width='10'/%3E%3Cpath d='M30,0v30M0,15h60' stroke='%23C8102E' stroke-width='6'/%3E%3C/svg%3E")}
.rf-flag--de{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect y='0' width='30' height='6.66667' fill='%23000'/%3E%3Crect y='6.66667' width='30' height='6.66667' fill='%23DD0000'/%3E%3Crect y='13.3333' width='30' height='6.66667' fill='%23FFCE00'/%3E%3C/svg%3E")}
.rf-flag--fr{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect x='0' width='10' height='20' fill='%23002395'/%3E%3Crect x='10' width='10' height='20' fill='%23fff'/%3E%3Crect x='20' width='10' height='20' fill='%23ED2939'/%3E%3C/svg%3E")}
.rf-flag--es{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect y='0' width='30' height='5' fill='%23AA151B'/%3E%3Crect y='5' width='30' height='10' fill='%23F1BF00'/%3E%3Crect y='15' width='30' height='5' fill='%23AA151B'/%3E%3C/svg%3E")}
.rf-flag--it{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect x='0' width='10' height='20' fill='%23009246'/%3E%3Crect x='10' width='10' height='20' fill='%23fff'/%3E%3Crect x='20' width='10' height='20' fill='%23CE2B37'/%3E%3C/svg%3E")}
.rf-flag--sv{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect width='30' height='20' fill='%23006AA7'/%3E%3Crect x='8.33' width='5' height='20' fill='%23FECC00'/%3E%3Crect y='7.5' width='30' height='5' fill='%23FECC00'/%3E%3C/svg%3E")}
.rf-flag--fi{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect width='30' height='20' fill='%23fff'/%3E%3Crect x='8.33' width='5' height='20' fill='%23002F6C'/%3E%3Crect y='7.5' width='30' height='5' fill='%23002F6C'/%3E%3C/svg%3E")}
.rf-flag--ro{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect x='0' width='10' height='20' fill='%23002B7F'/%3E%3Crect x='10' width='10' height='20' fill='%23FCD116'/%3E%3Crect x='20' width='10' height='20' fill='%23CE1126'/%3E%3C/svg%3E")}
.rf-flag--ru{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect y='0' width='30' height='6.66667' fill='%23fff'/%3E%3Crect y='6.66667' width='30' height='6.66667' fill='%230039A6'/%3E%3Crect y='13.3333' width='30' height='6.66667' fill='%23D52B1E'/%3E%3C/svg%3E")}
/* RF-TRUST-ROW: the two flags the footer's source list needs that no language
   uses - the United States (EIA) and the EU flag beside the ECB's euro rates. */
.rf-flag--us{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect width='30' height='20' fill='%23B22234'/%3E%3Cpath d='M0 2.31h30M0 5.38h30M0 8.46h30M0 11.54h30M0 14.62h30M0 17.69h30' stroke='%23fff' stroke-width='1.54'/%3E%3Crect width='12' height='10.77' fill='%233C3B6E'/%3E%3C/svg%3E")}
.rf-flag--eu{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='20' viewBox='0 0 30 20' preserveAspectRatio='none'%3E%3Crect width='30' height='20' fill='%23039'/%3E%3Cg fill='%23FC0'%3E%3Ccircle cx='15.00' cy='4.00' r='.95'/%3E%3Ccircle cx='18.00' cy='4.80' r='.95'/%3E%3Ccircle cx='20.20' cy='7.00' r='.95'/%3E%3Ccircle cx='21.00' cy='10.00' r='.95'/%3E%3Ccircle cx='20.20' cy='13.00' r='.95'/%3E%3Ccircle cx='18.00' cy='15.20' r='.95'/%3E%3Ccircle cx='15.00' cy='16.00' r='.95'/%3E%3Ccircle cx='12.00' cy='15.20' r='.95'/%3E%3Ccircle cx='9.80' cy='13.00' r='.95'/%3E%3Ccircle cx='9.00' cy='10.00' r='.95'/%3E%3Ccircle cx='9.80' cy='7.00' r='.95'/%3E%3Ccircle cx='12.00' cy='4.80' r='.95'/%3E%3C/g%3E%3C/svg%3E")}
.rf-lang > summary .rf-flag{width:18px; height:13px; margin-right:1px}
/* RF-LANG-POP (24 September 2026, the owner: "красивенько выскакивали"). The
   list drops in from the button — a short fade and slide, the rows a beat
   behind one another — once, on opening. Nothing moves with reduced motion. */
.rf-lang[open] > ul{transform-origin:top right; animation:rfLangPop .18s cubic-bezier(.2,.8,.2,1) both}
.rf-lang[open] > ul > li{animation:rfLangRow .22s ease-out both}
.rf-lang[open] > ul > li:nth-child(2){animation-delay:.02s} .rf-lang[open] > ul > li:nth-child(3){animation-delay:.04s}
.rf-lang[open] > ul > li:nth-child(4){animation-delay:.06s} .rf-lang[open] > ul > li:nth-child(5){animation-delay:.08s}
.rf-lang[open] > ul > li:nth-child(6){animation-delay:.10s} .rf-lang[open] > ul > li:nth-child(7){animation-delay:.12s}
.rf-lang[open] > ul > li:nth-child(8){animation-delay:.14s} .rf-lang[open] > ul > li:nth-child(n+9){animation-delay:.16s}
@keyframes rfLangPop{from{opacity:0; transform:translateY(-6px) scale(.97)} to{opacity:1; transform:none}}
@keyframes rfLangRow{from{opacity:0; transform:translateX(6px)} to{opacity:1; transform:none}}
.rf-lang[open] > summary::after{transform:rotate(225deg); margin-top:3px}
.rf-lang > summary::after{transition:transform .18s ease, margin .18s ease}
@media (prefers-reduced-motion:reduce){ .rf-lang[open] > ul, .rf-lang[open] > ul > li{animation:none} .rf-lang > summary::after{transition:none} }
/* RF-LANG-ON-TOP (30 September 2026). The header is z-index 60 and the language
   list lives INSIDE it, so every floating thing on a page with a higher z-index
   (the guide contents list at 400, the map's loading pill at 640) was drawn over
   the open list: a client saw two languages hidden under the contents list. The
   account menu (.auth-menu) sits in the same header and had the same problem on
   the map. While either menu is open the header now rises above all of those (and stays below the
   mobile drawer, the sticky CTA and the assistant button). Closed, nothing changes. */
body:not(.nav-open) .site-nav.rfs-nav:has(.rf-lang[open]),
body:not(.nav-open) .site-nav.rfs-nav:has(.auth-menu:not([hidden])){ z-index:1200 }
/* RF-LANG-FLAG-ONLY: on a phone the button is the flag alone — the code and
   the arrow crowded the bar next to the menu button. The summary keeps its
   aria-label ("Language: English"), so a screen reader loses nothing. */
@media (max-width:640px){
  .rf-lang > summary{font-size:0; gap:0; padding:0; width:44px; justify-content:center}
  .rf-lang > summary::after{display:none}
  .rf-lang > summary .rf-flag{width:24px; height:17px; margin:0; border-radius:4px}
}
.rf-lang a:hover{background:var(--rf-raised)}
.rf-lang a[aria-current]{color:var(--rf-brand); font-weight:600; background:var(--rf-raised)}
/* The suggestion bar: once, on an English page, when the browser prefers a
   language the page exists in. Never a redirect. */
.rf-lang-hint{position:fixed; left:50%; top:calc(var(--rf-nav-h, 64px) + 10px); transform:translateX(-50%);
  z-index:1090; display:flex; align-items:center; gap:10px; max-width:calc(100vw - 32px);
  padding:8px 8px 8px 14px; background:var(--rf-surface); border:1px solid var(--rf-line-strong);
  border-radius:999px; box-shadow:var(--rf-sh-3); font-size:14px; color:var(--rf-ink)}
.rf-lang-hint a{color:var(--rf-brand); font-weight:600; text-decoration:none}
.rf-lang-hint button{flex:none; width:32px; height:32px; border:0; border-radius:50%; background:transparent;
  color:var(--rf-ink-2); cursor:pointer; font-size:18px; line-height:1}
.rf-lang-hint button:hover{background:var(--rf-raised)}
/* A translated legal page says, in its own language, that English governs. */
.rf-legal-lang{margin:0 auto 20px; max-width:var(--rf-measure, 72ch); padding:12px 16px;
  border:1px solid var(--rf-line-strong); border-radius:12px; font-size:14px; line-height:1.5; color:var(--rf-ink-2)}

/* ============================================================================
   RF-NOT-GENERATED (23 September 2026). The owner's standard, in his words:
   "REFUELIA MUST NOT LOOK AI-GENERATED". No glass, no blur, no glow, no card
   wall. A container does not automatically get a background, a border, a
   radius and a shadow: the page must read with them removed. What floats over
   the map keeps one border and one small shadow, because there it separates
   two layers; everything else is rules, white space and alignment.
   ========================================================================= */

/* header: white, a thin bottom rule, graphite links, a short yellow mark
   under the current page */
.rfs-nav{
  background:var(--rf-bg) !important;
  -webkit-backdrop-filter:none !important; backdrop-filter:none !important;
  border-bottom:1px solid var(--rf-line) !important; box-shadow:none !important;
}
.rfs-nav .nav-links a[aria-current="page"]:not(.rfs-btn)::after{
  background:var(--rf-mark,var(--rf-brand)) !important; height:3px !important; border-radius:0 !important;
  left:50% !important; right:auto !important; width:22px !important; transform:translateX(-50%);
}
.rfs-nav .rf-lang summary, .rfs-nav .rf-topbar-signin, .rfs-nav .nav-signin,
.rfs-nav a.rfs-btn--secondary{ border-radius:var(--rf-r-ctl) !important }

/* the wordmark beside the plate: Plex Sans 600, set tight */
.rfs-nav .brand, .rfs-footer .brand{font-family:var(--rf-text) !important; font-weight:600 !important; letter-spacing:-.01em}

/* surfaces over the map: one border, one small shadow, 12px */
/* (RF-HOME-IS-THE-MAP: the home column is .rd-stage-side now, styled in
   road.css; the search block and the nearby list inside it paint nothing.) */
.rd-home .rfh-map-note,
.rd-home .rfh-map-zoom button,
.map-fab,
.leaflet-control-zoom a{
  background:var(--rf-surface) !important;
  -webkit-backdrop-filter:none !important; backdrop-filter:none !important;
  border-color:var(--rf-line-strong) !important;
  box-shadow:var(--rf-sh-2) !important;
}
.rd-home .rfh-map-note{border-radius:var(--rf-r-ctl) !important}

/* lists of stations are LISTS: rows on a rule, not a stack of cards */
.rd-home .rfh-card.rfh-st{
  background:transparent !important; border:0 !important; border-bottom:1px solid var(--rf-line) !important;
  border-radius:0 !important; box-shadow:none !important;
}
.rd-home .rfh-card.rfh-st:hover{background:var(--rf-bg-2) !important}

/* Explore / Route: a plain two-way switch, underlined, not a pill tray */
html.rf-map .mode-tabs{background:transparent; border:0; border-bottom:1px solid var(--rf-line); border-radius:0; padding:0; gap:0}
html.rf-map .mode-tab{border-radius:0; background:transparent !important; box-shadow:none !important; border-bottom:3px solid transparent; margin-bottom:-1px}
html.rf-map .mode-tab.active{border-bottom-color:var(--rf-mark,var(--rf-brand)); color:var(--rf-ink)}

/* the phone tab bar: white, a rule, the current tab marked by the yellow bar */
@media (max-width:767px){
  .rf-tabbar{
    background:var(--rf-bg) !important;
    -webkit-backdrop-filter:none !important; backdrop-filter:none !important;
    border-top:1px solid var(--rf-line) !important;
  }
  .rf-navtab[aria-current="page"],.rf-navtab.is-on{color:var(--rf-ink) !important}
  .rf-navtab[aria-current="page"]::before,.rf-navtab.is-on::before{
    background:var(--rf-mark,var(--rf-brand)) !important; width:26px !important; height:3px !important; border-radius:0 !important;
  }
}

/* one weight system: 400 / 500 / 600. Headings are 600, never 800. */
h1,h2,h3,h4,.rfh-hero h1{font-family:var(--rf-display); font-weight:600}

/* ==========================================================================
   RF-ONE-CHIP (23 September 2026). The owner: "remove the green background
   everywhere, one style for every button on the site, 100%".
   A measured inventory found eight chip looks for one job: green-filled route
   and ranking chips; map type chips at radius 12 in the old dark palette's
   blue-grey text; home chips at 36px; country chips at 41px; a graphite fill
   with white text on the route planner. Every chip that filters or chooses is
   now ONE component, whatever its class grew up as:
     at rest    white (surface), a 1px rule, secondary ink
     hover      the rule darkens, the ink goes full
     chosen     the yellow selection tint, a yellow edge, graphite ink, 600
   Yellow is the brand's SELECTION colour (§9). Green is a fuel STATUS and is
   never a chosen state. The status dots and type icons inside a chip keep their
   own colours — they are data. tests/one-chip.test.js holds this.
   ========================================================================== */
:is(.rf-key,.route-chip,.priority-btn,.explore-fuel-chip,.explore-vehicle-chip,.explore-connector-chip,
    .explore-queue-chip,.explore-sort-chip,.explore-open-toggle,.explore-247-toggle,.explore-today-toggle,
    .explore-prices-toggle,.explore-pricepins-toggle,.explore-unchecked-toggle,.explore-fuel-available-toggle,
    .explore-working-fuel-toggle,.report-fuel-chip,.report-queue-chip,.range-unit-chip,.range-style-chip,
    .rfh-chip,.cp-chip,.gd-chip,.rf-sort,.rf-qk-chip,.fa-status-chip,.ev-status-chip,.fa-fuel-chip,.svc-chip,
    .veh-kind-chip,.rfc-starter,.fn-cat-extra a,.rp-kindrow label,.rf-world-continents a,.rf-world-all){
  min-height:32px !important; height:auto !important; padding:0 12px !important; border-radius:999px !important;
  display:inline-flex; align-items:center; gap:6px;
  background:var(--rf-surface) !important; border:1px solid var(--rf-line-strong) !important;
  color:var(--rf-ink-2) !important; font-family:var(--rf-text) !important;
  font-size:13px !important; font-weight:500 !important; line-height:1.2;
  box-shadow:none !important; opacity:1; text-decoration:none !important;
  -webkit-backdrop-filter:none !important; backdrop-filter:none !important;
}
:is(.rf-key,.route-chip,.priority-btn,.explore-fuel-chip,.explore-vehicle-chip,.explore-connector-chip,
    .explore-queue-chip,.explore-sort-chip,.explore-open-toggle,.explore-247-toggle,.explore-today-toggle,
    .explore-prices-toggle,.explore-pricepins-toggle,.explore-unchecked-toggle,.explore-fuel-available-toggle,
    .explore-working-fuel-toggle,.report-fuel-chip,.report-queue-chip,.range-unit-chip,.range-style-chip,
    .rfh-chip,.cp-chip,.gd-chip,.rf-sort,.rf-qk-chip,.fa-status-chip,.ev-status-chip,.fa-fuel-chip,.svc-chip,
    .veh-kind-chip,.rfc-starter,.fn-cat-extra a,.rp-kindrow label,.rf-world-continents a,.rf-world-all):hover{
  border-color:var(--rf-ink-3,var(--rf-line-strong)) !important; color:var(--rf-ink) !important;
}
:is(.rf-key,.route-chip,.priority-btn,.explore-fuel-chip,.explore-vehicle-chip,.explore-connector-chip,
    .explore-queue-chip,.explore-sort-chip,.explore-open-toggle,.explore-247-toggle,.explore-today-toggle,
    .explore-prices-toggle,.explore-pricepins-toggle,.explore-unchecked-toggle,.explore-fuel-available-toggle,
    .explore-working-fuel-toggle,.report-fuel-chip,.report-queue-chip,.range-unit-chip,.range-style-chip,
    .rfh-chip,.cp-chip,.gd-chip,.rf-sort,.rf-qk-chip,.fa-status-chip,.ev-status-chip,.fa-fuel-chip,.svc-chip,
    .veh-kind-chip,.rp-kindrow label):is(.active,.is-on,.on,.is-active,.selected,[aria-pressed="true"],
    [aria-checked="true"],[aria-selected="true"]){
  background:var(--rf-brand-dim,rgba(255,201,40,.30)) !important;
  border-color:var(--rf-mark,#FFC928) !important;
  color:var(--rf-ink) !important; font-weight:600 !important;
}
/* The route planner's radio labels, on their own: a :has() inside the big
   :is() above made every chip on every page re-check its children on each DOM
   change — measured on the home page as 1.6 s of blocked main thread. */
.rp-kindrow label:has(> input:checked){
  background:var(--rf-brand-dim,rgba(255,201,40,.30)) !important; border-color:var(--rf-mark,#FFC928) !important;
  color:var(--rf-ink) !important; font-weight:600 !important;
}
/* A chip's own dot or icon is data; only the chip around it is the component. */
.rf-key .rf-key-dot{opacity:1 !important}
.rp-kindrow label input{accent-color:var(--rf-mark,#FFC928)}
/* the phone key bar sizes its chips to share the row; keep that */
@media (max-width:900px){ .rf-keybar .rf-key{padding:0 10px !important} }

/* ==========================================================================
   RF-ONE-BUTTON (23 September 2026), the same brief. The inventory found the
   primary action at 700 and 600, radius 6 / 8 / 10 / 12 / 14, and in four
   places as a GRAPHITE block — one of them (/account "Sign in with Google")
   with near-black text on it, which is to say unreadable. The secondary action
   came translucent with a blur, grey-filled ("Clear route"), or outlined.
   Now there are two buttons on this site, full stop:
     primary    yellow plate, graphite text, 600, radius 8   (--rf-cta-*)
     secondary  surface, a 1px rule, graphite text, 600, radius 8
   Sizes stay per context (a sidebar button is smaller than a hero one), but a
   bare .btn is 44px and .btn-lg 52px, not 58.
   ========================================================================== */
.btn{padding:11px 20px; font-size:15px; border-radius:var(--rf-cta-radius,8px)}
.btn.btn-lg{padding:14px 24px; font-size:15.5px}
:is(.btn,.rf-btn,.rfs-btn,.rfh-btn,.fn-primary,.fn-signin-btn,#fn-alert-btn,.rfp-signin){
  font-family:var(--rf-text) !important; font-weight:600 !important;
  border-radius:var(--rf-cta-radius,8px) !important; box-shadow:none !important;
  background-image:none !important; -webkit-backdrop-filter:none !important; backdrop-filter:none !important;
}
:is(.btn.primary,.rf-btn--primary,.rfs-btn--primary,.rfh-btn--primary,.fn-primary,.fn-signin-btn,#fn-alert-btn,.rfp-signin){
  background:var(--rf-cta-bg,#FFC928) !important; color:var(--rf-cta-ink,#16181D) !important;
  border:1px solid var(--rf-cta-bg,#FFC928) !important;
}
:is(.btn.primary,.rf-btn--primary,.rfs-btn--primary,.rfh-btn--primary,.fn-primary,.fn-signin-btn,#fn-alert-btn,.rfp-signin):hover{
  background:var(--rf-cta-bg-hover,#FFD659) !important; border-color:var(--rf-cta-bg-hover,#FFD659) !important; filter:none !important;
}
:is(.btn.ghost,.btn.secondary,.rf-btn--secondary,.rfs-btn--secondary,.rfh-btn--secondary){
  background:var(--rf-surface) !important; color:var(--rf-ink) !important;
  border:1px solid var(--rf-line-strong) !important;
}
:is(.btn.ghost,.btn.secondary,.rf-btn--secondary,.rfs-btn--secondary,.rfh-btn--secondary):hover{
  background:var(--rf-bg-2) !important; border-color:var(--rf-ink-3) !important;
}
/* RF-ACCOUNT-CLEAR (24 September 2026): the one destructive action, a third
   button. site.css drew .btn.danger as a red GRADIENT, and the background-image
   reset above removed it - "Delete my account" showed as plain dark text. Now:
   outlined in the status red for the button that opens the question, solid red
   for the one that answers it. Nothing else on the site is red-filled. */
.btn.danger{ background:var(--rf-surface) !important; color:var(--rf-out) !important; border:1px solid var(--rf-out) !important; }
.btn.danger:hover{ background:var(--rf-out-dim, rgba(200,51,47,.08)) !important; transform:none !important; filter:none !important; }
.btn.danger-solid{ background:var(--rf-out) !important; color:#fff !important; border:1px solid var(--rf-out) !important; }
.btn.danger-solid:hover{ filter:brightness(.94) !important; }
.btn.danger-solid:disabled, .btn.danger-solid[disabled]{ opacity:.45; cursor:not-allowed; filter:none !important; }
/* the sidebar's small outlined actions ("Directions →") are secondary buttons */
.res-acts > a{border-radius:var(--rf-cta-radius,8px) !important}
/* /fuel-now category tiles: cards, so card radius and a solid surface */
.fn-cat{border-radius:var(--rf-r-card,10px) !important; background:var(--rf-surface) !important}

/* ============================================================================
   RF-NO-OLD-GREEN (24 September 2026). The owner, on /map: "Show all stations"
   is yellow, and when you press it, it turns green. That was .rf-load-pill
   .rt:hover {#4af0bb} — the old project's mint, which a finger leaves "hovered"
   after a tap. His rule: no green left over from the old palette, anywhere in
   the interface.
   What stays green, and why: the ONE status green (--rf-ok) where it is fuel
   DATA — fuel confirmed, available, fresh report, open now — and the petrol
   fill (--pin-petrol) in the legend. Those are the map's language and the
   legend explains them. Everything else that was green — buttons, hovers,
   links, toasts, badges, "live" dots, tip boxes, step numbers — is brand
   yellow or neutral now. The old mint tokens are folded into --rf-ok so no
   second green can come back through a variable. Found by walking every
   stylesheet rule on 20 pages and resolving each colour (tests/no-old-green).
   ========================================================================= */
:root, html[data-theme="light"], html[data-theme="dark"]{ --ok:var(--rf-ok); --green:var(--rf-ok); }
/* interactive: buttons, links, hovers */
html body .sheet-body .btn.ghost:hover{ background:var(--rf-raised) !important; }
html body .veh-cls .veh-v.yes:hover{ background:var(--rf-bg-2) !important; border-color:var(--rf-line-strong) !important; color:var(--rf-ink) !important; }
html body .ntf-toast a{ color:#FFC928; }
html body .map-shot-foot .map-shot-cta,
html body .see-action .map-shot-cta{ background:var(--rf-cta-bg,#FFC928) !important; color:var(--rf-cta-ink,#16181D) !important; }
html body .lds-cta-in, html body .lda-empty a{ color:var(--rf-ink); }
html body .form-success{ color:var(--rf-ink); background:var(--rf-bg-2); border-color:var(--rf-mark,#FFC928); }
html body .rf-rebuild b{ color:#FFC928; }
/* "live" and activity markers are not a fuel status: brand yellow */
html body .pulse-dot, html body .pulse-dot::after, html body .dot-live,
html body .rf-activity-inline .rf-act-dot{ background:#FFC928; }
html body .rf-activity-inline .rf-act-dot{ background:none; color:#E0A800; }
html body .radar .ring{ border-color:rgba(22,24,29,.14); }
html body .radar .axis{ background:rgba(22,24,29,.10); }
/* labels and decoration: neutral */
html body .acc-src-tag.acc-src-official,
html body[data-theme] .acc-src-tag.acc-src-official,
[data-theme="dark"] .acc-src-tag.acc-src-official{ color:var(--rf-ink-2) !important; border-color:var(--rf-line-strong) !important; background:transparent !important; }
html body .cov-badge.cov-available,
[data-theme="dark"] .cov-badge.cov-available{ color:var(--rf-ink) !important; background:var(--rf-bg-2) !important; border-color:var(--rf-line-strong) !important; }
html body .mk-fresh.ok,
[data-theme="dark"] .mk-fresh.ok{ color:var(--rf-ink-2) !important; background:var(--rf-bg-2) !important; border-color:var(--rf-line) !important; }
html body .msg-rule-yes .msg-rule-tag{ color:var(--rf-ink); }
html body .map-shot-bar .d.g{ background:#C9CDD2; }
html body .df-ev{ background:var(--pin-ev,#159bb0); color:#fff; }
html body .fuelbar > i{ background:#FFC928; }
html body .ld-step .lds-n{ background:var(--rf-bg-2); border-color:var(--rf-line-strong); color:var(--rf-ink); }
html body .ld-tip{ background:var(--rf-brand-dim,rgba(255,201,40,.18)); border-color:var(--rf-mark,#FFC928); }
html body .ld-tip-body b{ color:var(--rf-ink); }
html body .admin-ok{ color:var(--rf-ok); }
/* a cheaper price is highlighted as a SELECTION (yellow), not as a status */
html body .pin-price.is-cheap{ background:#FFC928; color:#16181D; }
html body .rf-cheaper, html body .rf-cheaper-h, html body .rf-area b{ color:var(--rf-ink); }
/* status-coloured data keeps the ONE status green, never the old mints */
html body .stbadge::after, html body .stb-dot{ background:var(--stc, var(--rf-ok)); box-shadow:none; }
html body .rf-sc-bar i{ background:var(--rf-ok); }
html body .status-dot.ok, html body .feed-dot.ok, html body .ldk-badge.g,
html body .lds-open .od, html body .lda-dot{ background:var(--rf-ok); box-shadow:none; }
html body .lds-open{ color:var(--rf-ok); background:var(--rf-ok-dim); border-color:color-mix(in srgb, var(--rf-ok) 35%, transparent); }
html body .fa-badge.fa-available, html body .fr-badge.fr-fresh, html body .live-tag-ok,
[data-theme="dark"] .fa-badge.fa-available, [data-theme="dark"] .fr-badge.fr-fresh{ color:var(--rf-ok) !important; border-color:color-mix(in srgb, var(--rf-ok) 35%, transparent) !important; }
html body .cov-badge.cov-available{ }
html body .ntf-dot.ntf-ev_available, html body .ntf-dot.ntf-fuel_available{ background:var(--rf-ok); }
html body .rf-cluster.rf-g div{ background:var(--pin-station,#0F62FE); }

/* RF-SHORT-ANSWERS (24 September 2026). Search Console showed drivers asking
   these guides exact questions ("why is diesel more expensive than petrol",
   "what does a ccs connector look like") and the guides answering them only
   deep in long sections, at positions 30-95. Each guide now opens with those
   questions in the searcher's own words and a direct answer drawn from the
   article below. A ruled block, not a card. */
.article .rf-short-answers{margin:8px 0 28px; padding:14px 0 4px; border-top:2px solid var(--rf-mark,#FFC928); border-bottom:1px solid var(--rf-line)}
.article .rf-short-answers .rf-sa-label{margin:0 0 6px; font:600 11px/1 var(--rf-mono); letter-spacing:.09em; text-transform:uppercase; color:var(--rf-ink-3)}
.article .rf-short-answers h2{margin:14px 0 6px; font-size:18px; line-height:1.3}
.article .rf-short-answers p{margin:0 0 10px}

/* RF-FONTS-AT-HOME (24 September 2026). IBM Plex Sans and Mono used to come
   from fonts.googleapis.com / fonts.gstatic.com, which hands every visitor's IP
   address to Google on the first paint, before the cookie banner has asked
   anything (the Munich court ruled on exactly that in 2022). The same files
   are now served from our own domain: the OFL-licensed woff2 builds from
   @fontsource, weights 400/500/600, subsets latin, latin-ext (Romanian ș ț),
   cyrillic and cyrillic-ext (Russian). unicode-range means a page downloads
   only the subsets its text uses. tests/prior-consent.test.js keeps Google's
   font hosts out of every public page. */
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-cyrillic-ext-400-normal.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-cyrillic-400-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-latin-ext-400-normal.woff2) format('woff2');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}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-latin-400-normal.woff2) format('woff2');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+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-cyrillic-ext-500-normal.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-cyrillic-500-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-latin-ext-500-normal.woff2) format('woff2');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}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-latin-500-normal.woff2) format('woff2');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+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-cyrillic-ext-600-normal.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-cyrillic-600-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-latin-ext-600-normal.woff2) format('woff2');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}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/ibm-plex-sans-latin-600-normal.woff2) format('woff2');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+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-cyrillic-ext-400-normal.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-cyrillic-400-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-latin-ext-400-normal.woff2) format('woff2');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}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-latin-400-normal.woff2) format('woff2');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+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-cyrillic-ext-500-normal.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-cyrillic-500-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-latin-ext-500-normal.woff2) format('woff2');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}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-latin-500-normal.woff2) format('woff2');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+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-cyrillic-ext-600-normal.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-cyrillic-600-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-latin-ext-600-normal.woff2) format('woff2');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}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-latin-600-normal.woff2) format('woff2');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+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

/* RF-COUNTRY-OFFICIAL (24 September 2026). Official prices and availability on a
   country page (France first): a ruled table and a ruled list on the page, no
   cards, the same tokens as the rest of the shell. */
.cfo{ padding:var(--rf-7,32px) 0 0 }
.cfo-table, .cfo-avail, .cfo-dl{ max-width:860px }
.cfo-said, .cfo-src, .cfo-more{ max-width:72ch }
.cfo-kicker{ margin:0; font:500 11px/1.2 var(--rf-mono); letter-spacing:.1em; text-transform:uppercase; color:var(--rf-ink-3) }
.cfo h2, .cfo-names h2{ margin:6px 0 0; font-size:clamp(22px,2.6vw,28px); line-height:1.2; font-weight:600; color:var(--rf-ink) }
.cfo-lead{ margin:8px 0 0; font-size:15.5px; line-height:1.55; color:var(--rf-ink-2); max-width:66ch }
.cfo-table{ width:100%; margin:16px 0 0; border-collapse:collapse; font-size:15px }
.cfo-table th, .cfo-table td{ padding:11px 8px; border-bottom:1px solid var(--rf-line); text-align:left; vertical-align:baseline }
.cfo-table tbody tr:last-child > *{ border-bottom:1px solid var(--rf-line) !important }
.cfo-table thead th{ font:500 11px/1.2 var(--rf-mono); letter-spacing:.08em; text-transform:uppercase; color:var(--rf-ink-3); border-bottom:1px solid var(--rf-line-strong) }
.cfo-table tbody th b{ display:block; font-weight:600; color:var(--rf-ink) }
.cfo-table tbody th span{ display:block; margin-top:2px; font-size:13px; font-weight:400; color:var(--rf-ink-3) }
.cfo-price{ font:600 19px/1.2 var(--rf-mono); color:var(--rf-ink); white-space:nowrap; font-variant-numeric:tabular-nums }
.cfo-price span{ font:400 12.5px/1 'IBM Plex Sans', system-ui, sans-serif; color:var(--rf-ink-3) }
.cfo-n{ color:var(--rf-ink-2); font-size:13.5px; white-space:nowrap; font-variant-numeric:tabular-nums }
.cfo-said{ margin:14px 0 0; font-size:15px; line-height:1.55; color:var(--rf-ink) }
.cfo-src{ margin:10px 0 0; font-size:13px; line-height:1.5; color:var(--rf-ink-3) }
.cfo-src a{ color:inherit; text-decoration:underline; text-underline-offset:2px }
.cfo-go{ display:flex; flex-wrap:wrap; gap:10px; margin-top:16px }
.cfo-avail{ list-style:none; margin:14px 0 0; padding:0; border-top:1px solid var(--rf-line); display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); column-gap:28px }
.cfo-avail li{ padding:10px 0; border-bottom:1px solid var(--rf-line); font-size:14.5px }
.cfo-avail b{ display:block; font-weight:600; color:var(--rf-ink) }
.cfo-avail span{ color:var(--rf-ink-2) }
.cfo-avail strong{ color:var(--rf-out); font-weight:600 }
.cfo-names{ padding:var(--rf-7,32px) 0 var(--rf-4,8px) }
.cfo-dl{ margin:14px 0 0; border-top:1px solid var(--rf-line) }
.cfo-dl > div{ display:grid; grid-template-columns:180px 1fr; gap:4px 20px; padding:11px 0; border-bottom:1px solid var(--rf-line) }
.cfo-dl dt{ font-weight:600; color:var(--rf-ink) }
.cfo-dl dd{ margin:0; font-size:15px; line-height:1.5; color:var(--rf-ink-2) }
.cfo-more{ margin:12px 0 0; font-size:14px; color:var(--rf-ink-2) }
@media (max-width:640px){
  .cfo-table{ font-size:14px }
  .cfo-table th, .cfo-table td{ padding:10px 4px }
  .cfo-price{ font-size:16.5px }
  .cfo-price span{ display:block }
  .cfo-avail{ grid-template-columns:1fr }
  .cfo-dl > div{ grid-template-columns:1fr }
  .cfo-go .btn{ flex:1 1 100%; justify-content:center }
}

/* RF-LPG-MAP (24 September 2026): the LPG map on /lpg. The map card and the
   station cards are the home map's own (home.css); this only lays them out on
   an ordinary page: map beside the nearest list, stacked on a phone. */
.lpgm{ padding:var(--rf-6,24px) 0 0 }
.lpgm-grid{ display:grid; grid-template-columns:minmax(0,1fr) 340px; gap:20px; align-items:stretch }
.lpgm-map{ height:520px; min-height:0 }
.lpgm-side{ display:flex; flex-direction:column; max-height:520px }
.lpgm-side .rfh-nearby-head h2{ margin:0; font-size:19px; font-weight:600 }
.lpgm-go{ margin-top:12px; justify-content:center }
/* RF-MAP-FAILED: the page's own map card shrinks to its message instead of
   keeping a 520px grey frame, and the list beside it stops stretching to it. */
.lpgm-map.is-failed{ height:auto; min-height:0 }
.lpgm-map.is-failed .rfh-map{ display:none }
.lpgm-map.is-failed .rfh-map-note.is-fail{ position:static; max-width:none; margin:0; padding:16px; border:0; border-radius:0; background:none; -webkit-backdrop-filter:none; backdrop-filter:none }
.lpgm-grid:has(.lpgm-map.is-failed){ align-items:start }
@media (max-width:860px){
  .lpgm-grid{ grid-template-columns:1fr }
  .lpgm-map{ height:60vh; min-height:320px }
  .lpgm-side{ max-height:none }
  .lpgm-side .rfh-nearby-list{ flex-direction:column; overflow:visible }
  .lpgm-side .rfh-nearby-list > *{ flex:none }
}

/* ==========================================================================
   RF-NAV-GLIDE (25 September 2026). The owner: the header switches "топорно".
   Three things made it so, measured on the live site:
   1. the current link turned 650-weight, so it got 1px wider and the links
      after it shifted when the page changed (and 650 is off the 400/500/600
      scale in the guidelines anyway): every link now keeps its weight, and
      "you are here" is the ink colour plus the yellow mark;
   2. the mark vanished under one word and reappeared under another: it is now
      one element (.rf-nav-ink, written by the script in nav.tpl) that slides
      there, and the next page continues the slide;
   3. colour changes were instant on press: they now ease.
   Without the script (.rf-ink-on missing) the old ::after mark still shows.
   ========================================================================== */
.rfs-nav .nav-links a[aria-current="page"]:not(.rfs-btn){font-weight:500}
.rfs-nav .nav-links a:not(.rfs-btn){transition:color var(--rf-motion-medium) var(--rf-ease-standard), background-color var(--rf-motion-medium) var(--rf-ease-standard)}
.rfs-nav .nav-links a.rf-nav-going:not(.rfs-btn){color:var(--rf-ink)}
.rfs-nav .nav-links a.rf-nav-leaving:not(.rfs-btn){color:var(--rf-ink-2)}
.rf-nav-ink{display:none}
@media (min-width:768px){
  .rfs-nav .nav-links{position:relative}
  .rfs-nav.rf-ink-on .nav-links a[aria-current="page"]:not(.rfs-btn):not([data-nav="account"])::after{content:none !important}
  .rfs-nav .nav-links > li.rf-nav-ink{display:block; position:absolute; left:0; top:0; width:22px; height:3px; margin:0; padding:0;
    background:var(--rf-mark,var(--rf-brand)); pointer-events:none; opacity:0; list-style:none; will-change:transform}
}
@media (prefers-reduced-motion:reduce){
  .rfs-nav .nav-links a:not(.rfs-btn){transition:none}
}
/* RF-NAV-GLIDE, part 4 (27 September 2026): the page under the header
   dissolves instead of being cut. The script in nav.tpl sets html.rf-leave on
   a press in the header and html.rf-arrive on the page it lands on, with
   --rf-arrive-from = how far the old page had dimmed, so the two halves meet.
   The header itself is never faded: it is the one thing that stays.
   `backwards`, not `both`: once the fade is over no animation holds opacity,
   so no stacking context is left behind on main or the footer. */
@keyframes rf-arrive{from{opacity:var(--rf-arrive-from,.3)}}
@media (min-width:768px) and (prefers-reduced-motion:no-preference){
  html.rf-leave body > :not(.rfs-nav){opacity:.3; transition:opacity var(--rf-motion-fast) var(--rf-ease-exit)}
  html.rf-arrive body > :not(.rfs-nav):not(script):not(style):not(link){animation:rf-arrive var(--rf-motion-slow) var(--rf-ease-enter) backwards}
}
/* RF-NAV-GLIDE, part 2: the links stand still. They used to be pushed right by
   whatever sat after them, so they moved whenever that changed: 133 px between
   /map (no "Open the map" button) and every other page, and ~30 px on every
   load when the sign-in control arrived. Now they start after the logo and the
   variable items (language, the button, sign-in) sit at the far right, so
   nothing on their right can move them. */
@media (min-width:768px){
  .rfs-nav .nav-right{flex:1 1 auto; min-width:0}
  .rfs-nav .nav-right > .nav-links{margin-right:auto; margin-left:var(--rf-4)}
  /* site.css gives menu links the drawer's 48px rows below 1180px; on the
     desktop bar that set the words at the top of a tall box, 7px above the
     buttons beside them and far above the mark. */
  .rfs-nav .nav-links a:not(.rfs-btn){min-height:0}
}
/* 768-1023px: the bar did not fit — "How it works" was cut off. The yellow
   button goes (the Map link is the same place, first in the row) and the links
   sit a little closer. */
@media (min-width:768px) and (max-width:1023px){
  .rfs-nav .rfs-nav-cta{display:none}
  .rfs-nav .nav-links a:not(.rfs-btn){padding-left:8px; padding-right:8px}
}
a.auth-signin-btn{text-decoration:none}

/* ==========================================================================
   RF-ART (25 September 2026). The owner asked for pictures wherever a page
   needs one, each one different. They are drawings, not photographs: sharp
   at any size, a few KB, no licence question, and never mistakable for a
   stock photo or a render. Words stay in HTML under the drawing so every
   language gets them; a code such as E10 is drawn only where the code IS the
   picture. The palette is the RF-TRIP one, with its own dark theme.
   ========================================================================== */
.rf-art{margin:var(--rf-6,24px) 0;
  --ra-bg:#FFFFFF; --ra-gr:#F6F7F8; --ra-soft:#E4E8EC; --ra-mid:#C2C8D0; --ra-ink:#16181D; --ra-ink2:#4A5059;
  --ra-face:#FFFFFF; --ra-y:#FFC928; --ra-car:#4A5059; --ra-glass:#DCE7F1}
:root:not([data-theme="light"]) .rf-art{--ra-bg:#16181C; --ra-gr:#1C1F23; --ra-soft:#262A30; --ra-mid:#3A3F47;
  --ra-ink:#E6E8EB; --ra-ink2:#9AA1AA; --ra-face:#23262B; --ra-car:#B8BFC8; --ra-glass:#DCE7F1}
:root:not([data-theme="light"]) .rfs-paper .rf-art{--ra-bg:#FFFFFF; --ra-gr:#F6F7F8; --ra-soft:#E4E8EC; --ra-mid:#C2C8D0;
  --ra-ink:#16181D; --ra-ink2:#4A5059; --ra-face:#FFFFFF; --ra-car:#4A5059}
.rf-art-pic{border:1px solid var(--rf-line-faint,#E7EAEE); border-radius:12px; overflow:hidden; background:var(--ra-bg)}
.rf-art-pic svg{display:block; width:100%; height:auto}
.rf-art-legend{display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:10px 20px;
  margin:14px 0 0; padding:0; list-style:none; font-size:14px; line-height:1.45}
.rf-art-legend li{margin:0; padding:0}
.rf-art-legend b{display:block; font-weight:600; color:var(--rf-ink,#16181D)}
.rf-art-legend span{color:var(--rf-ink-2,#4A5059)}
.rf-art-legend .ra-key{display:inline-block; width:12px; height:12px; border-radius:3px; margin-right:8px; vertical-align:-1px;
  box-shadow:inset 0 0 0 1.5px var(--rf-ink,#16181D)}
.rf-art figcaption{margin-top:8px; font-size:12.5px; color:var(--rf-ink-3,#646B75)}
.rf-art .ra-bg{fill:var(--ra-bg)} .rf-art .ra-gr{fill:var(--ra-gr)} .rf-art .ra-soft{fill:var(--ra-soft)}
.rf-art .ra-mid{fill:var(--ra-mid)} .rf-art .ra-ink{fill:var(--ra-ink)} .rf-art .ra-y{fill:var(--ra-y)}
.rf-art .ra-face{fill:var(--ra-face); stroke:var(--ra-ink); stroke-width:3; stroke-linejoin:round}
.rf-art .ra-yk{fill:var(--ra-y); stroke:#16181D; stroke-width:2.5}
.rf-art .ra-pin{fill:var(--ra-ink)} .rf-art .ra-dc{fill:var(--ra-y); stroke:#16181D; stroke-width:2.5}
.rf-art .ra-ring{fill:none; stroke:var(--ra-ink); stroke-width:2.5}
.rf-art .ra-edge{stroke:var(--ra-ink); stroke-width:2}
.rf-art .ra-line{fill:none; stroke:var(--ra-ink); stroke-width:3; stroke-linecap:round}
.rf-art .ra-tick{fill:none; stroke:#16181D; stroke-width:4; stroke-linecap:round; stroke-linejoin:round}
.rf-art .ra-dash{fill:none; stroke:var(--ra-mid); stroke-width:2; stroke-dasharray:6 7}
.rf-art .ra-cable{fill:none; stroke:var(--ra-ink); stroke-width:4; stroke-linecap:round}
.rf-art .ra-cable--thick{stroke-width:7}
.rf-art .ra-bolt{fill:var(--ra-y)}
.rf-art .ra-car{fill:var(--ra-car); stroke:#16181D; stroke-width:2.2; stroke-linejoin:round}
.rf-art .ra-glass{fill:var(--ra-glass); stroke:#16181D; stroke-width:1.8; stroke-linejoin:round}
.rf-art .ra-tyre{fill:#16181D} .rf-art .ra-hub{fill:#DCE0E5}
.rf-art .ra-hand{fill:var(--ra-mid)}
.rf-art .ra-drop{fill:var(--ra-y); stroke:#16181D; stroke-width:2.5}
.rf-art .ra-l1{fill:#16181D} .rf-art .ra-l2{fill:#4A5059} .rf-art .ra-l3{fill:#C2C8D0}
.rf-art .ra-l4{fill:#E4E8EC; stroke:#C2C8D0; stroke-width:1.5} .rf-art .ra-l5{fill:var(--ra-y)}
.rf-art .ra-code{font:600 26px 'IBM Plex Mono',ui-monospace,monospace; fill:var(--ra-ink); text-anchor:middle}
.rf-art .ra-code--s{font-size:20px}
.rf-art .ra-l1, .rf-art .ra-l2, .rf-art .ra-l3{stroke:var(--ra-ink); stroke-width:1.5}
.rf-art--side{display:grid; grid-template-columns:minmax(0,240px) minmax(0,1fr); gap:28px; align-items:center}
.rf-art--side .rf-art-legend{grid-template-columns:1fr; margin:0}
.rf-art--side figcaption{grid-column:1 / -1}
.rf-art--narrow .rf-art-pic{max-width:260px}
.rf-art-legend li:has(> .ra-key){display:grid; grid-template-columns:22px minmax(0,1fr); column-gap:2px}
.rf-art-legend li > .ra-key{grid-row:span 2; margin:4px 0 0}
@media (max-width:560px){ .rf-art--side{grid-template-columns:minmax(0,180px) minmax(0,1fr); gap:16px} }

/* ===========================================================================
   RF-ONE-FIELD (25 September 2026) — one text field, one select, one
   checkbox, one file picker, site-wide.

   The owner circled the feedback form: a native grey "Choose File" button and
   "No file chosen" in the browser's own font, sitting among fields drawn by
   the page. Measured across the site that day, the same kind of control was
   drawn nine ways: heights 33, 41, 44, 45, 47, 48, 51, 53 and 55px, radii
   6, 8, 10 and 11px, text 13 to 16.5px, three backgrounds, native select
   arrows next to custom ones, two native checkboxes with no brand at all.

   One definition now, stronger than any page rule on purpose: the selector
   carries an id's weight through :is(html, #rf-one-field), so a page style
   can lay a field out (width, flex, margin) but cannot redraw it. 16px text
   keeps iOS from zooming into a field. Opt-out: .rf-field-free, for a field
   that is part of a composite control (the hero search, the map search, the
   chat and assistant composers, which size themselves to one line).
   ========================================================================= */
:root:is(html,#rf-one-field) :is(input:is([type=text],[type=email],[type=search],[type=number],[type=tel],[type=url],[type=password],[type=date],[type=time],[type=datetime-local],:not([type])),select,textarea):not(.rf-field-free,.rfc-in,.rfa-in):not(#rfh-q):not(#map-search-input){
  box-sizing:border-box; min-height:46px; padding:0 14px;
  font:400 16px/1.4 var(--rf-text); color:var(--rf-ink);
  background-color:var(--rf-surface); border:1px solid var(--rf-line-strong);
  border-radius:var(--rf-r-ctl); box-shadow:none; outline:none;
  transition:border-color var(--rf-fast), box-shadow var(--rf-fast);
}
:root:is(html,#rf-one-field) textarea:not(.rf-field-free,.rfc-in,.rfa-in):not(#rfh-q):not(#map-search-input):not([hidden]){ min-height:112px; padding:12px 14px; line-height:1.5; resize:vertical }
:root:is(html,#rf-one-field) :is(input,select,textarea):not(.rf-field-free,.rfc-in,.rfa-in):not(#rfh-q):not(#map-search-input)::placeholder{ color:var(--rf-ink-3); opacity:1 }
:root:is(html,#rf-one-field) :is(input:is([type=text],[type=email],[type=search],[type=number],[type=tel],[type=url],[type=password],[type=date],[type=time],[type=datetime-local],:not([type])),select,textarea):not(.rf-field-free,.rfc-in,.rfa-in):not(#rfh-q):not(#map-search-input):hover{ border-color:var(--rf-ink-3) }
:root:is(html,#rf-one-field) :is(input:is([type=text],[type=email],[type=search],[type=number],[type=tel],[type=url],[type=password],[type=date],[type=time],[type=datetime-local],:not([type])),select,textarea):not(.rf-field-free,.rfc-in,.rfa-in):not(#rfh-q):not(#map-search-input):focus{
  border-color:var(--rf-ink); box-shadow:0 0 0 3px var(--rf-brand-dim);
}
:root:is(html,#rf-one-field) :is(input,select,textarea):not(.rf-field-free,.rfc-in,.rfa-in)[aria-invalid="true"]{ border-color:var(--rf-out) }
:root:is(html,#rf-one-field) :is(input,select,textarea):not(.rf-field-free,.rfc-in,.rfa-in):disabled{ opacity:.55; cursor:not-allowed }

/* The select: our chevron, not the browser's. Two images because a data: URI
   cannot read a custom property; the dark one follows the theme rules above. */
:root:is(html,#rf-one-field) select:not(.rf-field-free,.rfc-in,.rfa-in):not(#rfh-q):not(#map-search-input):not([hidden]){
  -webkit-appearance:none; appearance:none; padding-right:40px; cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%234A5059' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 14px center; background-size:12px 8px;
}
:root:not([data-theme="light"]) select:not(.rf-field-free,.rfc-in,.rfa-in):not(#rfh-q):not(#map-search-input){
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23A8A7A0' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
}
:root:not([data-theme="light"]) .rfs-paper select:not(.rf-field-free,.rfc-in,.rfa-in):not(#rfh-q):not(#map-search-input){
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%234A5059' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
}

/* The checkbox: a 20px box on the control radius, the yellow mark plate with a
   graphite tick when chosen (--rf-brand is graphite in the light theme) — the same yellow a chosen chip uses. */
:root:is(html,#rf-one-field) input[type=checkbox]:not(.rf-field-free,.rfc-in,.rfa-in){
  -webkit-appearance:none; appearance:none; box-sizing:border-box;
  width:20px; height:20px; min-height:0; margin:1px 0 0; padding:0; flex:none;
  border:1.5px solid var(--rf-line-strong); border-radius:5px;
  background:var(--rf-surface) center/13px 13px no-repeat; cursor:pointer; vertical-align:-4px;
  transition:background-color var(--rf-fast), border-color var(--rf-fast);
}
:root:is(html,#rf-one-field) input[type=checkbox]:not(.rf-field-free,.rfc-in,.rfa-in):hover{ border-color:var(--rf-ink-3) }
:root:is(html,#rf-one-field) input[type=checkbox]:not(.rf-field-free,.rfc-in,.rfa-in):checked{
  background-color:var(--rf-mark,#FFC928); border-color:var(--rf-mark,#FFC928);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M2.5 7.4l3 3 6-6.4' fill='none' stroke='%2316140F' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
:root:is(html,#rf-one-field) input[type=checkbox]:not(.rf-field-free,.rfc-in,.rfa-in):focus-visible{ outline:2px solid var(--rf-ink); outline-offset:2px }
:root:is(html,#rf-one-field) input[type=checkbox]:not(.rf-field-free,.rfc-in,.rfa-in):disabled{ opacity:.5; cursor:not-allowed }

/* The file picker. The real input stays in the page (keyboard, screen reader,
   form reset) but is drawn by its label: a secondary button, then the file's
   name in our type. main.js (RF-ONE-FIELD) writes the name. */
.rf-file{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; position:relative }
.rf-file > input[type=file]{ position:absolute; width:1px; height:1px; opacity:0; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap }
.rf-file-btn{ cursor:pointer; border-radius:var(--rf-r-ctl) }
.rf-file > input[type=file]:focus-visible + .rf-file-btn{ outline:2px solid var(--rf-ink); outline-offset:2px }
.rf-file-name{ font-size:var(--rf-t-sm); color:var(--rf-ink-3); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100% }
.rf-file.has-file .rf-file-name{ color:var(--rf-ink) }
.rf-file-preview{ display:none; max-width:120px; max-height:80px; border-radius:var(--rf-r-ctl); border:1px solid var(--rf-line) }
.rf-file.has-preview .rf-file-preview{ display:block }

/* RF-COUNTRY-NOTES (26 September 2026): the sub-heads inside a country's
   "names on the pump" section (price rules, motorway, where prices come from). */
.cfo-names .cfo-sub{ margin:24px 0 0; font-size:18px; line-height:1.3; font-weight:600; color:var(--rf-ink) }
.cfo-names .cfo-src{ margin-top:16px }
.cfo-names .cfo-more a{ color:var(--rf-ink); text-decoration:underline; text-underline-offset:2px }

/* RF-GUIDE-TABLE (27 September 2026): a data table inside a guide article.
   Ruled rows like .cfo-table; it scrolls inside its own box on a phone, so the
   page itself never scrolls sideways. */
.article .gt-wrap{ margin:16px 0 8px; overflow-x:auto; -webkit-overflow-scrolling:touch }
.article .gt{ width:100%; min-width:560px; border-collapse:collapse; font-size:14.5px; line-height:1.4 }
.article .gt caption{ caption-side:bottom; text-align:left; padding-top:8px; font-size:13px; color:var(--rf-ink-3) }
.article .gt th, .article .gt td{ padding:10px 8px; border-bottom:1px solid var(--rf-line); text-align:left; vertical-align:baseline }
.article .gt thead th{ font:500 11px/1.2 var(--rf-mono); letter-spacing:.08em; text-transform:uppercase; color:var(--rf-ink-3); border-bottom:1px solid var(--rf-line-strong) }
.article .gt tbody th{ font-weight:600; color:var(--rf-ink); white-space:nowrap }
.article .gt td{ color:var(--rf-ink-2); font-variant-numeric:tabular-nums }
