/* fuel.css — the Fueling Planner's styles, shared by the app (main webapp/webapp/)
   and the standalone site (fuelplanner/). Every rule is scoped under #fp so the
   planner and the app can't restyle each other. Made by patch_10_split.py from
   fuel 0.9beta's own <style> block, then changed only by the patch_10_* scripts.
   Never edit one copy by hand: copy_10_to_app.py puts this file in the app. */
  /* ---- tokens ----------------------------------------------------------
     First block copied from webapp/index.html. Second block is new, and
     MM_Color_Constants.md proposes moving --select into the app so one edit
     changes both. --------------------------------------------------------- */
  #fp {
    --ink:#12202e; --muted:#5d7183; --line:#dfe6ec; --bg:#f4f7f9; --card:#fff;
    --accent:#003A63; --accent-d:#24486a; --good:#00674E; --warn:#99231f;
    --link:#2f5d86; --focus:#1177D1;

    --select:#7a4bab;
    --meter-under:var(--warn);
    --meter-ok:var(--good);
    --meter-over:#1177D1;
    --meter-soft:#854F0B;     /* potassium: worth a look, not worth a fix */
    --chip-over:var(--warn);

    /* Named so a test can simulate a phone's home-indicator band, which
       env() alone cannot be given a value in a headless browser. */
    --safe-bottom:env(safe-area-inset-bottom, 0px);
    /* How far the ? moves inside its 18px mark. Positive dy is DOWN, positive
       dx is RIGHT. Set by eye on the device the app actually runs on — see
       patch_09_tipmark.py for why this is not a measured number. */
    --qmark-dy:0.5px;
    --qmark-dx:0px;
    --tipbg:rgba(40,40,42,.92);   /* 92% of a true neutral dark grey */
    --tipink:#f4f7f9;             /* the app's own pale blue, softer than white */
    --wrap-max:620px;
    --labelrow:20px;          /* every label row in a sheet is exactly this tall */
    --heavy:#854F0B;          /* the not-mostly-carbs flag */
  }
  #fp, #fp * { box-sizing:border-box; -webkit-tap-highlight-color:transparent; }
  /* ---- guard: the app's own rules that share a class name -------------
     Inside the app, webapp/index.html's .ro, .addbtn and .fld reach these
     elements. `revert` gives back the browser's own value, which is what the
     planner has on its own site. Found and checked by leak_216.js. */
  #fp .ro { font-style:revert; }
  #fp .addbtn { padding:revert; margin:revert; }
  #fp .fld { margin-bottom:revert; }
  /* no double-tap zoom on anything you tap. Pinch zoom stays, for accessibility. */
  #fp button, #fp input, #fp select, #fp textarea, #fp a, #fp .c, #fp .chip, #fp .prow { touch-action:manipulation; }
  /* Clears the fixed meter bar and nothing more. 124px was sized when the bar
     carried a two-line footnote; T7 took that away, and the gap it left is the
     wasted space at the foot of the screen. Measured in Chromium for both the
     four-meter and five-meter bars — layout_07 asserts the clearance. */
  /* A floor only. The real clearance is measured from the bar after every
     render — see fitBar() — because the bar is two rows or three depending on
     whether caffeine is on, and a hand-maintained constant describing a layout
     is how this project lost three builds already. */
  #fp { margin:0; padding:0 0 96px; background:var(--bg); color:var(--ink);
         font:16px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
  #fp button { font:inherit; cursor:pointer; }

  #fp header.top { background:var(--accent); color:#fff; padding:12px 16px; min-height:58px;
               display:flex; align-items:center; gap:12px; }
  #fp header.top .brand { font-size:15px; font-weight:700; letter-spacing:-.2px; }
  #fp header.top .menu { margin-left:auto; width:34px; height:34px; border:0; border-radius:8px;
                     background:rgba(255,255,255,.18); color:#fff; font-size:17px; padding:0; }
  /* The tab strip (2.16beta): the app's dark title strip (.pagetitle in
     webapp/index.html — 11px, 800, uppercase, .1em, white on #2b2b2b, 28px)
     holding the four tabs. The one you're on is white and underlined; the
     others are white at 55%. "DIY:" is a label at 35%, after a thin divider. */
  #fp .ttabs { display:flex; align-items:stretch; height:28px; background:#2b2b2b; padding:0 10px;
               position:sticky; top:0; z-index:6; overflow:hidden; }
  #fp .ttabs .tab { flex:1 1 auto; border:0; background:none; padding:0 6px; margin:0; position:relative;
                    white-space:nowrap; font-size:11px; font-weight:800; letter-spacing:.1em; line-height:28px;
                    text-transform:uppercase; color:rgba(255,255,255,.55); text-align:center; }
  #fp .ttabs .tab.on { color:#fff; }
  #fp .ttabs .tab.on::after { content:""; position:absolute; left:6px; right:6px; bottom:0; height:3px;
                              background:#fff; border-radius:2px 2px 0 0; }
  #fp .ttabs .grp { flex:2 1 auto; display:flex; align-items:stretch; padding-left:8px; margin:6px 0 6px 4px;
                    border-left:1px solid rgba(255,255,255,.22); }
  #fp .ttabs .grp .lab { display:flex; align-items:center; font-size:11px; font-weight:800; letter-spacing:.1em;
                         text-transform:uppercase; color:rgba(255,255,255,.35); padding-right:2px; }
  #fp .ttabs .grp .tab { margin:-6px 0; }

  #fp .wrap { max-width:var(--wrap-max); margin:0 auto; padding:12px 14px 16px; }
  #fp .sect { font-size:12px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
          color:#8a8a85; margin:14px 0 7px; display:flex; align-items:center; gap:8px; }
  #fp .sect:first-child { margin-top:0; }
  #fp .sect .r { margin-left:auto; }
  #fp .sect .kc { margin-left:auto; font-weight:700; letter-spacing:0; text-transform:none;
              font-size:12px; color:var(--muted); }
  /* 8 between things that belong together, 12 between blocks. The card that
     is followed by its own + Add row is the "together" case, so .card carries
     8 and the last element before the next block carries 12. */
  #fp .card { background:var(--card); border:1px solid var(--line); border-radius:12px; padding:11px 12px; margin-bottom:8px; }
  #fp .card.tight { padding:8px 12px; }
  #fp .seg { display:inline-flex; border:1.5px solid var(--select); border-radius:20px; overflow:hidden; }
  /* NOT `font: 700 10.5px/1.3 inherit` — "inherit" is not a valid family
     inside the font shorthand, so the browser drops the whole declaration and
     these render at whatever the ancestor is. Longhand applies. */
  #fp .seg button { border:0; background:#fff; color:var(--select); padding:4px 10px;
                font-weight:700; font-size:10.5px; line-height:1.3;
                letter-spacing:.06em; text-transform:uppercase; }
  #fp .seg button.on { background:var(--select); color:#fff; }
  #fp .seg.sm button { padding:4px 9px; font-size:10px; }

  /* ---- run chips: unit beside the number, widths follow content ---- */
  #fp .rg { font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
        color:#8a8a85; margin:0 0 5px; display:flex; align-items:baseline; }
  #fp .rg.second { margin-top:10px; }
  #fp .sheet .rg { font-size:11px; letter-spacing:.07em; color:var(--muted); margin:0 0 6px; }
  #fp .sheet .rg.second { margin-top:10px; padding-top:8px; border-top:1px solid var(--line); }
  #fp .rowflex { display:flex; gap:6px; }
  #fp .rowflex .c { flex:1 1 auto; }
  #fp .rowflex .c.wide { flex:1.25 1 auto; }
  #fp .c { background:#eef4f8; border:1.5px solid transparent; border-radius:9px; padding:3px 8px 4px;
       min-height:34px; text-align:left; }
  #fp .c .l { display:block; font-size:9.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
          color:var(--muted); line-height:1.2; white-space:nowrap; }
  #fp .c .v { display:block; font-size:15px; font-weight:700; line-height:1.25; white-space:nowrap; color:var(--ink); }
  #fp .c .v u { font-size:11px; font-weight:600; color:var(--muted); text-decoration:none; margin-left:2px; }
  #fp .c.saved { background:#f6f1fb; border-color:var(--select); }
  #fp .c.saved .l { color:var(--select); }
  #fp .c.ro { background:#fff; border:1.5px dashed #c2ccd4; }
  /* Run Details, variant C. The label keeps the full width, so a long one does
     not squeeze the mark; the mark sits with the number it belongs to, at 20px
     rather than the 12px it would get inside the label line; and the chip is
     tinted to the mark, which is what stops four blue chips reading as one. */
  #fp .c.ci { padding:4px 8px 5px; }
  #fp .c.ci .btm { display:flex; align-items:center; gap:6px; margin-top:1px; }
  #fp .c.ci .ico { flex:0 0 20px; width:20px; height:20px; }
  #fp .c.k-time { background:#eef2f6; }   #fp .c.k-temp { background:#faf0ea; }
  #fp .c.k-bottle { background:#eaf4f6; } #fp .c.k-weight { background:#f3eff8; }
  #fp .ico.tone-time { color:#3d5a73; }   #fp .ico.tone-temp { color:#a8562f; }
  #fp .ico.tone-bottle { color:#2e7d8f; } #fp .ico.tone-weight { color:#6b5b8f; }
  #fp .cap { display:flex; gap:6px; margin-top:4px; }
  #fp .cap > div { position:relative; padding-top:9px; text-align:center; font-size:11px; line-height:1.3;
               font-weight:600; color:var(--muted); }
  #fp .cap > div::before { content:""; position:absolute; left:4px; right:4px; top:0; height:6px;
                       border:1.5px solid #b5c3cf; border-top:0; border-radius:0 0 6px 6px; }
  #fp .cap .s { flex:1 1 auto; color:var(--select); } #fp .cap .s::before { border-color:var(--select); }
  #fp .cap .h { flex:3.75 1 auto; }
  #fp .rnote { font-size:12px; line-height:1.5; color:var(--muted); margin-top:8px; }
  #fp .rnote div + div { margin-top:2px; }
  #fp a.lnk, #fp .lnkbtn { color:var(--link); font-weight:600; text-decoration:none; background:none;
                   border:0; padding:0; font-size:inherit; }

  /* ---- products ---- */
  #fp .chips { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:8px; }
  #fp .chip { font-size:12px; font-weight:700; padding:5px 10px; border-radius:20px;
          border:1.5px solid var(--line); background:#fff; color:var(--muted); }
  #fp .chip.on { background:var(--accent); border-color:var(--accent); color:#fff; }
  #fp .chip.mine { color:var(--select); border-color:#d9c8ea; }
  #fp .chip.mine.on { background:var(--select); border-color:var(--select); color:#fff; }
  #fp .prow { display:flex; align-items:center; gap:10px; padding:7px 0; border-top:1px solid var(--line); }
  #fp .prow.first { border-top:0; padding-top:0; }
  #fp .prow:last-child { padding-bottom:0; }
  #fp .prow .pb { flex:1; min-width:0; }
  #fp .prow .pt { font-size:14.5px; font-weight:700; line-height:1.25; }
  #fp .prow .pd { font-size:12px; color:var(--muted); line-height:1.35; }
  /* The category word used to be the first thing on every product line. A 16px
     mono mark in a 20px gutter says the same thing without spending a phrase,
     and the eye can sort a list by it without reading. Muted, not tinted —
     the row already has a title, a tag and a number fighting for attention. */
  #fp .prow .cat { flex:0 0 20px; display:flex; justify-content:center; padding-top:1px; color:var(--muted); }
  #fp .prow .cat svg { display:block; width:16px; height:16px; }
  #fp .c .ico, #fp .waternote .ic { display:block; }
  #fp .own { display:inline-block; white-space:nowrap; font-size:9.5px; font-weight:800; letter-spacing:.06em;
         text-transform:uppercase; color:var(--select); border:1px solid var(--select); border-radius:20px;
         padding:0 6px; margin-left:5px; }
  /* a second tap adds another, so the count has to be impossible to miss */
  @keyframes bump { 0%{transform:scale(1)} 30%{transform:scale(1.28)} 100%{transform:scale(1)} }
  #fp .own.inplan.flash { animation:bump .34s ease-out; background:var(--good); color:#fff; }
  #fp .heavy { display:block; font-size:11.5px; font-weight:600; color:var(--heavy); line-height:1.35; }
  #fp .inplan { color:var(--good); border-color:var(--good); }
  #fp .est { color:var(--muted); border-color:#c2ccd4; }
  #fp .stp { display:flex; align-items:center; border:1.5px solid var(--line); border-radius:10px;
         overflow:hidden; flex:0 0 auto; background:#fff; }
  #fp .stp button { width:36px; height:36px; border:0; background:#fff; color:var(--accent); font-size:18px; font-weight:700; padding:0; }
  #fp .stp .n { width:32px; text-align:center; font-size:15px; border-left:1px solid var(--line);
            border-right:1px solid var(--line); line-height:36px; }
  #fp .addrow { display:flex; gap:8px; margin-bottom:8px; }
  #fp .addbtn { flex:1 1 0; min-height:44px; border-radius:10px; font-size:14px; font-weight:700; background:#fff; }
  #fp .addbtn.main { border:1.5px solid var(--accent); color:var(--accent); }
  #fp .addbtn.water { border:1.5px solid #7fa8c9; color:#1d5c86; }
  #fp .clear { display:block; width:100%; border:0; background:none; text-align:center; font-size:12.5px;
           color:var(--muted); margin-bottom:12px; text-decoration:underline; padding:4px; }
  /* Option D from the mockups: said once, directly above the button that fixes
     it, so the instruction and the fix are one glance. The mockup used a water
     emoji for the visual weight; the app has an icon set now and uses no emoji
     anywhere, so the bottle mark carries it instead. */
  #fp .waternote { display:flex; gap:9px; align-items:flex-start; background:#e7effa; border:1.5px solid #b9cde3;
               border-radius:10px; padding:9px 11px; margin-bottom:8px; font-size:13px;
               line-height:1.45; color:#0b2c49; }
  #fp .waternote b { font-weight:700; }
  #fp .waternote .ic { flex:0 0 17px; width:17px; height:17px; margin-top:1px; color:#2e7d8f; }
  #fp .plus { border:1.5px solid var(--accent); color:var(--accent); background:#fff; border-radius:8px;
          padding:7px 12px; font-size:13px; font-weight:700; min-width:58px; }
  /* "+ Another" was 74px of button for one idea. Once the − exists, −1 / +1 is
     the same instruction in a third of the width, and the pair is symmetrical. */
  /* Josh, v0.5beta #1: "They vary in height too - and shouldn't." The minus
     carried font-size:15px and the plus did not, so the taller line box made
     it a taller button. One shared rule, at the +1 size, no override. */
  #fp .plus.in, #fp .plus.minus { min-width:44px; width:44px; padding:7px 0; }
  #fp .plus.in { border-color:var(--good); color:var(--good); }
  #fp .grp { font-size:11px; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
         color:var(--accent); margin:10px 0 2px; }
  #fp .empty { font-size:14px; color:var(--muted); padding:3px 0 4px; }

  /* ---- meters: option A, two by two, nothing wraps ---- */
  #fp .m .row { display:flex; align-items:center; gap:5px; font-size:12px; white-space:nowrap; }
  #fp .m .row b { font-weight:700; }
  #fp .m .row .v { margin-left:auto; }
  #fp .m .row .v small { color:var(--muted); font-size:11px; }
  #fp .st { font-size:8.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
        padding:1px 5px; border-radius:20px; color:#fff; line-height:13px; }
  #fp .st.under { background:var(--meter-under); } #fp .st.ok { background:var(--meter-ok); } #fp .st.over { background:var(--chip-over); }
  #fp .trk { position:relative; height:7px; border-radius:6px; background:#e7edf2; margin-top:3px; overflow:hidden; }
  /* left and width come from the meter's own tolerance now — see meter() */
  #fp .trk .band { position:absolute; top:0; bottom:0; background:rgba(0,103,78,.15); }
  #fp .trk .tgt { position:absolute; top:0; bottom:0; left:76.9%; width:2px; background:var(--ink); opacity:.45; }
  #fp .trk .fill { position:absolute; left:0; top:0; bottom:0; border-radius:6px; }
  #fp .fill.under { background:var(--meter-under); } #fp .fill.ok { background:var(--meter-ok); }
  #fp .fill.over { background:var(--meter-over); } #fp .fill.soft { background:var(--meter-soft); }
  #fp .mbar { position:fixed; left:0; right:0; bottom:0; z-index:7; background:#fff;
          border-top:1px solid var(--line); box-shadow:0 -4px 14px rgba(0,0,0,.06);
          padding:8px 14px calc(10px + var(--safe-bottom)); }
  /* ---- the preview state -----------------------------------------------
     A DIY draft in the meters is not the plan. The tint says provisional, the
     label says what it is, and the ON/UNDER chips go quiet — those chips were
     the actual lie, because a green ON is a claim that the plan is covered.

     THE LABEL COSTS NOTHING IN HEIGHT. It is paid for out of the bar's own
     bottom padding, which on a phone is mostly the home-indicator band sitting
     empty below the meters. --safe-bottom is 34px on Josh's phone, so the bar
     measures the same with the label as without it; on a device with no safe
     area there is nothing to reclaim and it grows by the floor instead. */
  #fp .mbar.preview { background:#f8f5ee; border-top-color:#e6dcc8;
                  padding-bottom:max(6px, calc(10px + var(--safe-bottom) - 14px)); }
  #fp .mbar.preview .st { background:transparent; color:var(--muted);
                      border:1px solid #c2ccd4; line-height:11px; }
  #fp .mbar .pvlabel { max-width:var(--wrap-max); margin:3px auto 0;
                   font-weight:700; font-size:9.5px; line-height:1.15;
                   letter-spacing:.07em; text-transform:uppercase; color:#7a6a4e; }
  #fp .mbar .inner { max-width:var(--wrap-max); margin:0 auto; display:grid;
                 grid-template-columns:1fr 1fr; gap:6px 14px; }
  #fp .mbar .full { grid-column:1 / -1; }

  /* ---- one what-to-do block ---- */
  #fp .todo { background:#e6f1f9; border:1.5px solid #006ebb; border-radius:10px; padding:10px 12px; margin-bottom:11px; }
  #fp .todo .hd { font-size:12px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:#00548d; margin-bottom:6px; }
  #fp .todo ul { margin:0; padding-left:18px; font-size:14px; line-height:1.45; }
  #fp .todo li { margin:3px 0; }
  #fp .todo .adv { font-size:13px; line-height:1.45; margin-top:9px; padding-top:8px;
               border-top:1px solid #bcd6e8; color:#0c3d5c; }
  #fp .todo .foot { font-size:12px; color:#00548d; margin-top:7px; }
  /* a question, so navy title, but a heavier outline because it is asking you to look */
  #fp .qcard { background:#fff; border:2px solid var(--warn); border-radius:10px; padding:12px 14px;
           margin:0 0 11px; box-shadow:0 2px 10px rgba(153,35,31,.14); }
  #fp .qcard .qt { font-size:15px; font-weight:800; color:var(--warn); margin-bottom:4px; }
  #fp .qcard .qb { font-size:13.5px; line-height:1.45; }
  #fp .qcard .qnote { font-size:12px; line-height:1.4; color:var(--muted); margin-top:5px; }
  #fp .qbtns { display:flex; gap:8px; margin-top:9px; }
  #fp .qbtn { flex:1 1 0; min-width:0; border-radius:8px; padding:9px 4px; font-size:14px; font-weight:600; }
  #fp .qbtn.go { background:var(--accent); color:#fff; border:1.5px solid var(--accent); }
  #fp .qbtn.no { background:#fff; color:var(--accent); border:1.5px solid var(--accent); }

  /* ---- sheets ---- */
  #fp .scrim { position:fixed; inset:0; z-index:60; background:rgba(8,20,32,.45); }
  #fp .sheet { position:fixed; left:0; right:0; bottom:0; z-index:61; background:#fff;
           border-radius:18px 18px 0 0; max-height:90%; overflow-y:auto;
           padding:0 12px calc(12px + env(safe-area-inset-bottom));
           box-shadow:0 -8px 24px rgba(0,0,0,.18); touch-action:pan-y; }
  #fp .sheet .in { max-width:var(--wrap-max); margin:0 auto; }
  #fp .grabrow { padding:6px 0 2px; position:sticky; top:0; z-index:3; background:#fff; }
  #fp .grab { width:44px; height:5px; border-radius:3px; background:#c9d3db; margin:0 auto; }
  #fp .sh { display:flex; align-items:center; font-size:17px; font-weight:800; margin:1px 0 9px; }
  #fp .sh .x { margin-left:auto; border:1.5px solid var(--line); background:#fff; border-radius:9px;
           width:30px; height:30px; font-size:17px; color:var(--muted); padding:0; line-height:1;
           display:flex; align-items:center; justify-content:center; flex:0 0 30px; }
  #fp .g2 { display:grid; grid-template-columns:1fr 1fr; gap:7px 9px; align-items:start; }
  /* Josh, v0.6beta #12: the ratio chooser reads as crowding the concentration
     field beside it. The boxes were not the problem — the column gap was. */
  #fp .g2.airy { column-gap:16px; }
  #fp .span { grid-column:1 / -1; }
  /* THE alignment fix: a label row is this tall whether or not it holds a switch,
     so two fields side by side always start their inputs at the same y. */
  #fp .fld .name { display:flex; align-items:center; gap:8px; height:var(--labelrow); overflow:hidden;
               font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
               color:var(--muted); margin-bottom:2px; }
  #fp .fld .name .ut { margin-left:auto; }
  #fp input[type=text], #fp input[type=number], #fp select, #fp textarea {
    width:100%; font:inherit; color:var(--ink); padding:5px 10px; border:1.5px solid var(--line);
    border-radius:9px; background:#fff; appearance:none; }
  #fp input[type=number]::-webkit-outer-spin-button, #fp input[type=number]::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }
  #fp input[type=number] { -moz-appearance:textfield; }
  #fp input:focus, #fp select:focus, #fp textarea:focus { outline:none; border-color:var(--focus); box-shadow:0 0 0 3px rgba(16,57,94,.20); }
  #fp .fld.saved input { border-color:var(--select); background:#f6f1fb; }
  /* the field the app changed, not the one you typed in */
  @keyframes fieldflash {
    0%, 70% { box-shadow:0 0 0 3px rgba(17,119,209,.30); border-color:var(--focus); }
    100%    { box-shadow:0 0 0 3px rgba(17,119,209,0); }
  }
  #fp .fld.flash input { animation:fieldflash 1.8s ease-out 1; }
  #fp .fld .hint { font-size:11.5px; line-height:1.35; color:var(--select); margin-top:4px; }
  #fp .fld .adj { font-size:11.5px; line-height:1.35; color:var(--muted); margin-top:4px; }
  /* unit switches: a real target, not a link */
  #fp .ut { display:inline-flex; margin-left:auto; flex:0 0 auto; height:19px;
        border:1px solid var(--line); border-radius:20px; overflow:hidden; }
  #fp .ut button { border:0; background:#fff; color:var(--muted);
               font-weight:700; font-size:11px; line-height:1;
               padding:0 7px; display:flex; align-items:center; justify-content:center; }
  #fp .ut button.on { background:var(--accent); color:#fff; }
  /* the degree glyph rides high, which reads as space underneath. Temp switch only. */
  #fp .ut.deg button { padding-top:1px; }
  #fp .hm { display:flex; gap:1px; align-items:flex-start; }
  #fp .hm input { text-align:center; }
  #fp .hmsep { flex:0 0 8px; text-align:center; color:var(--muted); font-size:17px; line-height:38px; }
  #fp .segs { display:flex; border:1.5px solid var(--line); border-radius:9px; overflow:hidden; }
  #fp .segs button { flex:1 1 0; border:0; background:#fff; color:var(--muted); font-size:13px; font-weight:600; padding:8px 2px; }
  #fp .segs button.on { background:var(--accent); color:#fff; }
  /* A two-way picker separates itself: one half is always filled. A three-way
     only does that when the MIDDLE option is active, so it gets a divider —
     suppressed either side of the filled block, because the fill is already
     doing that job there. Inset rather than full height: a line touching both
     edges reads as a wall between two controls, and this is one control.
     #b9c7d3 rather than --line, which is the control's own border colour and
     therefore invisible inside it. */
  #fp .segs > button { position:relative; }
  #fp .segs > button:first-child:nth-last-child(3) ~ button::before {
        content:""; position:absolute; left:0; top:22%; bottom:22%; width:1px; background:#b9c7d3; }
  /* :not(:only-child) is not decoration — it lifts this to the same specificity
     as the rule above, which carries three pseudo-classes. Without it the
     divider was drawn on both sides of the selected option and the suppression
     never applied at all. */
  #fp .segs > button.on:not(:only-child)::before,
  #fp .segs > button.on:not(:only-child) + button::before { background:transparent; }
  #fp .segs.sm { display:inline-flex; }
  #fp .segs.sm button { flex:0 0 auto; padding:6px 14px; font-size:12.5px; }
  #fp .ro { font-size:12.5px; color:var(--muted); margin-top:10px; padding-top:9px; border-top:1px solid var(--line); }
  #fp .ro b { color:var(--ink); font-weight:600; }
  #fp .done { display:block; width:72%; margin:11px auto 0; border:0; border-radius:10px;
          background:var(--accent); color:#fff; font-weight:800; font-size:16px; padding:12px; }
  #fp .openadv { width:100%; display:flex; align-items:center; gap:8px; margin-top:8px; padding:11px 12px;
             border:1.5px solid var(--select); border-radius:10px; background:#fcfaff;
             color:var(--select); font-size:14px; font-weight:700; }
  #fp .openadv span { margin-left:auto; font-size:12px; font-weight:600; }
  #fp .helper { border:1.5px solid var(--select); border-radius:10px; padding:8px 9px 9px;
            margin-top:10px; margin-bottom:12px; background:#fcfaff; }
  #fp .helper .hh { font-size:12px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--select); margin-bottom:8px; }
  #fp .helper .out { margin-top:10px; font-size:13px; background:#fff; border:1px solid var(--line); border-radius:9px; padding:8px 10px; }
  /* The empty state is a PROMPT, not an output. .out is white-filled with a 9px
     radius and a --line border, which is the recipe for a text input — so an
     instruction wearing it reads as a field waiting to be typed in. */
  #fp .helper .prompt { margin-top:9px; font-size:12.5px; line-height:1.45; color:var(--select); font-weight:600; }
  #fp .helper .fnote { margin-top:7px; }
  #fp .helper .keep { margin-top:9px; padding-top:8px; border-top:1px solid #e6dcf2;
                  font-size:11.5px; line-height:1.45; color:var(--muted); }
  #fp .usebtn { width:100%; margin-top:8px; border:0; border-radius:9px; background:var(--accent); color:#fff; font-weight:700; font-size:14px; padding:10px; }
  #fp .search { margin-bottom:8px; }
  #fp .custlink { width:100%; display:flex; align-items:center; gap:8px; margin-top:10px; padding:11px 12px;
              border:1.5px dashed #c2ccd4; border-radius:10px; background:#fff; font-size:14px; font-weight:700; color:var(--accent); }
  #fp .custlink span { margin-left:auto; }
  /* Josh, v0.6beta #3: a line of text with two links in it, not a second
     button. The .lnkbtn children carry their own tap targets; the block does
     not, because it is a sentence. */
  #fp .mixlink { border:1.5px dashed #c2ccd4; border-radius:10px; background:#fff; padding:11px 12px;
             margin-top:10px; font-size:13.5px; line-height:1.5; color:var(--ink); }
  #fp .mixlink .lnkbtn { text-decoration:underline; text-underline-offset:2px; }
  #fp .fnote { font-size:12px; color:var(--muted); margin-top:10px; line-height:1.4; }
  #fp .disc { font-size:11.5px; color:var(--muted); line-height:1.45; margin-top:10px;
          padding-top:9px; border-top:1px solid var(--line); }
  #fp .mnote { grid-column:1 / -1; font-size:11px; color:var(--muted); margin-top:1px; }
  /* ---- tooltips -------------------------------------------------------
     A ? earns its place when it explains a number you cannot derive from the
     screen, defines a word that is not plain English, or states a rule the app
     applies invisibly. Anything you do at the counter belongs in the practical
     notes instead. The mark is 16px so it fits inside --labelrow's 20px; the
     ::after is the tap target, drawn separately rather than being whatever the
     glyph happens to be. */
  /* The ? inside the mark, nudged. Flex centres the line box, which reserves
     descender room the ? does not use, so the ink reads high; and centring
     aligns the advance width, not the ink, so uneven side bearings read off to
     one side. Both are font-specific — measured as centred under DejaVu in the
     build container, visibly high under SF Pro on a Mac — so these are tokens
     to be set by eye once, not measured constants. The padding is DOUBLE the
     intended shift: on a border-box element pinned to 18px it steals from one
     edge and the centred glyph moves half that far. Do not "fix" this with
     line-height; that moves the box, not the ink. */
  #fp .q { position:relative; flex:0 0 auto; width:18px; height:18px; margin-left:6px;
       border:1.2px solid var(--muted); border-radius:50%; background:#fff;
       color:var(--muted); font-weight:800; font-size:10.5px; line-height:1;
       padding:calc(var(--qmark-dy) * 2) 0 0 calc(var(--qmark-dx) * 2);
       display:inline-flex; align-items:center; justify-content:center; vertical-align:-4px; }
  #fp .q::after { content:""; position:absolute; left:50%; top:50%; width:40px; height:40px;
              transform:translate(-50%,-50%); }
  /* A label row is 20px with overflow:hidden, by design — that pin is what keeps
     two fields side by side starting their inputs at the same y. A 40px target
     inside it is clipped, and a clipped region takes no taps either, so it was
     never reachable there. The mark itself is the target in a label row; every
     other mark on the screen keeps the full 40. */
  #fp .fld .name .q::after { content:none; }
  #fp .q.on { background:var(--accent); border-color:var(--accent); color:#fff; }
  /* The bubble floats over the page rather than sitting in it: opening one
     used to push everything below it down, which is the one thing a tooltip
     must not do. Positioned in JS from the mark's own box — see placeTip. */
  #fp #tipover { position:fixed; z-index:200; }
  #fp #tipover .tipbody { background:var(--tipbg); color:var(--tipink); border-radius:10px;
                      padding:10px 12px; font-size:12.5px; line-height:1.45;
                      font-weight:400; letter-spacing:0; text-transform:none;
                      box-shadow:0 6px 20px rgba(0,0,0,.28); }
  #fp #tipover .tiparrow { position:absolute; width:0; height:0;
                       border-left:7px solid transparent; border-right:7px solid transparent; }
  #fp #tipover.below .tiparrow { top:-6px; border-bottom:6px solid var(--tipbg); }
  #fp #tipover.above .tiparrow { bottom:-6px; border-top:6px solid var(--tipbg); }
  /* ⓘ opens the one how-it-works sheet; ? is always inline and always one
     idea. They never swap roles, so the two marks never mean the same thing. */
  #fp header.top .ihelp { margin-left:auto; width:34px; height:34px; border:0; border-radius:8px;
                      background:rgba(255,255,255,.18); color:#fff; font-size:16px; font-weight:700; padding:0; }
  #fp header.top .ihelp + .menu { margin-left:8px; }
  #fp .hs h4 { font-size:14px; font-weight:800; margin:14px 0 4px; }
  #fp .hs h4:first-child { margin-top:0; }
  #fp .hs p { font-size:13.5px; line-height:1.5; margin:0; color:var(--ink); }
  #fp .verline { text-align:center; font-size:11px; color:#8b9aa8; padding:12px 0 6px; }
  #fp .verline button { border:0; background:none; color:inherit; font-size:inherit; text-decoration:underline; }
  #fp .errline { max-width:var(--wrap-max); margin:10px auto; padding:10px 12px; border-radius:8px;
             background:#fcebeb; color:#791f1f; font-size:12px; }
  /* ---- DIY screens ---------------------------------------------------- */
  /* Josh, v0.6beta #23: the 8/12 normalisation was right everywhere except
     here, where a card inside a card carries two lots of vertical padding.
     About 40% off the top and bottom; the sides are untouched. */
  #fp .pk { display:block; width:100%; text-align:left; border:1.5px solid var(--line); background:#fff;
        border-radius:10px; padding:5px 10px; margin-bottom:6px; }
  #fp .pk:last-child { margin-bottom:0; }
  #fp .pk.on { border-color:var(--accent); background:#f2f7fb; }
  #fp .pk .pkt { font-size:14px; font-weight:700; color:var(--ink); }
  #fp .pk.on .pkt { color:var(--accent); }
  #fp .pk .pkm { font-size:11.5px; color:var(--muted); line-height:1.35; margin-top:1px; }
  #fp .rec { background:#e7effa; border:1.5px solid #b9cde3; border-radius:10px; padding:10px 12px; margin-bottom:11px; }
  #fp .rec .rh { display:flex; align-items:baseline; font-size:12px; font-weight:800; letter-spacing:.06em;
             text-transform:uppercase; color:#0b2c49; margin-bottom:7px; }
  #fp .rec .rh span { margin-left:auto; font-weight:700; letter-spacing:0; text-transform:none; font-size:12px; color:#2c5578; }
  #fp .ir { display:flex; align-items:baseline; font-size:14px; padding:4px 0; border-top:1px solid #cfe0ee; color:#12202e; }
  #fp .ir.first { border-top:0; }
  #fp .ir b { margin-left:auto; font-weight:700; font-variant-numeric:tabular-nums; }
  #fp .ir .u { font-size:11px; color:#2c5578; font-weight:600; margin-left:3px; }
  #fp .rsum { margin-top:8px; padding-top:8px; border-top:1px solid #cfe0ee; font-size:12.5px;
          line-height:1.5; color:#0c3d5c; }
  #fp .rsum b { font-weight:700; }
  #fp .warnline { font-size:12.5px; font-weight:600; color:var(--heavy); line-height:1.4; margin-top:7px; }
  #fp .credit { text-align:center; font-size:11.5px; color:var(--muted); line-height:1.5; padding:16px 4px 0; }
  #fp .namerow { display:flex; gap:8px; align-items:flex-end; }
  #fp .namerow .fld { flex:1; }
  #fp .savebtn { border:0; border-radius:10px; background:var(--accent); color:#fff; font-weight:800;
             font-size:15px; padding:12px 16px; white-space:nowrap; }
  #fp .savebtn[disabled] { background:#b7c4cf; }
  #fp .gnote { font-size:12px; color:var(--muted); line-height:1.45; margin-top:8px; }
  #fp .gnote b { color:var(--ink); font-weight:600; }
  /* Option C. A was a green title and no tag; Josh: "Green chip is good
     enough, just like the purple chip for my products." So the title stays ink
     like every other product and the tag does the work, which also makes MIX
     and MY PRODUCTS read as the same kind of mark. */
  #fp .own.mixtag { color:var(--good); border-color:var(--good); }
  #fp .chip.mix { color:var(--good); border-color:#a8cfc2; }
  #fp .chip.mix.on { background:var(--good); border-color:var(--good); color:#fff; }
  #fp .soon-card { background:#fff; border:1px solid var(--line); border-radius:12px; padding:16px; font-size:14px; line-height:1.5; }

  /* ---- compact meter, inside a sheet ----------------------------------
     The real .mbar is position:fixed at z-index 7 and the scrim is 60, so in
     picker mode the meters are UNDERNEATH the sheet, not hidden by it. No
     amount of styling rescues that — a sheet needs its own. Sticky rather
     than fixed, so it pins to the bottom of the sheet's scrollport while the
     product list scrolls behind it. Layout v5, option B. */
  #fp .pm { position:sticky; bottom:0; z-index:4; background:#fff; margin:0 -12px;
        padding:7px 12px calc(10px + env(safe-area-inset-bottom));
        border-top:1px solid var(--line); box-shadow:0 -4px 12px rgba(0,0,0,.07); }
  /* Sticky bottom:0 pins to the bottom of the CONTENT box, so the sheet's own
     12px bottom padding left a strip of background under the meter. The sheet
     gives that padding up and .pm supplies it, safe-area included. Found by
     measuring in Chromium; jsdom does no layout and could never see it. */
  #fp .sheet.haspm { padding-bottom:0; }
  #fp .pm .pmr { display:flex; gap:9px; }
  #fp .pm .pmc { flex:1 1 0; min-width:0; }
  #fp .pm .pml { display:flex; align-items:baseline; gap:4px; font-size:11px; line-height:1.2; white-space:nowrap; }
  #fp .pm .pml b { font-weight:800; letter-spacing:-.1px; }
  #fp .pm .pml span { margin-left:auto; font-weight:700; font-variant-numeric:tabular-nums; }
  #fp .pm .trk { margin-top:3px; height:5px; }

  /* ---- saved plans (2.16beta, item 1) --------------------------------- */
  #fp .planline { display:flex; align-items:baseline; gap:6px; flex-wrap:wrap; font-size:13px;
                  color:var(--muted); margin:0 0 9px; }
  #fp .planline b { color:var(--ink); font-size:14.5px; }
  #fp .own.dirty { color:var(--heavy); border-color:var(--heavy); }
  #fp .own.clean { color:var(--good); border-color:var(--good); }
  #fp .saverow { display:flex; gap:8px; margin-bottom:8px; }
  #fp .psave { flex:1 1 0; min-height:44px; border-radius:10px; font-size:14px; font-weight:700;
               background:var(--accent); color:#fff; border:1.5px solid var(--accent); }
  #fp .psave.alt { background:#fff; color:var(--accent); }
  #fp .psave:disabled { background:#eef2f6; border-color:#dfe6ec; color:#9aa9b6; }
  #fp .done:disabled { background:#b7c4cf; }
  #fp .plrow { display:flex; align-items:center; gap:10px; padding:9px 0; border-top:1px solid var(--line); cursor:pointer; }
  #fp .plrow.first { border-top:0; padding-top:2px; }
  #fp .plrow .pb { flex:1; min-width:0; }
  #fp .plrow .pt { font-size:14.5px; font-weight:700; line-height:1.25; }
  #fp .plrow .pd { font-size:12px; color:var(--muted); line-height:1.35; }
  #fp .dots { flex:0 0 36px; width:36px; height:36px; display:flex; align-items:center; justify-content:center;
              gap:3.5px; padding:0; border:1.5px solid var(--line); border-radius:10px; background:#fff;
              color:var(--muted); font-size:16px; }
  #fp .dots i { display:block; width:4px; height:4px; border-radius:50%; background:currentColor; }
  #fp .rowacts { display:flex; gap:8px; padding:0 0 10px; }
  #fp .rowacts button { flex:1 1 0; border-radius:8px; padding:8px 4px; font-size:13.5px; font-weight:700;
                        background:#fff; border:1.5px solid var(--accent); color:var(--accent); }
  #fp .rowacts button.del { border-color:var(--warn); color:var(--warn); }
  #fp .delconf { background:#fdf3f2; border:1.5px solid var(--warn); border-radius:10px; padding:9px 11px; margin:0 0 10px; }
  #fp .delconf .t { font-size:13.5px; font-weight:700; color:var(--warn); margin-bottom:7px; }
  #fp .delconf .b { font-size:12.5px; color:#6b3a36; margin:-3px 0 8px; }
  #fp .delconf .qbtns { margin-top:0; }
  #fp .qbtn.red { background:var(--warn); border:1.5px solid var(--warn); color:#fff; }
  #fp .custlink.first { margin:0 0 10px; }
  #fp .leftrow { border-color:#e2cfa6; background:#fbf6ec; }
  #fp .leftrow .pt { color:#6b4f12; }
  #fp .leftrow .dots { color:#8a6d2f; }
  #fp .leftcard { background:#f1f4f7; border:1.5px solid #c9d3db; border-radius:10px; padding:10px 12px; margin-bottom:11px; }
  #fp .leftcard .t { font-size:14px; font-weight:800; color:#3d5a73; }
  #fp .leftcard .b { font-size:12.5px; color:var(--muted); margin-top:2px; }
  #fp .openadv.arch { border-color:var(--accent); color:var(--accent); background:#fff; margin-top:10px; }
  #fp .capnote { font-size:12px; color:var(--muted); margin-top:10px; text-align:center; }
  #fp .lnkbtn.back { display:block; margin:0 0 8px; font-size:14px; }
  #fp .dup { font-size:11.5px; line-height:1.35; color:var(--warn); margin-top:4px; font-weight:600; }
  #fp .lnkbtn.sug { display:block; margin-top:3px; font-size:12.5px; text-decoration:underline; text-underline-offset:2px; }
  #fp .rocount { flex:0 0 auto; font-size:14px; font-weight:700; color:var(--muted); padding:0 6px; }
  /* The message strip: the app's .msg (webapp/index.html), so a save says it in
     the same voice in both places. */
  #fp .fpmsg { text-align:center; font-size:15px; font-weight:800; padding:2px 12px 9px; }
  #fp .fpmsg.ok { color:var(--good); }
  #fp .fpmsg.err { color:var(--warn); }
  #fp .fpmsg .sub { font-size:13px; font-weight:500; color:var(--ink); margin-top:4px; line-height:1.45; }
  #fp .fpwait { font-size:12.5px; line-height:1.45; color:#6b4f12; background:#fbf6ec; border:1px solid #e2cfa6;
                border-radius:8px; padding:7px 10px; margin-bottom:10px; text-align:center; }

  /* ---- products and mixes as rows (2.16beta, item 2) ------------------- */
  #fp .goneline { font-size:11.5px; line-height:1.35; color:var(--muted); font-style:italic; }
  #fp .usednote { color:var(--heavy); font-weight:600; }
