/* PackStoke design system — ported to match the original site (static/pack-planner.html)
   exactly: paper/moss/ochre palette, serif body + sans numerals, folder tabs, small
   radii, dark "readout" summary panel.

   THEMES — the original's seven, verbatim tokens. Paper is the default (no attribute,
   no OS-following: the old site defaults to paper and the picker is the only switch).
   The three dark schemes share the [data-dark] family block, with Midnight and Smokey
   re-pointing surfaces on top — same layering as the original. Extra tokens the old
   site handled with per-theme component rules: --rink/--rpaper (the readout is always
   a dark panel; each theme tints it with its own ink), --hairline (row separators),
   --soft (toolbar strips), --held (the on-hold row wash). */
:root{
  --ink:#16201d; --moss:#3d5a4a; --moss-soft:#e3ebe4;
  --ochre:#99681a; --paper:#f2efe7; --card:#fbfaf6;
  --rule:#d5d0c2; --dim:#656d68; --over:#a3402c; --good:#4a7a5c;
  --tab-idle:#eceadf; --row-on:#f6f8f4;
  --rink:#16201d; --rpaper:#f2efe7;
  --hairline:#ece8dd; --soft:#faf8f1; --held:#fdf4d0;
  --field:#fff;               /* face of an input or styled select on paper */
  /* Hover wash — ONE definition for every secondary control: menu items, tabs,
     styled selects, steppers, pickers. Never re-state the colour at a rule;
     reference these. `var(--moss-soft)` rather than its value so the per-theme
     blocks below keep resolving without a second set of hover overrides.
     --ro-hover is the same idea on the always-dark readout panel.
     --hover-solid is the ONLY heavy fill: the primary button, and nothing else —
     it used to leak onto every bare <button>, which is what made the styled
     selects slam to dark green on hover. */
  --hover:var(--moss-soft); --hover-ink:var(--moss); --hover-solid:#334c3e;
  /* the one destructive button. --over is dark on paper and LIGHT in every
     dark theme, so its ink has to flip with it rather than stay white. */
  --danger-ink:#fff; --danger-hover:#8a3524;
  --well:#f7f5ee;             /* add-box / picker wells: a shade off the card */
  --mute-ink:#b9bdb6;         /* the quietest text: empty states, remove x, units */
  --seg-base:#7fa07f; --seg-food:#d9c26a;   /* weight bar + legend segments */
  /* The readout is a dark instrument panel in EVERY theme, so its own palette is
     defined once here and is not overridden per theme — only --rink/--rpaper are.
     --ro-line doubles as the raised field colour inside it, as in the original. */
  --ro-line:#2b3733; --ro-edge:#46554e; --ro-edge-hover:#6a7d74; --ro-hover:#37463f;
  --ro-text:#c5d0c8; --ro-dim:#a9b8ae; --ro-mute:#8ea394; --ro-dot:#5d6f64;
  --ro-active:#f0e7c8; --ro-ok:#a9c9b4; --ro-accent:#8fbfa0;
  --ro-field-ink:#f2efe7; --ro-nudge:#e6ddc4;
  --ro-gold:#f7e3ad; --ro-pale:#cfe0d4;    /* hero: the total, and its labels */
}
/* "Sepia": a warmer, softer paper */
:root[data-theme="sepia"]{
  --paper:#efe6d6; --card:#faf4e8; --ink:#3b3026; --dim:#726452;
  --rule:#ddcfb6; --moss:#5b6d4a; --moss-soft:#e6e7d3; --ochre:#9d6019;
  --good:#5a7648; --over:#a3402c;
  --rink:#3b3026; --rpaper:#efe6d6;
}
/* "Ranger": routed trailhead sign, shield green, badge gold */
:root[data-theme="ranger"]{
  --paper:#e9e3d3; --card:#f7f3e9; --ink:#2f2a21; --dim:#6a6353;
  --rule:#cfc6ae; --moss:#2f4a34; --moss-soft:#dfe4d7; --ochre:#876821;
  --good:#3f6b45; --over:#8f3d26;
  --rink:#2f2a21; --rpaper:#e9e3d3;
}
/* "Gandalf": Gandalf the GREY — weathered cloak, one warm ember accent */
:root[data-theme="gandalf"]{
  --paper:#e4e4e2; --card:#f2f2f0; --ink:#2b2d2e; --dim:#616567;
  --rule:#c6c7c5; --moss:#4a545c; --moss-soft:#d8dadb; --ochre:#9a5f1c;
  --good:#4e6f5c; --over:#9a4128;
  --rink:#2b2d2e; --rpaper:#e4e4e2;
}
/* the dark family — "Forest" is this block as-is */
:root[data-dark]{
  --paper:#0f1712; --card:#182420; --ink:#e7ece9; --dim:#9ba49d;
  --rule:#33413a; --moss-soft:#20302a; --good:#8fd0a6; --over:#ef9c86;
  --moss:#8fbfa0; --ochre:#c98b2c; --tab-idle:#141d19; --row-on:#16241d;
  --rink:#0b120f; --rpaper:#e7ece9;
  --hairline:#26332d; --soft:#14201b; --held:#3a3418;
  --field:#101a16; --well:#14201b;
  --danger-ink:#1b2320; --danger-hover:#f5bbaa;
  /* the date field's native calendar button is drawn by the browser, not by us;
     without this it stays black-on-black in every dark scheme */
  color-scheme:dark;
}
/* "Midnight": true black, for OLED screens and dark tents */
:root[data-theme="night"]{
  --paper:#000; --card:#0c0f0e; --ink:#e9efea; --dim:#8d968f;
  --rule:#262c29; --moss-soft:#16201b; --good:#86d6a1; --over:#f0a089;
  --tab-idle:#070908; --row-on:#0e1712;
  --rink:#000; --rpaper:#e9efea; --soft:#090c0b;
  --field:#070a09; --well:#090c0b;
}
/* "Smokey": Smokey Bear — bear-brown ground, denim blue, campaign-hat gold */
:root[data-theme="smokey"]{
  --paper:#1d1713; --card:#2a221b; --ink:#ece0cd; --dim:#a39683;
  --rule:#443729; --moss:#8fb2cf; --moss-soft:#32281f; --ochre:#d2a53c;
  --good:#a9c17e; --over:#e59070;
  --tab-idle:#201a14; --row-on:#2d2417;
  --rink:#15100c; --rpaper:#ece0cd; --soft:#241d16; --hairline:#443729;
  --field:#191410; --well:#241d16;
}

*{box-sizing:border-box}
/* Form wrappers that must not affect layout. `inline` makes the form vanish from
   the box tree so its button sits in the parent's flex row as if unwrapped;
   `bare` just drops the UA margin. Alpine's x-cloak hides an element until it
   has evaluated x-show, so a "signup" line does not flash on load. */
