:root{
  --jade:#00A878; --teal:#079A9A; --lake:#008FD0; --deep:#0B6E99;
  --give:#00875F; --want:#0077B6; --ink:#17323B; --muted:#5A7180;
  --line:#DCE8EC; --bg:#FFFFFF; --soft:#F2F8F9;
  /* Gradient TEXT stops (m5): the action range #00875F -> #0077B6,
     every stop >= 4.5:1 on white. Graphics (wallet card) keep the
     bright --jade/--teal/--lake gradient above. */
  --grad-text:linear-gradient(90deg,#00875F,#07838B,#0077B6);
}
/* Type scale (P6): hero 40/800 · h1 24/700 · h2 18/700 · body 15/400 ·
   meta 13/400 · price 16/800. Weight 800 is reserved for the wordmark,
   hero, prices and the wallet balance. */
*{box-sizing:border-box}
body{margin:0;font-family:-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:var(--ink);background:var(--bg);line-height:1.5}
/* V8: the bar is position:fixed, not sticky — sticky failed in
   Floyd's in-app webview (the bar scrolled away with the page and
   the nav ended up rendered at the page's bottom area). Fixed is
   honoured in every scroll context. #topbar-spacer below reserves
   the bar's height in normal flow; app.js (syncTopbar) keeps the
   spacer — and the --topbar-h variable — equal to the bar's real
   measured height. The CSS default for both is 73px, the exact
   header-only height of the logged-out bar the page markup starts
   in (nav hidden): header padding 24 + brand block 48 + border 1.
   Logged in, the nav adds 45px (44px buttons + border) = 118px. */
.topbar{position:fixed;top:0;left:0;right:0;background:#fff;z-index:6}
#topbar-spacer{height:73px}
header{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:12px 16px;border-bottom:1px solid var(--line);background:#fff}
.brand{display:flex;align-items:center;gap:10px}
.brand-icon{width:40px;height:40px;border-radius:10px}
.brand-name{font-weight:800;font-size:20px;background:var(--grad-text);-webkit-background-clip:text;background-clip:text;color:transparent}
.brand-tag{color:var(--deep);font-size:12px;font-weight:600;letter-spacing:.4px}
.top-links{display:flex;align-items:center;gap:10px;font-size:14px}
.linklike{background:none;border:none;color:var(--want);font-size:15px;cursor:pointer;padding:4px}
.top-links .linklike{min-height:44px;display:inline-flex;align-items:center;padding:6px 8px}
main{max-width:860px;margin:0 auto;padding:16px}
main:has(> #view-explore:not(.hidden)){max-width:1200px}
h1{font-size:24px;font-weight:700;margin:8px 0 10px}
h2{font-size:18px;margin:22px 0 8px}
h3{margin:14px 0 4px;font-size:16px}
.muted{color:var(--muted)} .small{font-size:13px}
.hidden{display:none!important}
.card{border:1px solid var(--line);border-radius:14px;padding:16px;background:#fff;margin:10px 0}
label{display:block;margin:10px 0;font-size:14px;font-weight:600}
input,select,textarea{width:100%;margin-top:4px;padding:10px;border:1px solid var(--line);border-radius:10px;font-size:15px;font-weight:400;background:#fff}
.btn{border:none;border-radius:12px;padding:11px 18px;font-size:15px;font-weight:700;color:#fff;cursor:pointer}
.btn.green{background:var(--give)} .btn.blue{background:var(--want)}
.btn.ghost{background:var(--soft);color:var(--ink);border:1px solid var(--line)}
.btn.small{padding:7px 12px;font-size:13px;border-radius:9px}
.btn.danger{background:#B3261E}
.btn.google{background:#fff;color:var(--ink);border:1px solid var(--line);width:100%;display:flex;align-items:center;justify-content:center;gap:10px}
.btn.google .g-mark{font-weight:800;font-size:17px;color:var(--lake)}
.or-row{display:flex;align-items:center;gap:10px;color:var(--muted);font-size:12px;margin:12px 0 2px}
.or-row::before,.or-row::after{content:'';flex:1;border-top:1px solid var(--line)}
.btn.big{flex:1;padding:16px;font-size:18px}
.hero{text-align:center;padding:30px 4px 12px}
.hero-name{font-size:40px;font-weight:800;margin:0;background:var(--grad-text);-webkit-background-clip:text;background-clip:text;color:transparent}
.hero-slogan{font-size:21px;font-weight:700;color:var(--deep);margin:8px 0 10px}
.hero-mission{font-weight:700;color:var(--deep);margin:10px 0 0}
.hero-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:20px}
.hero-actions .btn{flex:1;min-width:220px}
.steps-list{margin:6px 0;padding-left:22px}
.steps-list li{margin:9px 0}
.back-row{margin:0 0 4px}
.tabs{display:flex;gap:8px;margin-bottom:8px}
.tab{flex:1;padding:9px;border-radius:9px;border:1px solid var(--line);background:var(--soft);cursor:pointer;font-weight:600}
.tab.active{background:var(--deep);color:#fff;border-color:var(--deep)}
.note{border-radius:10px;padding:10px 12px;background:#FFF4E0;border:1px solid #F0D9A8;font-size:14px;white-space:pre-line}
.search-row{display:flex;flex-direction:column;gap:8px}
#view-explore .search-row{position:sticky;top:var(--topbar-h,118px);background:#fff;z-index:4;padding:10px 0 8px}
.chips{display:flex;gap:8px}
.chip{border:1px solid var(--line);background:#fff;border-radius:999px;padding:6px 14px;cursor:pointer;font-size:14px}
.chip.active{background:var(--deep);color:#fff;border-color:var(--deep)}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:14px;margin-top:14px}
.tile{border:1px solid var(--line);border-radius:14px;overflow:hidden;cursor:pointer;background:#fff}
.tile-img{aspect-ratio:4/3;background:var(--soft);display:flex;align-items:center;justify-content:center;overflow:hidden}
.tile-img img{width:100%;height:100%;object-fit:cover}
.tile-img.noimg{flex-direction:column;gap:2px;color:var(--give)}
.tile-img.noimg .ph-letter{font-size:30px;font-weight:700;line-height:1.1}
.tile-img.noimg .ph-cat{font-size:12px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--muted)}
.tile-body{padding:12px}
.tile-title{font-weight:700;margin-bottom:2px}
.tile-meta{font-size:13px;color:var(--muted)}
.tile-trust{font-size:13px;color:var(--deep);margin-top:2px}
.trust-line{margin:6px 0}
.price{font-weight:800;color:var(--deep);font-size:16px}
.row{border:1px solid var(--line);border-radius:12px;padding:12px;margin:8px 0;background:#fff}
.row-head{display:flex;justify-content:space-between;gap:10px;align-items:baseline}
.row-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.badge{display:inline-block;font-size:12px;font-weight:700;padding:2px 8px;border-radius:999px;background:var(--soft);color:var(--deep)}
.badge.warn{background:#FFF4E0;color:#8A5A00}
.badge.bad{background:#FDECEA;color:#B3261E}
.wallet-card{border-radius:16px;padding:20px;color:#fff;background:linear-gradient(120deg,var(--jade),var(--teal),var(--lake))}
.wallet-balance{font-size:34px;font-weight:800}
.wallet-sub{opacity:.92;font-size:14px;margin-top:4px;white-space:pre-line}
.msg{border-top:1px solid var(--line);padding:8px 0;font-size:14px}
.msg b{color:var(--deep)}
footer{text-align:center;color:var(--deep);font-weight:600;padding:18px 10px 8px}
footer a{color:var(--want);text-decoration:none}
footer a:hover{text-decoration:underline}
footer .legal-links{font-size:14px;margin-top:2px}
footer .legal-links a{display:inline-block;padding:13px 8px;min-height:44px}
.trust-strip{display:flex;flex-wrap:wrap;gap:6px 22px;justify-content:center;border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:12px 8px;margin:16px 0 8px;font-size:14px;font-weight:600;color:var(--deep)}
.proof-line{text-align:center;font-weight:700;color:var(--deep);margin:6px 0 2px}
.empty-state{margin-top:14px}
:focus-visible{outline:3px solid var(--want);outline-offset:2px;border-radius:4px}
#bottom-nav{display:flex;background:#fff;border-bottom:1px solid var(--line)}
#bottom-nav button{flex:1;background:none;border:none;padding:13px 2px;min-height:44px;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer}
#bottom-nav button.active{color:var(--deep)}
/* V10: at >=900px the fixed bar becomes ONE row — brand left, nav
   centred, account actions right — instead of header stacked over
   nav (118px tall logged in). Under 900px the bar is one row too,
   with the nav behind a menu button (Floyd's one-bar rule — see
   the max-width:899px block below). The <header> becomes display:contents so
   its two children (.brand, .top-links) join the bar's grid
   directly, and the bar takes over the header's padding and bottom
   hairline. syncTopbar() measures the bar's offsetHeight, so the
   spacer and --topbar-h follow the new height automatically.
   Logged out at >=900px the member nav is hidden and its middle
   grid cell would sit empty, so two quiet landing links take it
   instead (anchor-scroll to the sections below); the :has rule
   shows them exactly while #bottom-nav carries .hidden — the same
   condition app.js uses for logged-out — and the nav replaces
   them the moment a member logs in. */
.landing-links{display:none}
@media (min-width:900px){
  .topbar{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:16px;padding:12px 16px;border-bottom:1px solid var(--line)}
  .topbar header{display:contents}
  .topbar .brand{grid-column:1;grid-row:1;justify-self:start}
  .topbar .top-links{grid-column:3;grid-row:1;justify-self:end}
  #menu-btn{display:none}
  /* grid-row:1 is load-bearing: the middle items come after
     .top-links in DOM order, and grid auto-placement would push
     them to row 2 (the V10 QA caught exactly that). */
  #bottom-nav{grid-column:2;grid-row:1;justify-self:center;border-bottom:none}
  #bottom-nav button{flex:none;padding:13px 14px}
  .landing-links{grid-column:2;grid-row:1;justify-self:center;align-items:center;gap:6px}
  .topbar:has(#bottom-nav.hidden) .landing-links{display:flex}
}
/* V10 (Floyd's one-bar rule): under 900px the bar is also ONE row —
   logo left, actions right — and the five nav choices collapse
   behind the "☰ Menu" button into a dropdown panel directly under
   the bar. The panel is absolutely positioned against the fixed
   bar, so it overlays the page: the bar's closed height (header
   only, 73–91px) is all the spacer ever reserves, open or closed.
   The nav's .hidden class (logged out) still wins over every rule
   here, and app.js only shows the menu button when logged in. */
@media (max-width:899px){
  /* One row has to fit ~358px: the brand keeps its icon + name
     (the tagline lives in the hero), the "Hi, name" greeting goes
     (Log out already says you're in), and the gaps/padding slim
     down. Measured result: a ~73px bar at 360–390px. */
  .brand{flex:none}
  .brand-tag{display:none}
  #whoami{display:none}
  header{gap:8px}
  .top-links{gap:6px}
  .top-links .linklike{padding:6px 5px}
  #bottom-nav{position:absolute;top:100%;left:0;right:0;flex-direction:column;display:none;box-shadow:0 14px 28px rgba(10,30,40,.14);z-index:7}
  .topbar.menu-open #bottom-nav{display:flex}
  #bottom-nav button{flex:none;width:100%;text-align:left;padding:14px 16px;min-height:48px;font-size:15px;border-top:1px solid var(--line)}
  #bottom-nav button:first-child{border-top:none}
  #bottom-nav button.active{background:var(--soft)}
}
.landing-links a{color:var(--ink);text-decoration:none;font-size:15px;min-height:44px;display:inline-flex;align-items:center;padding:10px 12px}
.landing-links a:hover{text-decoration:underline}
/* Anchor targets must land below the fixed bar, not behind it. */
#how-it-works,#what-can-be-exchanged{scroll-margin-top:calc(var(--topbar-h,73px) + 16px)}
#toast{position:fixed;left:50%;transform:translateX(-50%);bottom:24px;background:var(--ink);color:#fff;padding:11px 16px;border-radius:10px;font-size:14px;z-index:20;max-width:88vw;text-align:center}
#sheet{position:fixed;inset:0;background:rgba(10,30,40,.45);z-index:15;display:flex;align-items:flex-end;justify-content:center}
.sheet-card{background:#fff;width:100%;max-width:640px;max-height:88vh;overflow:auto;border-radius:18px 18px 0 0;padding:18px}
.sheet-img{aspect-ratio:16/9;border-radius:12px;background:var(--soft);display:flex;align-items:center;justify-content:center;overflow:hidden}
.sheet-img.noimg{flex-direction:column;gap:2px;color:var(--give)}
.sheet-img.noimg .ph-letter{font-size:40px;font-weight:700;line-height:1.1}
.sheet-img.noimg .ph-cat{font-size:12px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--muted)}
.sheet-img img{width:100%;height:100%;object-fit:cover}
.inline{display:flex;gap:8px} .inline input{flex:1}
/* Listing photos: the file inputs are never painted — display:none
   is the only reliable hide. (V7 used a 1px/opacity rule; iOS still
   painted the native "Choose File / no file selected" control at
   the page bottom — Floyd's screenshot, V8.) Activation does not
   need the input visible: the Give form's control is a <label
   for>, and the listings' Add/Change photo buttons call .click()
   from inside real tap handlers — both fire a display:none input
   in every modern browser, proven by the V8 device-matrix smoke
   (~/workspace/qa/trocaly-v8-matrix.mjs), which instruments click
   listeners on both inputs and clicks the styled controls. */
.file-hidden{display:none}
.photo-field{margin:2px 0 4px}
.photo-add{display:flex;align-items:center;gap:14px;margin:0;border:2px dashed var(--line);border-radius:14px;padding:14px;background:var(--soft);color:var(--deep);font-size:16px;cursor:pointer;min-height:44px}
.photo-add img{width:64px;height:64px;border-radius:10px;object-fit:cover;flex:none}
.photo-add:active{background:#E7F2F4}
table.log{width:100%;border-collapse:collapse;font-size:13px}
table.log td,table.log th{border-bottom:1px solid var(--line);padding:6px 4px;text-align:left;vertical-align:top}