form.inline{display:contents}
form.bare{margin:0}
[x-cloak]{display:none!important}
html{overflow-x:clip;scrollbar-gutter:stable}
body{margin:0;background:var(--paper);color:var(--ink);
  font:16px/1.5 "Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  font-variant-numeric:tabular-nums;}
.num,.wt,.readout .figs,.daysum,.mealsum{font-family:"Helvetica Neue",Arial,sans-serif;
  font-variant-numeric:tabular-nums;}

/* ---- main-column header: folder tabs + trip bar on one hairline (matches the
   original .tabrow — the tabs live INSIDE the main column, to the right of the
   readout, never spanning above it) ---- */
.tabrow{display:flex;align-items:flex-end;gap:12px 16px;flex-wrap:wrap;
  border-bottom:1px solid var(--rule);margin-bottom:16px}
.tabs{display:flex;gap:4px}
.tab{background:var(--tab-idle);border:1px solid var(--rule);border-bottom:none;
  border-radius:6px 6px 0 0;color:var(--dim);padding:9px 16px;margin-bottom:-1px;
  font:inherit;font-size:15px;font-weight:600;cursor:pointer;text-decoration:none;
  display:inline-block}
.tab:hover{background:var(--hover);color:var(--hover-ink)}
.tab.active{background:var(--card);color:var(--moss);border-bottom:1px solid var(--card)}
.tripbar{display:flex;align-items:center;gap:8px;margin-left:auto;margin-bottom:7px;flex-wrap:wrap}
.tripbar .tlabel{font-size:13px;font-weight:600;color:var(--moss)}
.tripbar select{flex:0 1 auto;min-width:0;max-width:100%;background:var(--card);
  border:1px solid var(--rule);color:var(--ink);border-radius:4px;padding:6px 9px;
  font:inherit;font-size:14px;font-weight:600}
/* Before ssel.js enhances it the OS draws its own arrow, 7px wider than our
   caret, so the buttons after it slid left on every load. No arrow, and the
   right padding is the button's: 9px padding + 6px gap + the 7px caret.
   Measured 85.0 vs 84.9px, and the buttons beside it do not move. */
.tripbar select:not(.sselnative),.readout .profilebar select:not(.sselnative){
  appearance:none;-webkit-appearance:none;padding-right:22px}
.tripbar .tbtn{background:var(--card);border:1px solid var(--moss);color:var(--moss);
  padding:0 10px;font:inherit;font-size:13px;border-radius:4px;cursor:pointer;
  height:35px /* = the picker's box (14px/600 + 6px padding + border): one
                 height for every control in the row — tools/polishprobe.js */}
.tripbar .tbtn:hover{background:var(--hover)}
.tripbar .picon{padding:0;width:35px;text-align:center;font-size:15px;line-height:1}
/* Split button: picker + its actions menu as one box. The seam is the
   picker's right border; the menu button drops its own left border and its
   inner corners, and takes the picker's border colour so the box reads as one
   control. `.tripbar select:not(.sselnative)` above styles the pre-enhance
   select to the same box, so nothing moves when ssel.js swaps it. */
.tripsplit{display:inline-flex;align-items:stretch;min-width:0;flex-wrap:nowrap}
/* A long trip name ends in an ellipsis instead of pushing the buttons off the
   row: the picker is capped, the same cap on the pre-enhance <select> and the
   styled button so the first paint is the final box (shiftprobe), and the
   cap shrinks with the viewport so a phone keeps the whole row. */
.tripsplit .ssel{flex:0 1 auto;max-width:min(320px,50vw)}
.tripsplit select{max-width:min(320px,50vw);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tripsplit select,.tripsplit .sselbtn{border-top-right-radius:0;border-bottom-right-radius:0}
.tripsplit .tripmenuwrap{display:inline-flex}
.tripsplit .tripmenuwrap .tbtn{border-left:0;border-color:var(--rule);
  border-top-left-radius:0;border-bottom-left-radius:0;width:30px}
/* App controls (palette, Log out) sit apart from the trip controls: same
   8px between them, a wider gap before them, so the grouping is visible. */
.appctl{display:inline-flex;gap:8px;margin-left:12px}

/* readout header: brand, account, profile, sub-tabs (matches original) */
.readout .rbrand{font-size:21px;font-weight:700;color:var(--rpaper);letter-spacing:.01em}
.readout .rtag{font-size:12.5px;color:var(--ro-dim);margin:1px 0 14px}
.readout .acctbar{display:flex;align-items:center;gap:8px;margin-bottom:10px;
  padding-bottom:10px;border-bottom:1px solid var(--ro-line)}
.readout .acctid{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.readout .acctwho{font-size:12.5px;color:var(--ro-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.readout .acctai{font-size:11.5px;color:var(--ro-mute);border-bottom:1px dotted var(--ro-dot);align-self:flex-start;padding-bottom:1px}
.readout .acctactions{display:flex;gap:6px;flex:none}
.readout .acctbtn{background:transparent;border:1px solid var(--ro-edge);color:var(--ro-text);
  padding:4px 10px;font-size:12px;border-radius:3px;cursor:pointer;font-family:inherit;
  text-decoration:none;line-height:normal}
.readout .acctbtn:hover{background:var(--ro-hover);color:var(--rpaper)}
.readout .profilebar{display:flex;align-items:center;gap:6px;margin-bottom:12px;
  padding-bottom:12px;border-bottom:1px solid var(--ro-line)}
.readout .plabel{font-size:12px;color:var(--ro-dim);flex:none}
/* The person picker is a native <select> until ssel.js enhances it, and every
   page load paints that first. Unstyled it is 19px tall and 54px wide against
   the 35px, full-width button that replaces it, so the readout shrank and
   grew by 9px on every load — visible as a jump whenever a trip switch
   reloaded the page. Same box as .sselbtn, so the swap changes nothing. */
.readout .profilebar select:not(.sselnative){flex:1 1 auto;min-width:0;
  background:var(--field);border:1px solid var(--rule);color:var(--ink);border-radius:4px;
  padding:6px 9px;font:inherit;font-size:14px;font-weight:600;line-height:inherit}
.readout .pbtn{background:var(--ro-line);border:1px solid var(--ro-edge);color:var(--ro-text);padding:5px 10px;
  font:inherit;font-size:12.5px;border-radius:3px;cursor:pointer}
/* 35px square: the picker beside them is 35px, and a 26px button next to it
   read as sitting low. One height per row — tools/polishprobe.js. */
.readout .pbtn.picon{padding:0;width:35px;height:35px;text-align:center;font-size:14px;line-height:1}
.readout .pbtn:hover{background:var(--ro-hover);color:var(--rpaper)}
/* Person actions (rename/delete). The menu hangs off the dark readout but is paper,
   like the original — it reads as part of the page, not of the instrument panel. */
.readout .pmenuwrap{position:relative}
.readout .pmenu{position:absolute;right:0;top:calc(100% + 4px);z-index:60;min-width:170px;
  background:var(--card);border:1px solid var(--rule);border-radius:6px;
  box-shadow:0 8px 20px rgba(0,0,0,.28);padding:4px}
.readout .pmenu[hidden]{display:none}
.readout .pmi{background:none;border:0;text-align:left;padding:8px 10px;font:inherit;
  font-size:13.5px;color:var(--ink);border-radius:4px;cursor:pointer}
/* :focus as well as :hover — the menu focuses its first item on open, like the original */
.readout .pmi:hover,.readout .pmi:focus{background:var(--hover);color:var(--hover-ink);outline:none}
.readout .pmi:disabled{color:var(--dim);opacity:.6;cursor:default}
.readout .pmi:disabled:hover{background:none;color:var(--dim)}
.readout .rsubtabs{display:flex;gap:18px;margin-bottom:14px;border-bottom:1px solid var(--ro-line)}
.readout .rsub{font-size:14px;color:var(--ro-mute);padding-bottom:8px;cursor:pointer;font-weight:600}
.readout .rsub.active{color:var(--ro-active);border-bottom:2px solid var(--ro-active);margin-bottom:-1px}

/* ---- page layout: sticky summary left, content right ---- */
.wrap{max-width:1280px;margin:0 auto;padding:24px 18px 80px}
.layout{display:grid;grid-template-columns:minmax(300px,340px) minmax(0,1fr);
  gap:20px;align-items:start}
.layout > *{min-width:0}
.side{position:sticky;top:20px}
@media(max-width:1040px){ .layout{grid-template-columns:minmax(0,1fr)} .side{position:static} }

h1.screen{font-size:20px;margin:0 0 14px;color:var(--ink);letter-spacing:.01em}

/* ---- readout (dark summary panel), matches the original ---- */
/* The readout is a dark instrument panel in EVERY theme; --rink/--rpaper give each
   theme its own dark tint (sepia's warm brown, gandalf's slate) without ever letting
   the panel flip light — the old site got this via `background:var(--ink)` plus
   per-theme overrides for the dark family. */
.readout{
  background:var(--rink);color:var(--rpaper);border-radius:6px;padding:18px 20px;
  box-shadow:0 6px 20px rgba(22,32,29,.22)}
.readout h2{margin:0 0 12px;font-size:13px;font-weight:600;letter-spacing:.06em;color:var(--ro-dim);
  text-transform:uppercase}
.readout .rrow{display:flex;justify-content:space-between;padding:4px 0;color:var(--ro-text);font-size:14px}
.readout .rrow .figs{font-weight:600;color:var(--rpaper)}
.readout .rrow.total{border-top:1px solid var(--ro-line);margin-top:8px;padding-top:10px;
  font-size:15px;color:var(--rpaper);font-weight:600}
.readout .head{margin-top:12px;padding-top:12px;border-top:1px solid var(--ro-line);font-size:13px}
.readout .head.ok{color:var(--ro-ok)} .readout .head.near{color:var(--ochre)} .readout .head.over{color:var(--over)}
.readout.over{box-shadow:0 6px 20px rgba(163,64,44,.28)}
/* segment colors, shared by bar + legend */
.s-base{background:var(--seg-base)} .s-cons{background:var(--ochre)} .s-food{background:var(--seg-food)} .s-over{background:var(--over)}

/* hero total / limit — the original's, verbatim. Grid, not flex: three auto columns
   centred as a group, each number centred over its own label on row 2. The limit is
   an input drawn as a figure: transparent, dashed underline, spinner hidden. */
.readout .hero{display:grid;grid-template-columns:auto auto auto;grid-auto-rows:auto;
  justify-content:center;align-items:baseline;column-gap:13px;row-gap:6px;margin-bottom:14px;
  font-family:"Helvetica Neue",Arial,sans-serif;letter-spacing:-.02em}
.readout .hero .hn{font-size:46px;line-height:1;font-weight:600}
.readout .hero .total{grid-column:1;grid-row:1;justify-self:center;color:var(--ro-gold)}
.readout .hero.over .total{color:#f0a48f}
.readout .hero .hsl{grid-column:2;grid-row:1;font-size:36px;font-weight:400;color:#7f8a83}
.readout .hero .hnrow{grid-column:3;grid-row:1;justify-self:center;display:inline-flex;
  align-items:baseline;gap:6px}
/* --limw is the value's width in ch, set by the template (digits 1, a point
   .5); the .6ch is the air the fixed 2.6ch box gave a two-digit limit, kept
   so a round "20" paints exactly where it always did */
.readout .hero .tgt input{width:calc(var(--limw,2) * 1ch + .6ch);font:inherit;font-size:46px;font-weight:600;letter-spacing:-.02em;
  color:var(--ro-pale);background:transparent;border:none;border-bottom:1px dashed #56685e;
  text-align:center;padding:0;-moz-appearance:textfield}
.readout .hero .tgt input::-webkit-outer-spin-button,.readout .hero .tgt input::-webkit-inner-spin-button{
  -webkit-appearance:none;margin:0}
.readout .hero .tgt input:focus{outline:none;border-bottom-color:var(--ochre);color:var(--paper)}
.readout .hero .hu{font-size:18px;font-weight:400;color:var(--ro-dim)}
.readout .hlab{font-size:12.5px;font-weight:600;letter-spacing:.01em;white-space:nowrap;color:var(--ro-dim)}
.readout .hlab.lab1{grid-column:1;grid-row:2;justify-self:center;position:relative}
.readout .hlab.lab1 .pre{position:absolute;right:100%;margin-right:6px;white-space:nowrap}
.readout .hlab.lab2{grid-column:3;grid-row:2;justify-self:center}
.readout .hlab .g{color:var(--ro-gold)}
.readout .hlab .s{color:var(--ro-pale)}
.readout .segbar{display:flex;height:12px;border-radius:6px;overflow:hidden;background:var(--ro-line)}
.readout .segbar i{display:block;height:100%}
.readout .headroom{text-align:right;font-size:13px;color:var(--ro-ok);margin:8px 0 0}
.readout .headroom.over{color:var(--over)}
.readout .breakdown{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;justify-content:center;
  margin:16px 0 10px;padding-top:16px;border-top:1px solid var(--ro-line);
  font-family:"Helvetica Neue",Arial,sans-serif}
.readout .breakdown div{text-align:center}
.readout .breakdown b{display:block;font-size:22px;font-weight:700;color:var(--rpaper)}
.readout .breakdown b span{font-size:12px;font-weight:400;color:var(--ro-mute);margin-left:2px}
.readout .breakdown em{font-style:normal;font-size:11.5px;color:var(--ro-dim);
  font-family:"Iowan Old Style",Palatino,Georgia,serif}
.readout .legend{display:flex;gap:14px;font-size:11.5px;color:var(--ro-dim);margin-bottom:6px}
.readout .legend span{display:flex;align-items:center;gap:5px}
.readout .legend i{width:9px;height:9px;border-radius:2px;display:inline-block}
.readout .targets{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:14px;
  padding-top:16px;border-top:1px solid var(--ro-line)}
.readout .tcard .tlabel{font-size:11.5px;color:var(--ro-dim)}
.readout .tcard .tval{font-size:22px;font-weight:700;color:var(--rpaper);
  font-family:"Helvetica Neue",Arial,sans-serif;line-height:1.15}
.readout .tcard .tsub{font-size:11px;color:var(--ro-mute);margin-bottom:5px}
.readout .tcard .tbar{height:4px;border-radius:2px;background:var(--ro-line);overflow:hidden}
.readout .tcard .tbar i{display:block;height:100%;background:var(--seg-base)}

/* ---- panels / cards ---- */
.panel{background:var(--card);border:1px solid var(--rule);border-radius:8px;overflow:hidden;
  margin-bottom:16px}
.panelhead{padding:9px 15px;border-bottom:1px solid var(--rule);display:flex;
  justify-content:space-between;align-items:baseline;gap:10px;
  font-size:11.5px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;
  color:var(--moss);background:var(--moss-soft)}
.panelhead .sum{font-weight:400;text-transform:none;letter-spacing:0}

/* ---- folder tabs (sub-navigation) ---- */
.ptabs{display:flex;gap:4px;padding:10px 15px 0;border-bottom:1px solid var(--rule)}
.ptab{background:var(--tab-idle);border:1px solid var(--rule);border-bottom:none;
  border-radius:5px 5px 0 0;color:var(--dim);padding:7px 14px;margin-bottom:-1px;
  font:inherit;font-size:14px;font-weight:600;cursor:pointer;text-decoration:none}
.ptab:hover{background:var(--hover);color:var(--hover-ink)}
.ptab.active{background:var(--card);color:var(--moss);border-bottom:1px solid var(--card)}

/* ---- list rows (gear / food / pantry) ---- */
ul.items{list-style:none;margin:0;padding:0}
ul.items li{display:flex;align-items:center;gap:11px;padding:9px 15px;
  border-bottom:1px solid var(--hairline)}
ul.items li:last-child{border-bottom:0}
ul.items li.on{background:var(--row-on)}
input[type=checkbox]{width:19px;height:19px;flex:none;accent-color:var(--moss);cursor:pointer;margin:0}
.drag{cursor:grab;color:#c2c7bf;font-size:15px;flex:none;line-height:1;user-select:none}
.drag:hover{color:var(--moss)} .drag:active{cursor:grabbing}
li.draggingrow,.sortable-ghost{opacity:.45}
.nm{flex:1;min-width:0;line-height:1.35}
.nm b{font-weight:600;display:block;font-size:14.5px}
.nm em{font-style:normal;font-size:12.5px;color:var(--dim)}
/* The Pack READS an item's specs; the Gear Room is where they are typed. A
   rating that is not set renders nothing at all. */
.spec{flex:none;font-size:12px;font-weight:600;color:var(--dim);white-space:nowrap}
/* Gear Room: the name and the note are typed in place (editable.js). An
   editable shows its hand on hover and a ring while typing. An EMPTY note takes
   no room — no blank band under every name — so the row offers "add a note" at
   the end of the name line instead (on hover, or while the name is being
   typed), and the note line itself appears only once it is clicked into. */
.nm [data-edit][contenteditable]{cursor:text;border-radius:3px;padding:0 3px;margin-left:-3px}
.nm [data-edit][contenteditable]:hover{background:var(--hover)}
.nm [data-edit][contenteditable]:focus{outline:none;background:var(--card);
  box-shadow:inset 0 0 0 1px var(--rule)}
.nm .gnote:empty{padding:0;margin:0}            /* a zero-height line, not a band */
.nm .gnote:empty:focus{display:inline-block;min-width:6em;padding:0 3px;margin-left:-3px}
.nm .gnote:empty:focus::before{content:attr(data-ph);color:var(--dim)}
ul.items li:hover .nm:has(.gnote:empty:not(:focus)) > b::after,
.nm:has(.gnote:empty) > b:focus-within::after{content:"add a note";margin-left:6px;
  font-weight:400;font-size:12.5px;color:var(--dim);cursor:text}
.wt{font-size:14px;font-weight:600;white-space:nowrap;flex:none;display:flex;align-items:center;gap:4px}
.wt .wtu{font-size:12px;font-weight:400;color:var(--dim)}

/* ---- buttons ---- */
button,.btn{padding:6px 13px;border:1px solid var(--moss);background:var(--moss);color:#fff;
  border-radius:3px;font:inherit;font-size:13.5px;cursor:pointer;text-decoration:none;display:inline-block}
button:hover,.btn:hover{background:var(--hover-solid)}
button.ghost,.btn.ghost{background:var(--card);color:var(--moss)}
button.ghost:hover,.btn.ghost:hover{background:var(--hover)}
.rm{border:0;background:none;color:var(--mute-ink);font-size:17px;cursor:pointer;padding:2px 4px}
.rm:hover{color:var(--over)}

/* ---- qty / oz stepper ---- */
.qty{display:flex;align-items:center;gap:0;flex:none}
.qty button{width:28px;height:28px;padding:0;font-size:16px;line-height:1;border-radius:3px;
  background:var(--card);color:var(--moss);border:1px solid var(--rule)}
.qty button:hover{background:var(--hover)}
.qty .val{min-width:56px;height:28px;display:flex;align-items:center;justify-content:center;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);font-size:14px;
  font-family:"Helvetica Neue",Arial,sans-serif}

/* ---- inputs ---- */
input[type=email],input[type=password],input[type=text]{width:100%;padding:9px;
  border:1px solid var(--rule);border-radius:4px;font:inherit;font-size:14px;
  background:var(--card);color:var(--ink)}

/* ---- confidence / macro chips ---- */
.conf{font-size:11px;font-weight:600;padding:2px 8px;border-radius:10px;white-space:nowrap;
  font-family:"Helvetica Neue",Arial,sans-serif}
.conf.high,.conf.ok{background:var(--moss-soft);color:var(--good)}
.conf.medium,.conf.near{background:#f3ead6;color:var(--ochre)}
.conf.low,.conf.off{background:#f2ddd6;color:var(--over)}

.hint{color:var(--dim);font-size:12.5px;margin-top:10px;line-height:1.5}
.empty{padding:14px 15px;color:var(--mute-ink);font-size:13px}

/* ---- sub-tab strips ----
   (.ptabs itself is defined once, up with the folder tabs. There used to be a
   .pagetabs variant here that zeroed the padding and added 18px below; it put the
   Pack|Kits|Gear Room row 10px too high, flush left, and floating clear of the
   panel. The original insets them 15px and lets them sit ON the content's rule.) */
.leadline{color:var(--dim);font-size:14px;margin:0 0 14px}

/* ---- gear sections: the sage header band carries title, subtitle and weight
   (matches the original section.group/.ghead exactly) ---- */
section.group{background:var(--card);border:1px solid var(--rule);
  border-radius:4px;margin-bottom:20px;overflow:hidden}
.ghead{display:flex;justify-content:space-between;align-items:baseline;gap:12px;
  padding:12px 15px;border-bottom:1px solid var(--rule);background:var(--moss-soft)}
.ghead h2{margin:0;font-size:16px;font-weight:600;color:var(--moss)}
.ghead .sub{font-size:12.5px;color:var(--dim)}
/* serif, like the rest of the header — only .foodstat below switches to the sans
   numerals, which is why the Food band reads differently from a section weight */
.ghead .gsum{font-size:14px;font-weight:600;white-space:nowrap}
.foodstat{white-space:normal;text-align:right;font-weight:400;font-size:13px;
  font-family:"Helvetica Neue",Arial,sans-serif;font-variant-numeric:tabular-nums}
.foodstat b{font-weight:600}
.gadd{padding:9px 15px;border-top:1px solid var(--hairline);color:#b08a3e;
  font-size:13.5px;cursor:pointer}
.gadd:hover{color:var(--ochre)}

/* The "+ Add <section> from the Gear Room" picker at the foot of each section —
   the original's .addbox/.add/.packpick, verbatim. A <details>, so it costs no JS. */
.addbox{border-top:1px solid var(--rule);background:var(--well)}
.addbox>summary{list-style:none;cursor:pointer;padding:9px 15px;font-size:13px;
  font-weight:600;color:var(--moss);user-select:none}
.addbox>summary::-webkit-details-marker{display:none}
.addbox>summary:hover{background:var(--hover)}
/* the Build-a-meal picker toggles with Alpine rather than <details>, but wears the
   same .addbox summary face the original gives it */
.addboxlink{display:block;border-top:1px solid var(--rule);background:var(--well);
  padding:9px 15px;font-size:13px;font-weight:600;color:var(--moss);
  text-decoration:none;cursor:pointer;user-select:none}
.addboxlink:hover{background:var(--hover)}
.addbox[open]>summary{border-bottom:1px solid var(--rule)}
.add{padding:11px 15px;background:var(--well)}
.add .cap{font-size:12px;color:var(--dim);margin-bottom:6px}
.packpicks{display:flex;flex-direction:column;gap:1px;margin-bottom:10px;
  max-height:280px;overflow:auto}
.packpick{display:flex;align-items:center;gap:9px;font-size:13.5px;padding:4px 2px;cursor:pointer}
.packpick input{width:17px;height:17px;flex:none;margin:0}
.packpick em{font-style:normal;color:var(--dim);font-size:12.5px}
.packpick.off{opacity:.6;cursor:default}
/* the original tints these per dark theme rather than from a token */
.gpanel ul.items li{gap:10px}
/* the "missing since you came back" list: an ochre edge so it reads as a
   notice, not another gear section, and its two buttons sit where a row's
   weight normally does */
.gpanel.lostpanel{border-left:3px solid var(--ochre)}
.lostpanel .lostacts{display:flex;gap:6px;flex:none}
.lostpanel .lostacts .ghost{padding:5px 10px;font-size:12.5px}
body.locked .lostacts{display:none!important}

/* The Gear Room is a different place from the Pack: neutral header + a quiet
   left edge, so you can tell at a glance which surface you're on. */
.group.roomsec{border-left:3px solid var(--rule)}
.group.roomsec .ghead{background:var(--paper)}
.group.roomsec .ghead h2{color:var(--dim)}
.group.roomsec .gsum{color:var(--dim);font-weight:400}
/* Hans's actual gear wall, across the top of the Room. Text never sits ON it —
   the strip dissolves into the page and the caption starts below. */
.roomhero{position:relative;height:clamp(74px,10.5vw,128px);margin:6px 0 2px;
  border-radius:8px;overflow:hidden;border:1px solid var(--rule);
  background:var(--paper) url('/static/gearwall.jpg') center top/cover no-repeat}
.roomhero::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to bottom, rgba(0,0,0,0) 52%, var(--paper) 100%)}
.roomcaption{color:var(--dim);font-size:14px;margin:10px 0 16px}
.roomcaption b{color:var(--ink);font-weight:600}

/* Kits collapse so the names are what you scan; the caret sits in the header */
.kitbox>summary{list-style:none;cursor:pointer}
.kitbox>summary::-webkit-details-marker{display:none}
.kitbox>summary::before{content:"\25B8";color:var(--moss);font-size:15px;line-height:1;
  align-self:center;margin-right:4px;width:12px;text-align:center}
.kitbox[open]>summary::before{content:"\25BE"}
.kitbox>summary:hover{background:var(--hover)}
.kitbox .kitaddbtn{padding:4px 11px;font-size:12.5px;white-space:nowrap}

/* Trip Report: one card, big serif title + meta, prompts as body copy */
.reporthead{display:flex;align-items:baseline;gap:12px;padding:18px 20px 4px}
.reporthead h2{margin:0;font-size:26px;font-weight:700;color:var(--ink);letter-spacing:.01em}
.reporthead .reportmeta{font-size:13px;color:var(--dim)}
.reportbody{padding:4px 20px 18px;font-size:15px;line-height:1.65;color:var(--ink)}
.reportbody p{margin:6px 0}
.nm .lnk{color:#b7c0b6;font-size:12px;font-weight:400}
.wtbox{display:flex;align-items:center;gap:3px;flex:none;font-family:"Helvetica Neue",Arial,sans-serif}
.wtbox .wtin{min-width:34px;text-align:right;padding:5px 7px;border:1px solid var(--rule);
  border-radius:3px;font-size:13.5px;font-weight:600;background:var(--card)}
.wtbox .wtin.oz{min-width:44px}
.wtbox .wtu{font-size:12px;color:var(--dim)}
/* 32px, the same box as the weight and R-value fields on the row; a pill
   2-3px shorter than the fields it sits beside read as a stagger
   (tools/polishprobe.js). Radius = half the height keeps it a pill. */
.holdbtn{flex:none;background:var(--card);color:var(--dim);border:1px solid var(--rule);
  border-radius:16px;padding:0 12px;height:32px;font-size:12.5px;font-weight:400}
.holdbtn:hover{background:var(--hover);color:var(--hover-ink);border-color:var(--moss)}

/* ---- login gate / public landing (matches the original authgate) ---- */
.authgate{min-height:100vh;background:var(--paper);display:flex;align-items:center;
  justify-content:center;padding:20px;overflow-y:auto}
.authwrap{display:grid;grid-template-columns:minmax(0,1fr) minmax(320px,380px);
  gap:38px;align-items:center;max-width:940px;width:100%;margin:auto}
/* the reset page: the card alone, no pitch beside it */
.authwrap.single{grid-template-columns:minmax(320px,380px);justify-content:center}
.authbrand h1{margin:0;font-size:30px;color:var(--moss);letter-spacing:.01em}
.authbrand .authtag{margin:3px 0 16px;font-size:14px;color:var(--dim)}
/* the board sits left of centre in the photo (≈180px of wall on the left,
   410px on the right, of 1600). At this strip's width nothing is cropped
   sideways, so it reads off-centre; 1600/1370 zoom anchored left trims the
   right wall to match the left and centres the board. */
.authshot{height:118px;border-radius:8px;border:1px solid var(--rule);margin-bottom:16px;
  background:var(--paper) url('/static/gearwall.jpg') left top/116.8% auto no-repeat}
.authlede{margin:0 0 14px;font-size:15px;line-height:1.5;color:var(--ink);max-width:52ch}
.authfeat{margin:0 0 16px;padding:0;list-style:none;max-width:52ch}
.authfeat li{position:relative;padding:3px 0 3px 19px;font-size:14px;line-height:1.45}
.authfeat li::before{content:'';position:absolute;left:3px;top:11px;width:6px;height:6px;
  border-radius:50%;background:var(--moss)}
.authfoot{margin:0;font-size:12.5px;line-height:1.5;color:var(--dim);max-width:52ch;
  border-top:1px solid var(--rule);padding-top:12px}
/* Phone: the form first. The left column dissolves so brand, card and pitch
   are three grid items in that order — Hans had to scroll past the pitch to
   sign in. The pitch keeps its copy but loses the photo strip and the
   feature list: on a phone that is chatter between someone and the button. */
@media(max-width:820px){
  .authgate{align-items:flex-start;padding:16px 14px 34px}
  .authwrap{grid-template-columns:minmax(0,1fr);gap:18px;max-width:420px}
  .authleft{display:contents}
  .authbrand{order:1} .authcard{order:2} .authpitch{order:3}
  .authbrand h1{font-size:25px} .authbrand .authtag{margin-bottom:0}
  .authshot,.authfeat{display:none}
  .authlede{font-size:14px;color:var(--dim)}
}
.authcard{background:var(--card);border:1px solid var(--rule);border-radius:8px;
  max-width:380px;width:100%;padding:26px 24px;box-shadow:0 12px 34px rgba(0,0,0,.14)}
.authcard h1{margin:0 0 2px;font-size:26px;color:var(--moss);letter-spacing:.01em}
.authcard .authsub{margin:0 0 18px;font-size:13.5px;color:var(--dim)}
.authcard label{display:block;font-size:12px;font-weight:600;color:var(--dim);margin-top:12px}
.authcard input{margin-top:5px}
.authcard button.authsubmit{width:100%;margin-top:18px;padding:10px;font-size:15px}
.autherr{color:var(--over);font-size:13px;margin-top:12px;min-height:1px}
.authswitch{margin-top:16px;font-size:13px;color:var(--dim);text-align:center}
.authswitch a{color:var(--moss);font-weight:600;cursor:pointer;text-decoration:underline}
.authgoogle{margin-top:16px;padding-top:16px;border-top:1px solid var(--rule);
  font-size:12px;color:var(--dim);text-align:center}
/* Google's button, to its branding spec: 40px tall, neutral field, #747775
   border, 20px logo, 14px medium text — and its own hover, so the generic
   button:hover (specificity 0,1,1) cannot slam it to moss green */
.gsi{display:flex;align-items:center;justify-content:center;gap:12px;width:100%;margin-top:10px;
  height:40px;padding:0 12px;border:1px solid #747775;border-radius:4px;background:#fff;color:#1f1f1f;
  font-family:inherit;font-size:14px;font-weight:500;line-height:1;cursor:pointer}
.gsi:hover{background:#f2f2f2}
.gsi:disabled{opacity:.6;cursor:default}
.gsi-logo{width:20px;height:20px;flex:none}
:root[data-dark] .gsi{background:#131314;border-color:#8e918f;color:#e3e3e3}
:root[data-dark] .gsi:hover{background:#2a2a2b}

/* ================= A/B parity pass additions ================= */
[x-cloak]{display:none!important}

/* toolbar row above the pack / kits: lead line left, actions right */
.gearbar{display:flex;align-items:center;gap:10px;margin:14px 0;flex-wrap:wrap}
.gearbar .leadline{margin:0}
.gearbar .sp,.reporthead .sp{flex:1}

/* AI controls carry the Claude spark; unwired ones are disabled with a title */
/* AI controls are just ghost buttons in the original — same border, radius, padding
   and weight as any other — distinguished only by the Claude spark. They had drifted
   to a grey border, 4px radius and 600 weight, which read as a different control. */
.aibtn{background:#fff;border:1px solid var(--moss);color:var(--moss);
  border-radius:3px;padding:6px 13px;font:inherit;font-size:13.5px;
  cursor:pointer;white-space:nowrap}
.aibtn:hover:not(:disabled){background:var(--hover)}
.aibtn:disabled{cursor:default;opacity:.75}
.cicon{vertical-align:-2px;margin-right:5px}

/* Styled select (.ssel) — the original's replacement for every native <select>, so
   the list is ours rather than an OS popup: paper menu, a tick on the active row,
   and it follows the theme. Global on purpose; the trip bar's select wants it too.
   Values are the original's, verbatim. */
.ssel{position:relative;display:inline-flex;min-width:0;flex:1 1 auto}
.ssel select.sselnative{position:absolute;opacity:0;pointer-events:none;width:1px;height:1px}
.sselbtn{display:flex;align-items:center;gap:6px;width:100%;min-width:0;
  background:var(--field);border:1px solid var(--rule);color:var(--ink);border-radius:4px;
  padding:6px 9px;font:inherit;font-size:14px;font-weight:600;cursor:pointer;text-align:left}
.sselbtn .sseltxt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sselbtn .sselcar{color:var(--dim);font-size:11px;flex:none}
/* an explicit hover background, or the bare `button:hover` above wins on
   specificity (0,1,1 over 0,1,0) and paints the whole control dark */
.sselbtn:hover{border-color:var(--moss);background:var(--hover)}
.sselmenu{position:absolute;top:calc(100% + 4px);left:0;min-width:100%;width:max-content;
  max-width:min(320px,80vw);max-height:280px;overflow:auto;z-index:46;
  background:var(--card);border:1px solid var(--rule);border-radius:6px;
  box-shadow:0 8px 20px rgba(0,0,0,.18);padding:4px}
/* ssel.js closes the menu with the `hidden` attribute, which only works through the
   UA's [hidden]{display:none} — any explicit display beats it. The original carries
   this rule for that reason; dropping it (and adding display:flex above) left every
   styled select permanently open. */
.sselmenu[hidden]{display:none}
.sselmenu .ssi{display:flex;align-items:center;gap:7px;width:100%;text-align:left;
  background:none;border:0;font:inherit;font-size:13.5px;color:var(--ink);
  padding:7px 9px;border-radius:4px;cursor:pointer}
.sselmenu .ssi:hover,.sselmenu .ssi:focus{background:var(--hover);outline:none}
.sselmenu .ssi .tick{width:12px;flex:none;color:var(--moss);font-weight:700}
/* Scoped to .tform, NOT .readout: the Sex box sits among dark inputs and has to
   match them, but the person picker is in the same dark panel and is deliberately
   WHITE there, exactly as the original draws it. Matches .tform input. */
.tform .sselbtn{background:var(--ro-line);border-color:var(--ro-edge);color:var(--ro-field-ink);
  border-radius:4px;padding:7px 9px;font-size:14px}
.tform .sselbtn:hover{border-color:var(--ro-edge-hover);background:var(--ro-hover)}
.tform .sselbtn .sselcar{color:var(--ro-mute)}
.tform .ssel{flex:none;min-width:96px}
/* Dark family: EVERY styled select takes the theme's field colour, the Sex box in
   .tform included. Not redundant with .sselbtn{background:var(--field)} above —
   html[data-dark] .sselbtn is (0,2,1) and outranks .tform .sselbtn (0,2,0), which is
   exactly how the original gets a #101a16 Sex box in dark themes rather than the
   readout's raised #2b3733. Dropping this rule changed that box and nothing else. */
html[data-dark] .sselbtn{background:var(--field);color:var(--ink)}

/* AI check results — the original's .mealcheck box, verbatim, plus the two bits
   the rewrite needs around it: the cost hint every AI control carries, and the
   error line that an over-quota or upstream failure lands in. */
.mealcheck{margin:0 0 12px;border:1px solid var(--rule);border-radius:4px;background:var(--soft)}
.mealcheck>summary{cursor:pointer;list-style:none;padding:8px 12px;font-size:13px;
  font-weight:600;color:var(--moss)}
.mealcheck>summary::-webkit-details-marker{display:none}
.mealcheck>summary::before{content:"\25B8";margin-right:6px;color:var(--moss)}
.mealcheck[open]>summary::before{content:"\25BE"}
.mealcheck>summary .boxsub{font-weight:400;font-size:12px;color:var(--dim);
  margin:2px 0 0 18px}
.mcbody{padding:2px 14px 12px;font-size:13.5px;line-height:1.55;color:var(--ink)}
.mcbody p{margin:0 0 8px} .mcbody ul{margin:0;padding-left:19px} .mcbody li{margin:3px 0}
.mcbody .mcq{font-style:italic;color:var(--dim)}
/* the figures row inside a result box: same shape as the readout's breakdown */
.mcfigs{display:flex;gap:18px;flex-wrap:wrap;margin:0 0 10px}
.mcfigs div{text-align:center}
.mcfigs b{display:block;font-size:20px;font-weight:700;color:var(--moss);
  font-family:"Helvetica Neue",Arial,sans-serif}
.mcfigs b span{font-size:11px;font-weight:400;color:var(--dim);margin-left:1px}
.mcfigs em{font-style:normal;font-size:11.5px;color:var(--dim)}
/* the AI control row: a toolbar, so the inputs are sized rather than left to
   fill the line and wrap one-per-row */
.aiform{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 12px}
.aiform input{border:1px solid var(--rule);border-radius:4px;background:var(--card);
  color:var(--ink);font:inherit;font-size:13.5px;padding:6px 9px}
.aiform input[name=destination]{flex:1 1 210px;min-width:0}
.aiform input[name=when]{flex:0 1 170px;min-width:0}
.aiform input[name=elevation]{flex:0 0 62px;text-align:center}
.aicost{font-size:12px;color:var(--dim);white-space:nowrap}
/* Suggest just wrote these: a gold wash that fades, so the eye finds what changed */
@keyframes targetflash{from{background:var(--ochre);color:var(--rink)}to{background:var(--ro-line);color:var(--ro-field-ink)}}
.tform input.flash{animation:targetflash 2.6s ease-out 1}
.whymodal p{font-size:14.5px;line-height:1.55;color:var(--ink);margin:8px 0}
.whymodal .hint{margin-top:10px}
.modalactions{display:flex;justify-content:flex-end;margin-top:12px}

/* the pending state of an AI panel, while a worker has the job */
.aiworking{display:flex;align-items:center;gap:8px;margin:0 0 12px;
  font-size:13px;color:var(--dim)}
.aispin{width:11px;height:11px;flex:none;border-radius:50%;
  border:2px solid var(--rule);border-top-color:var(--moss);
  animation:aispin 0.7s linear infinite}
@keyframes aispin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.aispin{animation:none}}
.readout .aiworking{color:var(--ro-dim)}
.readout .aispin{border-color:var(--ro-edge);border-top-color:var(--ro-accent)}
/* Suggest's status line, in the dark readout — the original's .bstatus colours */
.bstatus{font-size:12.5px;color:var(--ro-dim);margin-top:10px;line-height:1.5}
.bstatus.err{color:#f0a48f}
.bstatus.ok{color:#9fd5b2}
/* what a lookup found, sitting under the Add row as a hint rather than a heading —
   the weight is a suggestion until a person presses Add */
.lookuphit{margin:0;font-size:13px;color:var(--dim);line-height:1.5}
.lookuphit b{color:var(--ink)}
.condconf{font-size:11.5px;color:var(--dim);border:1px solid var(--rule);border-radius:10px;
  padding:1px 7px;margin-left:6px;white-space:nowrap}
.aierr{margin:0 0 12px;padding:9px 12px;border:1px solid var(--over);border-radius:4px;
  background:var(--card);color:var(--over);font-size:13.5px}

/* trip actions dropdown */
.tripmenuwrap{position:relative}
.tripmenu{position:absolute;right:0;top:calc(100% + 4px);z-index:60;min-width:190px;
  background:var(--card);border:1px solid var(--rule);border-radius:6px;
  box-shadow:0 10px 26px rgba(22,32,29,.18);padding:4px;display:flex;flex-direction:column}
.tmi{background:none;border:0;text-align:left;padding:8px 12px;font:inherit;
  font-size:13.5px;color:var(--ink);border-radius:4px;cursor:pointer}
.tmi:hover{background:var(--hover);color:var(--hover-ink)}
.tmi:disabled{color:var(--dim);opacity:.6;cursor:default}
.tmi:disabled:hover{background:none;color:var(--dim)}
/* A menu hangs off its button's RIGHT edge, which is right for a button at
   the end of a row. On a phone the app controls wrap to a second line at
   the LEFT edge and the settings menu opened 125px off-screen; at 606px
   they are still on the right. So the button decides on each open (base.html
   sets .flip when it sits in the left half) and the menu hangs the other way. */
.tripmenu.flip{left:0;right:auto}
/* the settings menu: a heading over a radio pair, the chosen one marked with
   the same wash a hover uses, so the state reads before anything is clicked */
.setmenu{margin:0}
.setmenu .tmhead{font-size:11.5px;text-transform:uppercase;letter-spacing:.04em;
  color:var(--dim);padding:6px 12px 2px}
.setmenu .tmi{display:flex;justify-content:space-between;gap:14px;align-items:baseline}
.setmenu .tmi small{font-size:12px;color:var(--dim)}
.setmenu .tmi.on{background:var(--hover);color:var(--hover-ink)}
.setmenu .tmi.on small{color:inherit;opacity:.8}

/* modal (Trip details) */
.modalmask{position:fixed;inset:0;z-index:100;background:rgba(15,20,15,.55);
  display:flex;align-items:flex-start;justify-content:center;padding:40px 16px;overflow:auto}
.modal{background:var(--card);border:1px solid var(--rule);border-radius:8px;
  width:min(440px,100%);padding:22px 24px;box-shadow:0 18px 48px rgba(0,0,0,.25)}
.modal h2{margin:0 0 4px;font-size:20px;color:var(--moss)}
.modalsub{margin:0 0 14px;font-size:13px;color:var(--dim);line-height:1.5}
.mlabel{display:block;font-size:12.5px;font-weight:600;color:var(--dim);margin-top:12px}
.mlabel input{margin-top:5px}
.modalactions{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}

/* a review's body: the summary line, the action items, then the detail */
.mcsummary{margin:0 0 8px;font-weight:600;color:var(--ink)}
.mcactions{margin:0 0 10px;padding:8px 10px;border:1px solid var(--rule);border-radius:6px;
  background:var(--well)}
.mcactions .mcah{font-size:11.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;
  color:var(--moss);margin-bottom:4px}
.mcactions ul{margin:0;padding-left:18px}
.mcactions li{margin:2px 0}
.mcnone{margin:0 0 8px;font-size:13px;color:var(--good)}
.mcdetail{font-size:13px;color:var(--dim)}

/* Locked: read-only, safe to scroll. The ROUTES refuse edits; this only takes
   the controls away so nothing invites one. Trip bar, readout account bar, tabs
   and AI panels stay live, as in the original. Mapped from its body.locked rules. */
body.locked .addbox,body.locked .addform,body.locked .addrow,body.locked .gadd,
body.locked .gaddwrap,body.locked .kitaddbtn,body.locked .rm,body.locked .holdbtn,
body.locked .mealadd,body.locked .slotpick,body.locked .bmpick,body.locked .buildmeal,
body.locked .manual,body.locked .paste,body.locked .filterin,body.locked .drag,
body.locked .packpick,body.locked .roompointer{display:none!important}
body.locked ul.items li,body.locked .planitem,body.locked .wtedit,body.locked .rval,
body.locked .ownedbox,body.locked .qty,body.locked .tform input,body.locked .tform .ssel,
body.locked .hero input{pointer-events:none!important}
body.locked ul.items li .lnk,body.locked ul.items li a{pointer-events:auto!important}
body.locked ul.items li,body.locked .planitem{cursor:default}
.tripbar .tbtn.on{background:var(--moss);color:var(--card)}

/* ---- trip report — values from the original, colours as tokens ---- */
.rptcard{padding:16px 18px}
.rpthead{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.rpthead h2{margin:0}
.rpthead .grow{flex:1}
.rptstamp{font-size:12px;color:var(--dim)}
.rpttools{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:8px;
  border:1px solid var(--rule);border-radius:5px;padding:4px;background:var(--paper)}
.rpttools button{background:none;border:1px solid transparent;color:var(--ink);
  font:inherit;font-size:13.5px;min-width:30px;padding:4px 8px;border-radius:4px;cursor:pointer}
.rpttools button:hover{background:var(--hover);border-color:var(--rule)}
.rpttools .sep{width:1px;background:var(--rule);margin:2px 3px}
.rptedit{min-height:260px;border:1px solid var(--rule);border-radius:5px;background:var(--card);
  padding:12px 14px;font-size:15px;line-height:1.6;outline:none;overflow-wrap:anywhere}
.rptedit:focus{border-color:var(--moss);box-shadow:0 0 0 2px var(--moss-soft)}
.rptview{border:1px solid transparent;padding:2px 0;font-size:15px;line-height:1.6;
  overflow-wrap:anywhere}
.rptview h2,.rptedit h2{font-size:17px;margin:14px 0 6px}
.rptview h3,.rptedit h3{font-size:15px;margin:12px 0 5px}
.rptview p,.rptedit p{margin:0 0 9px}
.rptview ul,.rptview ol,.rptedit ul,.rptedit ol{margin:0 0 9px;padding-left:22px}
.rptview a,.rptedit a{color:var(--moss);text-decoration:underline}
.rptedit:empty::before{content:attr(data-ph);color:var(--dim);white-space:pre-line}
.rptempty{color:var(--dim);white-space:pre-line;font-size:14.5px;line-height:1.7}
.rptdraft{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:13px;
  background:var(--moss-soft);border:1px solid var(--rule);border-radius:5px;
  padding:7px 10px;margin-bottom:8px}
.rptdraft[hidden]{display:none}
.rptdraft button{font-size:12px;padding:2px 8px}
.rptdirty{color:var(--ochre);font-size:12px;font-weight:600}
.rptlinkin{width:100%;margin:8px 0 4px;padding:9px;border:1px solid var(--rule);border-radius:4px;
  font:inherit;font-size:14px;background:var(--card);color:var(--ink)}
.rptlinkh{color:var(--moss)!important}
body.locked .rptbtn{display:none!important}
.tripbar .tbtn.on{border-color:var(--moss)}

/* Print checklist: the free preflight list above the section boxes */
.prflight{margin:0 0 12px;padding:8px 10px;border:1px solid var(--rule);border-radius:6px;
  background:var(--well)}
.prflight .prfh{font-size:12px;font-weight:700;color:var(--moss);margin-bottom:4px}
.prflight ul{margin:0;padding-left:18px;font-size:12.5px;line-height:1.5}
.prflight li.warn{color:var(--over)}
.prflight li.note{color:var(--dim)}
.prflight .prfok{margin:0;font-size:12.5px;color:var(--good)}
.prflight .prfpast{margin:0;font-size:12.5px;line-height:1.5;color:var(--dim)}
.prflight .prfdone{margin:6px 0 0;font-size:12.5px;line-height:1.5;color:var(--ink)}
.prflight .prfrow{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px}
.prflight .prfrow form{margin-top:0}
.resultsbox{width:min(520px,100%)}
.resultsbox h3{color:var(--moss)}
.prfresult{margin:10px 0 0;padding-top:10px;border-top:1px solid var(--rule)}
.prfresult:first-of-type{border-top:0;padding-top:0}
.prfresult p{margin:4px 0 0}
.prfresult ul{margin:4px 0 0;padding-left:18px;font-size:13px;line-height:1.5}
.prflight form{display:flex;align-items:center;gap:8px;margin-top:8px}
.prflight .prfai{font-size:12.5px;padding:5px 10px}
.modal .rosterrow input[type=checkbox]{width:16px;height:16px}

/* Delete or archive: two answers, each with its consequence beside it, because
   the difference between them is the whole decision. */
.binchoice{display:flex;align-items:flex-start;gap:12px;margin-top:14px}
/* the two buttons share one column width so the answers line up; the reason
   for each takes the rest, and min-width:0 is what stops a long one pushing
   its way out of the dialog instead of wrapping */
.binchoice > form,.binchoice > button{flex:0 0 132px}
.binchoice > form button{width:100%}
.binwhy{flex:1;min-width:0;font-size:12.5px;line-height:1.5;color:var(--dim)}
.binrestore{padding:3px 10px;font-size:12.5px}
.mrule{border-top:1px solid var(--rule);margin:18px 0 4px}
.rosterrow .binrestore{margin-left:auto}

/* "Do you really wish to close?" — over the dialog it is about, so the dialog
   itself never moves. z-index above .modalmask (100); its backdrop is inert on
   purpose, because a confirmation you can click past is not a confirmation. */
.confirmmask{position:fixed;inset:0;z-index:300;background:rgba(15,20,15,.45);
  display:flex;align-items:center;justify-content:center;padding:24px 16px}
.confirmmask[x-cloak]{display:none}
/* the same box driven by the `hidden` attribute (the report's link prompt): the
   class's display:flex outranks the UA's [hidden], so say it explicitly */
.confirmmask[hidden]{display:none}
.confirmbox{background:var(--card);border:1px solid var(--rule);border-radius:8px;
  width:min(400px,100%);padding:20px 22px;box-shadow:0 22px 56px rgba(0,0,0,.4)}
.confirmbox h3{margin:0 0 8px;font-size:17px;color:var(--over)}
.confirmbox p{margin:0;font-size:13.5px;line-height:1.55;color:var(--ink)}
button.danger{background:var(--over);border-color:var(--over);color:var(--danger-ink)}
button.danger:hover{background:var(--danger-hover);border-color:var(--danger-hover)}

/* The Trip details / New trip dialog. One set of fields for both — the New
   version just adds the copy choice at the top — so all of this is shared. */
.modal.wide{width:min(560px,100%)}
/* A field is as wide as its answer. A day count is one or two characters and a
   full-width box for it reads as a mistake, so only the fields that hold a
   sentence stretch: everything in a row sizes to its content, and ONE child
   marked .grow takes whatever is left. */
.mrow{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-start}
/* every label in a row stacks over its field, as the full-width ones outside a
   row already do — shrink-to-content otherwise lets the short ones fall inline
   and the row reads as two different layouts */
.mrow .mlabel{flex:0 0 auto;display:flex;flex-direction:column;align-items:flex-start}
.mrow .mlabel.grow{flex:1;min-width:150px}
/* the date, number and search fields the dialog adds. SCOPED to .modal on
   purpose: `input[type=number]` unscoped is (0,1,1) and would outrank .wtin,
   .rvin and the hero's limit — the bare-element-selector trap, one rung up. */
.modal input[type=search],.modal input[type=date],.modal input[type=number]{
  padding:9px;border:1px solid var(--rule);border-radius:4px;
  font:inherit;font-size:14px;background:var(--card);color:var(--ink)}
.modal input[type=search]{width:100%}
.modal input[type=date]{width:11.5em}
.modal input[type=number].wnum{width:4.5em}
.modal input[type=number].wnum.wide{width:7em}
.unitpair{display:flex;align-items:center;gap:5px;margin-top:5px}
.unitpair input{margin-top:0}
.unitpair i{font-style:normal;font-size:12.5px;font-weight:600;color:var(--dim)}
/* One height for every control in a dialog row — inputs, the styled select's
   button, a unit-suffixed pair. ssel.js's button is 6px-padded everywhere else,
   and mixed heights in a row stagger the labels above them whichever edge you
   align to. Scoped to .modal so the readout's own selects keep their size. */
.modal .mrow input,.modal .mrow .sselbtn,.modal .mrow select{height:40px}
/* .mlabel input already carries this gap under the label; ssel.js's wrapper
   replaces the <select> with a <div>, so it has to be given the same one */
.modal .mrow .ssel,.modal .mrow select{margin-top:5px}
.modal .sselbtn{padding:9px}
.copypick{display:flex;flex-direction:column;gap:2px;margin:4px 0 0}
/* the dialog is long enough without 14px under every explanatory line */
.modal .modalsub{margin-bottom:10px}
.modal h2+.modalsub{margin-bottom:12px}
.rosterrow.chkrow{margin:12px 0 0}
.rosterrow input[type=radio]{width:16px;height:16px;flex:none;accent-color:var(--moss)}
.rosterrow input:disabled{opacity:.55}
.tcmaddrow{display:flex;gap:8px;margin-top:2px}
.tcmaddrow input{flex:1;min-width:0}
/* Start date as words, days as a stepper, the end date said back — tripdate.js.
   The stepper reuses the .qty look but at the dialog's 40px row height, and
   the calendar input exists only for showPicker(): it never paints. */
.datein{position:relative;display:flex;gap:8px;margin-top:5px;align-self:stretch}
.datein input[type=text]{flex:1;min-width:0;margin-top:0}
.calbtn{flex:none;width:42px;background:var(--card);border:1px solid var(--rule);
  border-radius:4px;font-size:17px;line-height:1;cursor:pointer}
.calbtn:hover{background:var(--hover)}
.calnative{position:absolute;left:0;bottom:0;width:1px;height:1px;opacity:0;pointer-events:none}
.daystep{margin-top:5px}
.daystep button{width:36px;height:40px;font-size:18px}
.daystep button:first-child{border-radius:4px 0 0 4px}
.daystep button:last-child{border-radius:0 4px 4px 0}
/* margin-top:0 — the 5px under the label is .daystep's; `.mlabel input` gave
   the field its own too, and centred beside margin-less buttons that read as
   the number sitting 2.5px low. tools/polishprobe.js is what catches this. */
.modal .daystep input.val{width:3.4em;height:40px;border-radius:0;border-left:0;border-right:0;
  text-align:center;padding:9px 4px;margin-top:0;-moz-appearance:textfield}
.daystep input::-webkit-outer-spin-button,.daystep input::-webkit-inner-spin-button{
  -webkit-appearance:none;margin:0}
.daystep input:disabled{color:var(--dim)}
.modal .endin input{width:11em;margin-top:5px}
/* the Day hike box lives in the date row, level with the inputs, not the labels */
.mrow .chkrow.inrow{margin:0;align-self:flex-end;height:40px;display:flex;align-items:center;gap:6px}
.modal .dateecho{margin:6px 0 0;min-height:1.5em;font-size:12.5px}
.dateecho.bad{color:var(--over)}
.tcmhint{margin:7px 0 0;font-size:12px;line-height:1.5}
.tcmhint code{font-size:11.5px;background:var(--hover);padding:1px 4px;border-radius:3px}

/* Trip conditions: where the numbers came from, and what is burning nearby.
   Values verbatim from the original (static/pack-planner.html). */
.askabout{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}
.askabout b{font-size:13.5px;color:var(--ink)}
.askmeta{font-size:12px;color:var(--dim)}
.wxsrc{margin:0 0 8px;font-size:12px;color:var(--dim)}
.wxbadge{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.03em;
  text-transform:uppercase;padding:2px 7px;border-radius:10px;margin-right:6px;
  background:var(--moss-soft);color:var(--dim)}
.wxbadge.fc{background:var(--moss-soft);color:var(--good)}
.wxbadge.hist{background:var(--held);color:var(--ochre)}
.smokebox{margin:8px 0 4px;padding:8px 10px;border:1px solid var(--rule);border-radius:6px;
  background:var(--moss-soft)}
.smokeline{margin:0 0 5px;font-size:13px}
.smokeline:last-of-type{margin-bottom:6px}
.smokebox .dimline{margin:0;font-size:12px;color:var(--dim)}
.aqibadge{display:inline-block;font-size:11px;font-weight:700;padding:1px 7px;border-radius:10px;
  margin-right:4px;color:#fff;vertical-align:1px}
.aqibadge.aqi-good{background:var(--good)}
.aqibadge.aqi-mod{background:var(--ochre)}
.aqibadge.aqi-usg{background:#c9702a}
.aqibadge.aqi-bad{background:var(--over)}
.aqibadge.aqi-haz{background:#7a2438}
.aqibadge.fire{background:#b5451f}

/* the camp-pin map. Hidden until the 📍 is pressed — see tripmap.js. */
.geofield{position:relative;display:flex;gap:8px;align-items:stretch}
.mapbtn{flex:none;width:42px;background:var(--card);border:1px solid var(--rule);
  border-radius:4px;font-size:17px;line-height:1;cursor:pointer;margin-top:5px}
.mapbtn:hover{background:var(--hover)}
.mappanel{margin-top:8px}
.mappanel[hidden]{display:none}
/* Two screens. With the map open on a wide screen the dialog grows and the
   map takes the right half, every other field keeping its place on the left
   — the grid lifts ONE child (.mappanel, a direct child of .tdfields) into
   column 2 and spans it down the whole list. Under 900px there is no grid:
   one column, the map right under Location where the DOM puts it, and the
   dialog no wider than the phone. The switch rides on the 📍 click, never on
   load, so first paint is untouched. */
@media(min-width:900px){
  .modal.wide:has(.mappanel:not([hidden]):not(.mini)){width:min(1040px,100%)}
  .tdfields:has(.mappanel:not([hidden]):not(.mini)){display:grid;
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:24px;align-items:start}
  .tdfields:has(.mappanel:not([hidden]):not(.mini))>.mappanel{grid-column:2;grid-row:1/span 40;
    margin-top:12px;position:sticky;top:0}
  .tdfields:has(.mappanel:not([hidden]):not(.mini)) .mapcanvas{height:min(640px,72vh)}
}
/* Done: the map folds to a strip with the pin on it, back in the single
   column under Location. Nothing on it takes the mouse — the strip is one
   button (.mapexpand) that opens the map again. */
.mappanel{position:relative}
.mapexpand{display:none}
.mappanel.mini .mapcanvas{height:88px;pointer-events:none}
.mappanel.mini .leaflet-control-container{display:none}
.mappanel.mini [data-mapbar],.mappanel.mini .mapnote{display:none}
.mappanel.mini .mapexpand{display:block;position:absolute;inset:0;height:88px;z-index:1000; /* over Leaflet's panes (400+) */
  background:transparent;border:0;border-radius:6px;cursor:pointer;font:inherit;
  font-size:12.5px;font-weight:600;color:var(--ink);text-align:left;padding:8px 10px;
  text-shadow:0 0 6px var(--card),0 0 2px var(--card)}
.mappanel.mini .mapexpand:hover{background:rgba(127,127,127,.12)}
.mapdone{margin-left:auto}
/* Twice the height it launched with: at 280px the pin was always a drag from
   the edge, and panning a map you can barely see is the whole job here. The
   dialog's mask scrolls, so a tall map just makes a taller dialog; the vh
   clamp keeps a phone from giving the map the entire screen. */
.mapcanvas{height:min(560px,70vh);border:1px solid var(--rule);border-radius:6px;overflow:hidden}
.mapbar{display:flex;gap:6px;margin-top:6px}
.maptoggle{background:var(--card);border:1px solid var(--rule);color:var(--ink);
  border-radius:4px;padding:5px 10px;font:inherit;font-size:12.5px;cursor:pointer}
.maptoggle:hover{background:var(--hover);color:var(--hover-ink)}
.maptoggle.on{background:var(--hover);color:var(--hover-ink);border-color:var(--moss);font-weight:600}
.mapnote{margin:6px 0 0;font-size:12px}
/* the marker: a CSS pin, so no image files and it follows the theme */
.camppin span{display:block;width:16px;height:16px;margin:3px;border-radius:50% 50% 50% 0;
  transform:rotate(-45deg);background:var(--over);border:2px solid #fff;
  box-shadow:0 1px 4px rgba(0,0,0,.4)}
/* Leaflet paints its own controls and attribution; keep them legible on the
   dark themes without restating the palette. */
.leaflet-container{background:var(--well);font:inherit;font-size:12px}
.leaflet-control-attribution{background:var(--card)!important;color:var(--dim)!important}
.leaflet-control-attribution a{color:var(--moss)!important}

/* the location type-ahead. The drop sits over the fields below it, so it is
   positioned against .geowrap rather than the modal. */
.geowrap{position:relative}

.geodrop{position:absolute;left:0;right:0;top:calc(100% + 2px);z-index:70;
  background:var(--card);border:1px solid var(--rule);border-radius:4px;
  max-height:240px;overflow:auto;box-shadow:0 10px 26px rgba(0,0,0,.16)}
.geodrop[hidden]{display:none}
.geodrop .gi{padding:8px 10px;font-size:13.5px;color:var(--ink);cursor:pointer}
.geodrop .gi:hover,.geodrop .gi.hot{background:var(--hover);color:var(--hover-ink)}
.geodrop .gimeta{font-size:12px;color:var(--dim)}
.geodrop .gi:hover .gimeta,.geodrop .gi.hot .gimeta{color:var(--hover-ink)}
.geodrop .noresult{padding:8px 10px;font-size:13px;color:var(--dim)}
.locerr{margin-top:6px;font-size:12.5px;line-height:1.45;color:var(--over)}
.locerr[hidden]{display:none}

/* on hold: still on the list, not in the total. Deliberately loud. */
ul.items li.held{background:var(--held);box-shadow:inset 3px 0 0 #d9a406}
ul.items li.held .wtedit{opacity:.45}
ul.items li.held .wtedit .wtin{text-decoration:line-through}
ul.items li.held .wt{opacity:.45;text-decoration:line-through}
ul.items li.held .nm b.gname{color:#7a5c05}
.heldsum{font-size:11px;font-weight:600;color:#8a6a08;margin-left:6px}
.holdbtn.isheld{background:#d9a406;border-color:#c09105;color:#2d2206}

/* R-value / °F rating beside the weight, and the owned count in the Room */
.rval{display:flex;align-items:center;gap:4px;flex:none;font-size:12px;
  font-weight:600;color:var(--dim);margin:0}
.rval .rvin{width:46px;height:32px;text-align:right;padding:0 6px;border:1px solid var(--rule);
  border-radius:3px;font:inherit;font-size:13px;font-weight:600;background:var(--card);
  color:var(--ink)}
.wtedit{display:flex;align-items:center;gap:3px;margin:0}
.wtbox .wtin,.ownedbox .wtin{color:var(--ink)}
.ownedbox{display:flex;align-items:center;gap:4px;margin:0}
.ownedbox .wtin{min-width:40px;width:40px}
.ownedbox .wtu{color:var(--mute-ink)}
.taken{display:inline-block;font-size:11px;font-weight:600;margin-top:2px;padding:1px 7px;
  border-radius:9px;font-family:"Helvetica Neue",Arial,sans-serif}
.taken.mine{background:var(--moss);color:var(--card)}
.nm .taken{display:inline-block}

/* pack footer pointer to the Room */
.roompointer{color:var(--dim);font-size:14px;margin:22px 0 10px}
.roompointer b{color:var(--ink)}

/* the Room's Add gear box + filter */
.paste.roomadd{background:var(--soft);border:1px solid var(--rule);border-radius:8px;
  padding:12px 14px;margin:0 0 16px}
.addrow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:9px}
.addrow:last-child{margin-bottom:0}
/* the original's .cap.capai: plain body text carrying the Claude spark, not a
   bolded moss heading with an ochre glyph */
.addtitle{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap;
  font-size:16px;font-weight:400;color:var(--ink)}
.addform{display:flex;align-items:center;gap:8px;flex:1;min-width:0;margin:0}
.addform input[type=text]{flex:1;min-width:0}
.addform .wtin{width:64px}
/* One 34px box for everything on an add row: the name field was 41px (the
   generic input padding), the oz field 32, the buttons 34, and the row read
   as three different heights (tools/polishprobe.js). 34 is the buttons'
   natural height, so they do not change. */
.addrow .aibtn,.addrow .ghost,.addform input[type=text],.addform .wtin,.addform button{
  height:34px;padding-top:0;padding-bottom:0}
.addform.inline{padding:9px 15px;flex:none}
.addform.inline input[type=text]{width:200px;flex:none}
.filterin{max-width:260px;font-size:13px;padding:7px 9px!important}
.gaddwrap .gadd{display:block;text-decoration:none}

/* meal plan: day band, slot bands, plan rows, inline picker */
.daybar{display:flex;align-items:center;gap:12px;padding:9px 15px;
  background:var(--moss);color:#fff}
.daybar .dayname{font-weight:700;font-size:15px}
.daybar .daysum{flex:1;font-size:12px;color:#cdd9cf;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
/* In the dark family --moss is a LIGHT accent (#8fbfa0, #8fb2cf), so the band
   goes pale and white text on it measures ~2:1. Dark ink on the band there is
   over 8:1. The original never added this override; the rewrite is where it
   gets fixed. */
:root[data-dark] .daybar{color:#0e1a14}
:root[data-dark] .daybar .daysum{color:#20362b}
:root[data-theme="smokey"] .daybar{color:#0d1c28}
:root[data-theme="smokey"] .daybar .daysum{color:#21384a}
.slothead span:first-child{text-transform:uppercase}
.slothead .mealsum{font-size:11.5px}
.planitem .amt{display:flex;align-items:center;gap:4px;margin:0;flex:none}
.planitem .amt .wtin{width:56px}
.slotpick{display:flex;flex-direction:column;border-top:1px solid var(--hairline)}
.pickrow{background:none;border:0;border-bottom:1px solid var(--hairline);text-align:left;
  padding:8px 15px 8px 32px;font:inherit;font-size:13.5px;color:var(--ink);cursor:pointer}
.pickrow:hover{background:var(--hover)}
.pickrow em{font-style:normal;color:var(--dim);font-size:12.5px;margin-left:6px}
.pickrow.cancel{color:var(--dim);border-bottom:0}

/* the Food checks sit under the sub-tabs, on the panel's own paper */
.foodcheckrow{padding:12px 15px 0}
.foodcheckrow .mealcheck{margin:0 0 12px}

/* pantry: manual entry grid, the original's .manual verbatim; the filter reuses
   the Gear Room's .filterin. Dark themes give the block the theme's well colour. */
.manual{padding:11px 15px;border-top:1px solid var(--rule)}
.manual .grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-bottom:7px}
@media(max-width:560px){.manual .grid{grid-template-columns:repeat(2,1fr)}}
.manual input{width:100%;padding:6px 7px;border:1px solid var(--rule);
  border-radius:3px;font:inherit;font-size:13px;background:var(--field)}
.manual .cap{font-size:12px;color:var(--dim);margin-bottom:7px}
.manual .line{display:flex;gap:7px;flex-wrap:wrap}
html[data-dark] .manual{background:var(--well)}
.pantrywrap .addrow{padding:9px 15px;border-bottom:1px solid var(--rule)}

/* packing tab */
.bagrow{padding:11px 15px;border-bottom:1px solid var(--rule);font-size:13.5px;
  color:var(--dim);background:var(--soft)}
.bagrow form{display:flex;align-items:center;gap:8px;margin:0}
.bagrow .wtin{width:56px}
.bagfacts{text-align:right;flex:none;font-family:"Helvetica Neue",Arial,sans-serif}
.bagfacts b{display:block;font-size:14px}
.bagfacts em{font-style:normal;font-size:12px;color:var(--dim)}
.wizrow{padding:11px 15px;border-bottom:1px solid var(--rule);font-size:13px;
  color:var(--dim);background:var(--soft)}
.mealadd{display:flex;align-items:center;gap:6px;margin:0;flex:none}
.mealadd select{font:inherit;font-size:12.5px;padding:5px 6px;border:1px solid var(--rule);
  border-radius:3px;background:var(--card);color:var(--ink)}

/* kits empty state */
.kitempty{color:var(--ink);font-size:15px;line-height:1.6;max-width:64ch;margin:8px 2px}

/* readout: nudge box + Daily targets form (palette pinned like the readout) */
/* Body-stats prompt. One compact line at the FOOT of the summary, because it is
   per hiker: above the numbers it moved the whole panel 128px every time you
   switched people. The whole strip is the button — there is only one action. */
.nudge{display:block;width:100%;text-align:left;margin-top:16px;
  border:1px solid #b8862f;border-radius:6px;padding:9px 12px;background:transparent;
  font:inherit;font-size:13px;line-height:1.45;color:var(--ro-nudge);cursor:pointer}
.nudge:hover{background:var(--ro-hover)}
.tform{font-size:13px}
.tform .trow{display:flex;gap:14px;margin-bottom:12px;align-items:flex-end;flex-wrap:wrap}
.tform label{display:flex;flex-direction:column;gap:5px;font-size:12px;color:var(--ro-dim)}
.tform input,.tform select{background:var(--ro-line);border:1px solid var(--ro-edge);color:var(--ro-field-ink);
  border-radius:4px;padding:7px 9px;font:inherit;font-size:14px;width:74px}
.tform select{width:auto;min-width:96px}
.tform .tpair{display:flex;align-items:center;gap:5px}
.tform .tpair i{font-style:normal;color:var(--ro-mute);font-size:12px}
.tform .tpair input{width:52px}
.tform input[name=weight_lb]{width:74px}
.tform .trule{border-top:1px solid var(--ro-line);margin:14px 0}
.tform .tactions{display:flex;gap:8px;align-items:center;margin-left:auto}
.tform .tsave{background:var(--seg-base);border:1px solid var(--seg-base);color:#16201d;font-weight:600;
  padding:7px 14px;border-radius:4px;font:inherit;font-size:13.5px;cursor:pointer}
.tform .tsave:hover{background:#8fae95}
/* Suggest keeps the plain ghost look here too — the original leaves it white on the
   dark panel rather than tinting it to match the readout. */
.tform .tnote{color:var(--ro-mute);font-size:12px;line-height:1.5;margin-top:14px}
/* editable weight inputs stay compact like the original .wtlb/.wtoz */
.wtedit .wtin{width:44px;min-width:0;height:32px;padding-top:0;padding-bottom:0}
.wtedit .wtin.oz{width:64px}
/* every .wtin input carries the card palette itself — without this, inputs
   outside .wtbox (owned count, add-gear oz) fell back to the UA's white and
   went invisible in dark mode */
.wtin{text-align:right;padding:5px 7px;border:1px solid var(--rule);border-radius:3px;
  font:inherit;font-size:13.5px;font-weight:600;background:var(--card);color:var(--ink);
  font-family:"Helvetica Neue",Arial,sans-serif;min-width:0}
.mlabel input{width:100%}
/* build-a-meal form on the Meals tab */
.buildmeal{margin:0}
.buildmeal .bmrow{padding:12px 15px}
.buildmeal .bmrow input[type=text]{max-width:520px}
.buildmeal .gadd{display:block}
.bmpick{border-top:1px solid var(--hairline)}
/* Toast — the original's, top-centre with a draining countdown bar, so it reads
   as "on a timer" rather than "waiting for you". The original patched --ink/--paper
   back to dark in three themes; here --rink/--rpaper are already the always-dark
   pair the readout uses, so all seven schemes come out right with no overrides. */
.toast{position:fixed;left:50%;top:18px;transform:translate(-50%,-14px);
  background:var(--rink);color:var(--rpaper);padding:12px 22px;border-radius:6px;
  font-size:14px;font-weight:600;box-shadow:0 8px 24px rgba(22,32,29,.32);
  z-index:300;opacity:0;pointer-events:none;max-width:88vw;text-align:center;
  overflow:hidden;   /* clip the countdown bar to the rounded corners */
  transition:opacity .22s ease, transform .28s cubic-bezier(.3,.7,.4,1)}
.toast.show{opacity:1;transform:translate(-50%,0)}
/* leaving: drift UP and off, toward where the eye already is */
.toast:not(.show){transform:translate(-50%,-26px)}
/* scaleX animates on the compositor, and the duration is set inline per toast so
   the bar always matches that toast's real timeout */
.toastbar{position:absolute;left:0;right:0;bottom:0;height:3px;
  background:rgba(255,255,255,.55);transform-origin:left center;
  animation-name:toastdrain;animation-timing-function:linear;animation-fill-mode:forwards}
@keyframes toastdrain{from{transform:scaleX(1)}to{transform:scaleX(0)}}
/* --good/--over and --paper both flip per theme, so this pair always contrasts */
.toast.ok{background:var(--good);color:var(--paper)}
.toast.err{background:var(--over);color:var(--paper)}
/* Undo action inside a toast — the parent is pointer-events:none, so re-enable it */
.toast .toastundo{pointer-events:auto;margin-left:14px;background:transparent;
  border:1px solid currentColor;color:inherit;opacity:.85;padding:3px 12px;font-size:13px;
  font-weight:600;border-radius:4px;cursor:pointer}
.toast .toastundo:hover{opacity:1;background:rgba(127,127,127,.22)}
.toast .toastundo[disabled]{opacity:.5;cursor:default}
/* the spark in a toast: still for "ready", turning while a check runs */
.toast .cicon{vertical-align:-3px;margin-right:9px;flex:none}
.toast .cicon.spin{animation:aispin 1.1s linear infinite;transform-origin:50% 50%}
@media(prefers-reduced-motion:reduce){.toast .cicon.spin{animation:none}
  .toast{transition:opacity .2s ease}
  .toastbar{animation:none}}

/* Trip roster — who comes on this trip. One row per person on the account; the
   tick is membership, not existence, so unticking keeps their pack and plan. */
.roster{display:flex;flex-direction:column;gap:2px;margin:4px 0 16px}
.rosterrow{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:4px;
  font-size:14px;cursor:pointer}
.rosterrow:hover{background:var(--hover)}
.rosterrow input{width:16px;height:16px;flex:none;accent-color:var(--moss)}
/* a target the hiker set by hand, against the ones that follow their weight */
.tform input.mine{border-color:var(--ochre)}
.tnote.tderiv{margin:0 0 12px}

/* Add gear from a list — the original's glModal rows, values verbatim from
   static/pack-planner.html (.glcard … .glhint). The `#fff` field backgrounds
   became var(--card) so the dark schemes get their own ink, the way every other
   field in a dialog already does here. */
.modal.glcard{width:min(600px,100%)}
.glform textarea{width:100%;box-sizing:border-box;padding:9px;border:1px solid var(--rule);
  border-radius:4px;font:inherit;font-size:14px;background:var(--card);color:var(--ink);resize:vertical}
.glbtns{align-items:center}
.glbtns .aicost{margin-right:auto}
.glstatus{font-size:12px;color:var(--dim);margin:6px 0 0;min-height:16px}
.glstatus.err{color:var(--over)}
.glrows{margin-top:14px;max-height:46vh;overflow-y:auto;border-top:1px solid var(--rule)}
.glempty{font-size:13px;color:var(--dim);margin:12px 0 0}
.glrow{display:flex;align-items:center;gap:8px;padding:8px 2px;border-bottom:1px solid var(--rule)}
.glrow input.glname{flex:1 1 auto;min-width:80px;padding:6px;border:1px solid var(--rule);
  border-radius:4px;font:inherit;font-size:14px;background:var(--card);color:var(--ink)}
.modal .glrow input.gloz{width:62px;padding:6px;border:1px solid var(--rule);border-radius:4px;
  font:inherit;font-size:14px;background:var(--card);color:var(--ink);text-align:right}
/* one width for the group column, or each row's styled select sizes to its own
   label and the weight boxes stagger */
.glrow select.glgrp,.glrow .ssel{flex:0 0 138px;width:138px}
.glrow .sselbtn{padding:6px;font-size:13px;width:100%}
.glrow .glu{font-size:12px;color:var(--dim)}
.conf{font-size:11px;font-weight:600;padding:2px 6px;border-radius:10px;white-space:nowrap}
.conf.high{background:#e3ebe4;color:var(--good)}
.conf.medium{background:#f3ead6;color:var(--ochre)}
.conf.low{background:#f2ddd6;color:var(--over)}
.glhint{font-size:11px;color:var(--over);margin:2px 0 0 30px}
@media(max-width:640px){
  /* review rows wrap so the name field isn't crushed */
  .glrow{flex-wrap:wrap}
  .glrow input.glname{flex:1 1 100%;order:-1}
}

/* ======================= GUIDED TOUR (tour.js) ===========================
   Values verbatim from the original's block of the same name. Above every
   modal (100) on purpose: the tour may point at a control inside one. */
.tourmask{position:fixed;inset:0;z-index:500;background:transparent}
/* a centred step: the ring is a point, so only its dim shows — no ochre dot */
.tourring.none{box-shadow:0 0 0 9999px rgba(15,20,15,.55)}
/* the dim between pages, painted from <head> while a tour is in flight so the
   next page never shows a bright frame before tour.js has mounted its ring */
html.touring::before{content:"";position:fixed;inset:0;z-index:499;
  background:rgba(15,20,15,.55);pointer-events:none}
/* ONE dim at a time. While the coat is on, the ring carries no shadow of its
   own: two 55% washes stack to ~80%, which is the "darker, then lighter" Hans
   saw on every page change. The class flips both in the same paint, so the
   coat hands over to the ring's shadow with no frame darker or brighter. */
html.touring .tourring{box-shadow:0 0 0 3px var(--ochre)}
html.touring .tourring.none{box-shadow:none}
.tourring{position:fixed;z-index:501;border-radius:8px;pointer-events:none;
  box-shadow:0 0 0 9999px rgba(15,20,15,.55), 0 0 0 3px var(--ochre);
  transition:left .2s ease,top .2s ease,width .2s ease,height .2s ease}
/* The bubble is ONE object that travels, not a new one per step: it slides on
   the ring's own easing, keeps one width, and holds a floor height (measured:
   the thirteen pointing steps fall in 201–241px) with the controls
   pinned to its bottom edge — so Next is under the same spot of the thumb from
   step to step, and the eye has one moving thing to follow, not a box that
   teleports and resizes while the ring slides. */
.tourbubble{position:fixed;z-index:502;width:min(380px,92vw);min-height:240px;
  display:flex;flex-direction:column;
  background:var(--card);color:var(--ink);border:1px solid var(--rule);border-radius:8px;
  box-shadow:0 14px 38px rgba(0,0,0,.34);padding:15px 16px 12px;font-size:14px;line-height:1.5;
  max-height:min(78vh,560px);overflow:auto;
  transition:left .2s ease,top .2s ease}
/* a lede for the skimmer, the detail for the reader — the detail is the one
   that grows to pin the controls to the bottom */
.tourbubble .tourlede{margin:0 0 5px;font-weight:600;color:var(--ink)}
.tourbubble .tourbody{flex:1;font-size:13.5px;color:var(--dim)}
.tourbubble .tourbody b{color:var(--ink)}
.tourbubble h4{margin:0 0 6px;font-size:15.5px;color:var(--moss)}
.tourflowh{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--dim);margin:2px 0 5px}
.tourbubble ol.tourflow{margin:0 0 12px;padding-left:20px;font-size:13.5px}
.tourbubble ol.tourflow li{margin:4px 0;line-height:1.45}
.tourbubble ol.tourflow + .tourflowh{margin-top:16px;padding-top:13px;
  border-top:1px solid var(--rule)}
.tourbubble p{margin:0 0 11px}
.tourbubble b{color:var(--ink);font-weight:600}
.tourrow{display:flex;align-items:center;gap:8px}
.tourrow .grow{flex:1}
.tourrow+.tourrow{margin-top:8px}
.tourstep{font-size:12px;color:var(--dim)}
.tourbubble .tbtn2{padding:6px 14px;font-size:13.5px}
.tourskip{background:none;border:0;color:var(--dim);font-size:12.5px;cursor:pointer;
  text-decoration:underline;padding:2px 4px}
.tourskip:hover{color:var(--ink);background:none}
.readout .acctbtn#tourBtn{width:30px;padding:4px 0;text-align:center;font-weight:700;flex:none}
@media(prefers-reduced-motion:reduce){.tourring,.tourbubble{transition:none}}

/* ---- admin page — the original's admin.html, on the app's tokens ----------- */
.adminwrap{max-width:1120px;margin:0 auto;padding:20px 16px 80px}
.admintop{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:18px;
  padding-bottom:14px;border-bottom:1px solid var(--rule)}
.admintop h1{font-size:22px;color:var(--moss);margin:0}
.admintop .sp{margin-left:auto}
.adminwho,.adminwrap .sub{font-size:11.5px;color:var(--dim);font-weight:400}
.adminwrap > h2{font-size:14px;letter-spacing:.04em;text-transform:uppercase;color:var(--dim);
  margin:26px 0 12px}
.adminwrap .cards{display:flex;gap:14px;flex-wrap:wrap}
.adminwrap .card{background:var(--card);border:1px solid var(--rule);border-radius:8px;
  padding:14px 18px;min-width:150px;flex:1}
.adminwrap .card .n{font-size:30px;font-weight:600;color:var(--moss);
  font-family:"Helvetica Neue",Arial,sans-serif;line-height:1.1}
.adminwrap .card .n small{font-size:15px;color:var(--dim);font-weight:400}
.adminwrap .card .lab{font-size:12.5px;color:var(--dim);margin-top:3px}
.adminwrap .card.cost .n{color:var(--ochre)}
.adminwrap .card.warn{border-color:var(--over)} .adminwrap .card.warn .n{color:var(--over)}
.adminwrap .chartwrap{background:var(--card);border:1px solid var(--rule);border-radius:8px;
  padding:10px 12px 4px;margin-top:14px}
.adminwrap .chartwrap svg{width:100%;height:170px;display:block}
.adminwrap .chartwrap rect{fill:var(--ochre)}
.adminwrap .chartwrap line.axis{stroke:var(--rule)}
.adminwrap .chartwrap text{font-size:10px;fill:var(--dim);font-family:"Helvetica Neue",Arial,sans-serif}
.adminwrap .chartwrap text.empty{font-size:13px}
.adminwrap .note{font-size:12.5px;color:var(--dim);margin:10px 0 0;line-height:1.5}
.adminwrap .note a{color:var(--moss)}
.adminwrap .tablewrap{overflow-x:auto;background:var(--card);border:1px solid var(--rule);border-radius:8px}
.admintable{width:100%;border-collapse:collapse;font-size:13.5px}
.admintable th,.admintable td{padding:9px 12px;text-align:left;border-bottom:1px solid var(--rule);
  vertical-align:top}
.admintable th{font-size:11.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--dim);
  font-weight:600;background:var(--paper)}
.admintable tr:last-child td{border-bottom:none}
.admintable .num{text-align:right;white-space:nowrap}
.admintable tr.disabled td{opacity:.55}
.admintable.security{max-width:420px}
.admintable tr.quiet td{color:var(--dim)}
.logrow.fail b{color:var(--over)}
.admintable .email{font-weight:600}
.admintable .acts{display:flex;gap:5px;flex-wrap:wrap}
.admintable .acts form{display:inline}
.adminwrap button.mini{padding:3px 8px;font-size:12px}
.adminwrap button.danger{border-color:var(--over);background:var(--card);color:var(--over)}
.adminwrap button.danger:hover{background:var(--hover)}
.adminwrap button:disabled{opacity:.45;cursor:default}
.adminwrap button.ghost:disabled:hover{background:var(--card)}
.capform{display:flex;gap:4px;justify-content:flex-end;align-items:center}
.capform input.capin{width:4.5em;padding:3px 6px;border:1px solid var(--rule);border-radius:4px;
  background:var(--card);color:var(--ink);font:inherit;font-size:12.5px;text-align:right}
.capin.over{border-color:var(--over);color:var(--over)}
.pill{display:inline-block;font-size:10.5px;font-weight:600;padding:1px 7px;border-radius:10px;
  vertical-align:middle;letter-spacing:.02em}
.pill.admin{background:var(--moss-soft);color:var(--moss)}
.pill.on{background:var(--moss-soft);color:var(--good)}
.pill.off{background:var(--hover);color:var(--over)}
.adminlog,.faillist,.actlist{margin-top:14px;background:var(--card);border:1px solid var(--rule);
  border-radius:8px;padding:10px 14px}
.adminlog summary{cursor:pointer;font-size:13px;color:var(--moss);font-weight:600}
.logrow{font-size:12.5px;color:var(--dim);padding:5px 0;border-bottom:1px solid var(--rule)}
.logrow:last-child{border-bottom:none}
.logrow[hidden]{display:none}
.logfilter{display:flex;align-items:center;gap:10px;margin:8px 0 4px}
.logfilter input{flex:1;min-width:0;padding:6px 9px;border:1px solid var(--rule);border-radius:4px;
  font:inherit;font-size:13px;background:var(--paper);color:var(--ink)}
.logfilter input:focus{outline:none;border-color:var(--moss)}
.logcount{font-size:12px;color:var(--dim);white-space:nowrap}
.logrow b{color:var(--ink)}
.linkbox{width:100%;box-sizing:border-box;padding:9px;border:1px solid var(--rule);
  border-radius:4px;font:inherit;font-size:13px;background:var(--paper);color:var(--ink);margin-top:8px}

/* ---- admin: invite codes ---- */
.inviteform{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;margin:10px 0 14px}
.inviteform label{display:flex;flex-direction:column;gap:4px;font-size:12px;font-weight:600;color:var(--dim)}
.inviteform label small{font-weight:400}
.inviteform input{padding:6px 8px;border:1px solid var(--rule);border-radius:4px;background:var(--card);
  color:var(--ink);font:inherit;font-size:13.5px}
.inviteform input[name=count]{width:5em}
.inviteform input[name=email]{width:16em}
.inviteform input[name=label]{width:14em}
.invcode{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13.5px;letter-spacing:.06em;user-select:all;white-space:nowrap}
/* both admin tables are wider than a phone: scroll the table, never the page */
.tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.admintable .act{text-align:right;white-space:nowrap}
.admintable td.dim{color:var(--dim);white-space:nowrap}
@media (max-width:600px){.inviteform label{flex:1 1 100%}.inviteform input{width:100%!important}}

/* the phone's summary strip does not exist on a wide screen: the readout
   itself is sticky there (.side). The PHONE block below turns it on. */
.rostrip{display:none}

/* ============================== PHONE ==================================
   ONE breakpoint for the phone, 820px, and ONE block for its rules — add a
   phone rule here, not as a new @media beside the desktop rule (the sign-in
   page's block above 480 predates this and is the same width on purpose).
   Nothing here removes content: it reorders, wraps and enlarges. The desktop
   is the full experience; this is the compromise, and it is designed with
   every feature (CLAUDE.md, "Two screens"). Checked at 606px, Chrome's
   floor on this Mac, and at an emulated 391px (body zoom 1.55).

   The rules, each one a thing that was wrong on 2026-09-27:
   1. The page comes first, the readout after. The dark summary is 750px
      tall on a phone and every visit began with a scroll past it to reach
      the tabs and the list.
   2. A list row is two lines: the name, then its controls right-aligned.
      One line squeezed "Osprey Atmos 65" into three and put "the
      comfortable one" under the R-value box.
   3. A form row wraps, and its text field takes the whole first line. The
      Gear Room's add row had shrunk its name field to 20px.
   4. Sub-tabs never break a label ("Hans's meal plan" was three lines).
   5. A tap target is 32px or more. The × was 22 wide, the ? 27 tall.
   6. Nothing a person reads is under 12px.
   The probes: tools/polishprobe.js and tools/shiftprobe.js at 606, then
   `document.body.style.zoom='1.55'` and look for crushed text and overflow. */
@media(max-width:820px){
  /* 1. the readout stays on top, and once it has scrolled off, the strip:
     total / limit and the bar, fixed at the top edge, a tap away from the
     full panel. Fixed and translated off-screen until rostrip.js shows it,
     so it takes no space at first paint and nothing moves (shiftprobe).
     Hans, 2026-09-27: "it's always there but now you're in the main view". */
  .rostrip{display:flex;position:fixed;top:0;left:0;right:0;z-index:50;
    align-items:center;gap:10px;padding:8px 16px;padding-top:max(8px,env(safe-area-inset-top));
    background:var(--rink);color:var(--rpaper);border:0;border-bottom:1px solid var(--ro-line);
    box-shadow:0 4px 14px rgba(22,32,29,.28);font:inherit;text-align:left;cursor:pointer;
    border-radius:0;   /* a button, so 3px corners by default — square, or the
                          screen's own corner shows through at the top edge */
    transform:translateY(-100%);transition:transform .18s ease}
  .rostrip[hidden]{display:flex}          /* the attribute is the state; the transform is the look */
  .rostrip:hover{background:var(--rink)}  /* or the bare button:hover (0,1,1) paints it moss */
  .rostrip.show{transform:none}
  .rostrip .rsnum{font-size:15px;white-space:nowrap;color:var(--ro-text)}
  .rostrip .rsnum b{font-size:19px;font-weight:600;color:var(--ro-gold)}
  .rostrip.over .rsnum b{color:#f0a48f}
  .rostrip .rshead{font-size:12px;color:var(--ro-dim);white-space:nowrap}
  .rostrip.over .rshead{color:#f0a48f}
  .rostrip .segbar{flex:1;min-width:60px;margin:0;height:6px}
  /* Hans, 2026-09-27, from his phone on the Goat Rocks trip: the section
     description ("Pad, bag, pillow — check what you carry") leaves the
     weight no room and the header two lines tall. His call: the phone
     forgoes that line — the first thing the phone drops on purpose. The
     desktop keeps it. */
  .ghead .sub{display:none}
  /* 7. A state change never moves what is below it. A hold adds "+2 lb 13 oz
     on hold" to the section header; inline beside a two-line header it
     dropped everything under it by 18px — while the person was looking at
     that row. The first fix reserved a 16px band under every header for
     the note, and with the description gone that band was the blank strip
     Hans saw under "Sleep system" (8. below). So instead the header is ONE
     line, always: the title never wraps — it is clipped with an ellipsis
     when a hold note needs the room, a phone compromise — and the weight
     never shrinks, so the note appears on the line and nothing moves. The
     hold button keeps the width of its wider label ("on hold") so the
     weight boxes beside it do not slide when the word changes. */
  .ghead > div:first-child{min-width:0}
  .ghead h2{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ghead .gsum{flex:none}
  .holdbtn{min-width:68px;text-align:center}
  /* 8. A box is no taller than what is in it. No band, padding or margin
     reserved for a line the phone dropped or a note that is not there —
     what the phone gives up in words it must get back in height. The
     card gap was the desktop's 20px; on a phone 12px still reads as a gap.
     tests/browser/test_phone_vspace.py measures every block for this. */
  section.group{margin-bottom:12px}
  .gearbar{margin:10px 0}
  .gearbar .sp{display:none}   /* wrapped to an empty 10px row under the lead line */
  .roompointer{margin:12px 0 6px}
  /* while the strip is showing, the toast drops below it instead of landing
     on top of the number it is about (the strip is 46px + the safe area) */
  body:has(.rostrip.show) .toast{top:calc(env(safe-area-inset-top,0px) + 58px)}
  /* 2. list rows: name line, controls line */
  ul.items li{flex-wrap:wrap;row-gap:6px;justify-content:flex-end}
  /* the name's basis leaves room for the drag handle and the checkbox and
     nothing else, so ALL the controls go to line two together — a basis of
     55% let a narrow R-value box stay up beside the name while the weight
     dropped, and the row read as two different layouts */
  ul.items li .nm{flex:1 1 calc(100% - 64px)}
  ul.items li > form,ul.items li > .holdbtn,ul.items li > .rm,
  ul.items li > .wt,ul.items li > .spec{flex:0 0 auto}
  /* the meal-plan row has its amounts BEFORE the name; put the name first
     so the row reads the same as a gear row */
  .planitem .drag{order:-2}
  .planitem .nm{order:-1;flex:1 1 55%}
  /* 3. form rows wrap; the text field gets the line */
  /* the add FORM shares its row with three buttons at basis 0, so it got the
     50px left over; on a phone it takes the line and the buttons follow */
  .addrow > .addform{flex:1 1 100%;flex-wrap:wrap}
  .addform{flex-wrap:wrap}
  .addform input:not(.wtin){flex:1 1 100%}   /* the name field, typed or not */
  .aiform .askabout{flex:1 1 100%}
  /* 4. sub-tabs keep their words */
  .ptabs{flex-wrap:wrap;row-gap:4px}
  .ptab{white-space:nowrap}
  /* 5. tap targets */
  .rm{min-width:32px;min-height:32px}
  .readout .acctbtn#tourBtn{width:32px;height:32px;padding:0}
  .kitaddbtn{min-height:32px}
  /* 6. legible small print */
  .readout .tcard .tsub,.taken,.conf,.askmeta,.sselbtn .sselcar{font-size:12px}
}
