/* ==========================================================================
   assets/css/page-profile.css — Profile + Menu (builder B4)
   Owner: this file only (profile.php, menu.php). Loaded AFTER
   assets/css/brutal-lite.css + brutal-lite-web.css + legacy-pages.css +
   lite-tabs.css on profile.php only (menu.php keeps loading
   assets/css/lite-profile.css for its own, not-rebuilt-this-round, look —
   see that file's own remaining header comment).

   References (Brutal Lite v3.1): lite5/profile-preview.html (creator, the
   VISITOR's view — the owner sees the same classes with Edit profile instead
   of Follow), lite5/user-profile-preview.html (a normal user, public by
   default), lite5/user-profile-hidden-preview.html ("This one's kept
   private."). Class names below are copied from those three files' own
   <style> blocks; this is the v3.1 rebuild of what used to be
   assets/css/lite-profile.css's .prof-* classes (same ideas, renamed to
   match the reference instead of a one-off prefix).

   Real-site notes (vs. the static preview files):
   - No fake iPhone status bar — real browser, safe-area aware.
   - The map banner is a real MapLibre map (assets/js/map-explore.js's own
     restyle + pin-element builder, reused in a non-interactive "banner"
     mode — see .map-header__banner / .map-header__gen), not the reference's
     decorative mock SVG + photo pins. Same colours/pins as Explore so every
     map on the site looks the same (rules §2.1/§6.8).
   - .page's own top padding (brutal-lite-web.css: 58px + safe-area) would
     leave a white strip above a full-bleed banner, so it's zeroed just for
     this page (body.profile-page .page{padding-top:0}), the same fix
     builder B1 used for the Intro screen — not a negative-margin trick
     fighting that padding. .map-header only needs to break out of the
     16px side padding now.
   - Real extra features the reference doesn't show at all (not a conflict —
     the reference is a generic mockup, these are real, working product
     surfaces kept from the previous pass): the owner's "Your places" quick
     row (.prof-places), the "Become a Creator" card (.creq-card), and the
     owner's pin manager overlay (.vcard__mgmt).
   ========================================================================== */

/* .page's padding-top is zeroed (not fought with a negative margin) so the
   map-header can be truly full-bleed from y=0, like the reference — same
   fix as page-onboard-intro.css's .ob-intro.lite-page{padding:0}. Specificity
   ties with brutal-lite-web.css's `.lite-v31 .page` via the extra `body`
   element selector, so this wins regardless of load order too. */
/* v272: + .lite — lite-tools.css `body.lite .page` (18px top) tied and won on load order */
body.profile-page.lite .page{ padding-top:0; }

/* ---------- map banner (real MapLibre map, assets/js/map-explore.js) ---------- */
.map-header{
  position:relative; width:calc(100% + 32px); height:220px; background:var(--card-2); overflow:hidden;
  margin:0 -16px 0;
}
.map-header--creator{ height:230px; }
.map-header__banner,.map-header__gen,.map-header__fallback{ position:absolute; inset:0; width:100%; height:100%; }
/* v151: static backdrop (lite5/profile-preview.html's own SVG shapes) sits behind the
   real map at all times; the map fades in on top once it's actually drawn something
   (profile.php's "is-ready" toggle), so a slow/failed map never leaves a blank grey
   box — the banner always looks like the approved design. */
.map-header__fallback{ z-index:0; }
.map-header__fallback svg{ width:100%; height:100%; display:block; }
.map-header__banner{ z-index:1; opacity:0; transition:opacity .4s ease; }
.map-header__banner.is-ready{ opacity:1; }
/* saved map pictures: the picture (fallback) IS the tap target until the live map is in */
.map-header__banner:not(.is-ready){ pointer-events:none; }
.map-header__fallback[data-map-tap][role="button"]{ cursor:pointer; -webkit-tap-highlight-color:transparent; }
.map-header__fallback:focus-visible{ outline:3px solid var(--blue,#2f6bff); outline-offset:-3px; }
/* credit bottom-right, clear of the avatar that overlaps the banner's bottom-left (wraps to 2 lines on narrow phones) */
.map-header .mapshot__credit{ top:auto; bottom:4px; right:4px; max-width:calc(100% - 136px); white-space:normal; text-align:right; }
.map-hint{ position:absolute; z-index:4; right:12px; bottom:14px; display:inline-flex; align-items:center; gap:5px; height:26px; padding:0 10px;
  border-radius:999px; background:rgba(255,255,255,.92); border:1.5px solid var(--ink,#141518); color:var(--ink,#141518);
  font:700 11.5px/1 var(--font-ui,'DM Sans',system-ui,sans-serif); pointer-events:none; box-shadow:var(--sh-sm,2px 2px 0 #141518); }
.mapshot ~ .map-hint{ bottom:38px; }   /* above the (up to 2-line) map credit */
.map-hint[hidden]{ display:none; }
.map-hint .ph-spinner{ animation:mapTapSpin 1s linear infinite; }
@media (prefers-reduced-motion:reduce){ .map-hint .ph-spinner{ animation:none; } }
@media (prefers-reduced-motion:reduce){ .map-header__banner{ transition:none; } }
.map-header__gen{ display:flex; align-items:center; justify-content:center; background:var(--card-2); }
.map-header__gen svg{ width:100%; height:100%; }
/* map-explore.js's own photo-sticker pin element + collision/highlight states (rules
   §6.8: round photo, 2.5px ink border, 2px hard shadow, black name tag) — identical
   copy of lite-explore.css's `body.lite-fullbleed .sm-pin*` rules (Explore's own map),
   just rescoped to `.map-header` since this page doesn't carry that body class. Kept in
   lock-step with that file on purpose so every map on the site looks the same. */
/* v153: markers MUST stay position:absolute (MapLibre places them by transform) — the old
   position:relative here out-ranked .maplibregl-marker and stacked pins down the banner. */
.map-header .sm-pin-wrap{ position:absolute; }
.map-header .sm-pin{ display:flex; flex-direction:column; align-items:center; width:72px; }
.map-header .sm-pin__photo{
  width:42px; height:42px; margin:0 auto; border-radius:50%; border:2.5px solid var(--ink); box-shadow:var(--sh-sm);
  background-size:cover; background-position:center; display:flex; align-items:center; justify-content:center;
}
.map-header .sm-pin--featured .sm-pin__photo{ border-color:var(--ink); border-width:2.5px; box-shadow:0 0 0 3px var(--yellow), var(--sh-sm); }
.map-header .sm-pin__name{
  margin-top:5px; max-width:110px; background:var(--ink); color:#fff; font:700 10.5px/1 var(--font-ui); padding:4px 7px;
  border-radius:7px; border:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; text-align:center;
}
.map-header .sm-pin--featured .sm-pin__name{ background:var(--ink); color:var(--yellow); }
.map-header .sm-pin__tail{ display:none; }
.map-header .sm-pin__ph{ color:var(--muted); }
.map-header .sm-pin-wrap.sm-pin--circle-hidden{ opacity:0!important; pointer-events:none!important; }
.map-header .sm-pin-wrap.sm-pin--label-hidden .sm-pin__name{ visibility:hidden; }
.map-header .sm-pin-wrap.sm-pin--active .sm-pin__photo{ transform:scale(1.14); box-shadow:0 0 0 3px var(--yellow), var(--sh-sm); }
.map-header .sm-userdot{ width:16px; height:16px; border-radius:50%; background:var(--blue); border:3px solid #fff; box-shadow:0 2px 6px rgba(20,21,24,.3); }
.map-top{ position:absolute; top:calc(14px + var(--sat,0px)); left:16px; right:16px; display:flex; align-items:flex-start; justify-content:space-between; z-index:30; }
.map-top-right{ display:flex; gap:10px; position:relative; }
.map-header .icon-btn{ box-shadow:none; }

/* ---------- identity block ---------- */
.identity{ position:relative; padding:0 2px; z-index:2; }
.avatar-wrap{ margin-top:-40px; margin-bottom:10px; width:84px; height:84px; }
.avatar-wrap img{ width:84px; height:84px; border-radius:50%; object-fit:cover; border:var(--bd); box-shadow:none; background:var(--card-2); display:block; }
.avatar-wrap__ph{ width:84px; height:84px; border-radius:50%; border:var(--bd); background:var(--card-2); display:flex; align-items:center; justify-content:center; color:var(--muted-2); font-size:34px; }
.name-line{ display:flex; align-items:center; gap:7px; font:800 24px/1.1 var(--font-display); color:var(--ink); min-width:0; }
.name-line .nm{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; }
.name-line i{ color:var(--blue); font-size:18px; flex:0 0 auto; }
.handle-line{ font:600 13.5px/1 var(--font-ui); color:var(--muted); margin-top:4px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; }
.loc-line{ font:600 12.5px/1 var(--font-ui); color:var(--muted); margin-top:10px; }
/* v262 fix, kept for Medals & Tags: a long badge name shouldn't push a chip past the
   viewport edge and cause horizontal page scroll — cap it like the other identity lines.
   (.badge-row/.badge-chip layout + colour rules live in partials/badge_sheet.php.) */
.badge-chip{ max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.badge-chip i{ flex:0 0 auto; }
.stats-row{ display:flex; gap:22px; margin:16px 0; }
/* plain text stats, no boxed card — app.css's generic ".stat" card rule (hard shadow)
   would otherwise draw a stray box behind the number */
.stats-row .stat{ background:none; border:0; border-radius:0; box-shadow:none; padding:0; text-align:left; min-width:0; flex:0 0 auto; }
.stats-row .stat b{ font:800 16px/1 var(--font-display); color:var(--ink); display:block; }
.stats-row .stat span{ font:600 11.5px/1 var(--font-ui); color:var(--muted); white-space:nowrap; }
.profile-actions{ display:flex; gap:10px; margin-bottom:16px; }
.profile-actions .btn{ flex:1; height:48px; }
/* every icon-btn in this row (owner's Share, ig-btn, more-btn) stays calm — the row's
   one btn-brand (Edit profile / Follow / Share profile) is the only hard shadow allowed
   on this screen (rules §1 MUST-4); Appendix A's .icon-btn.ink-ring carries a 2px hard
   shadow by default, which this turns back off. width/height match the 48px-tall brand
   button next to it (Appendix A's .icon-btn{44px !important} still wins the a11y
   minimum, so this is a floor, never a shrink). */
.profile-actions .icon-btn{ flex:0 0 auto; width:48px !important; height:48px !important; box-shadow:none; }

/* assets/css/brutal.css (the pre-strict v2 system, still loaded on every $lite page for
   not-yet-rebuilt pages) has its own `.btn{box-shadow:var(--sh-sm)}` base rule that
   Appendix A's `.btn-ghost` never explicitly cancels, so a plain `.btn.btn-ghost` (the
   owner's "Drafts" button here) silently keeps a hard shadow it shouldn't have — a
   second one next to "Edit profile"/"Add pin", breaking the one-shadow rule. This is a
   wider gap (any `.btn-ghost` on any not-yet-rebuilt $lite page has it), out of scope to
   fix everywhere from here, but turned off on this page's own ghost buttons. */
.btn-ghost{ box-shadow:none; }
.link-chips{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:16px; }
.link-chips .chip{ text-decoration:none; }
.link-chips .chip i{ color:var(--blue); }

/* ---------- owner-only "Your places" quick row (real feature, not in the reference) ---------- */
.prof-places{ display:flex; gap:8px; overflow-x:auto; margin:0 0 16px; scrollbar-width:none; }
.prof-placebtn{
  flex:0 0 auto; display:flex; flex-direction:column; align-items:flex-start; gap:4px; min-width:112px;
  padding:12px 13px; border-radius:var(--r-card); background:var(--card-2); text-decoration:none; color:var(--ink);
}
.prof-placebtn i{ font-size:17px; }
.prof-placebtn span{ font:700 11.5px/1.2 var(--font-ui); color:var(--muted); }
.prof-placebtn b{ font:800 18px/1 var(--font-display); color:var(--ink); }
.prof-private-note{
  display:flex; align-items:center; gap:8px; font-size:13px; color:var(--muted); background:var(--card-2);
  border-radius:var(--r-ctl); padding:11px 13px; margin:0 0 16px;
}
.prof-private-note.is-hidden-note{ color:var(--muted); }

/* ---------- "Become a Creator" card (real feature, not in the reference) ---------- */
.creq-card{ margin-top:0; }
body .creq-card.card.pad{ padding:16px !important; }   /* v234: lite-v31 .card{padding:0} reset was winning */
.creq-summary{ cursor:pointer; font:700 14px/1.4 var(--font-ui); color:var(--ink); list-style:none; }
.creq-summary::-webkit-details-marker{ display:none; }
.creq-summary b{ font-weight:800; }
.creq-reqs{ list-style:none; margin:0 0 14px; padding:0; display:flex; flex-direction:column; gap:6px; font-weight:600; color:var(--ink); }
.creq-reqs li{ display:flex; align-items:flex-start; gap:8px; }
.creq-reqs i{ flex:0 0 auto; font-size:15px; margin-top:1px; color:var(--blue) !important; }

/* ---------- Pins grid (creator / own page) — owner's manage overlay on each vcard ---------- */
.vcard.is-inactive .vcard__media{ opacity:.55; }
.vcard{ position:relative; }
/* v153: the <a> wraps photo + place name, so .vcard's own gap never reached the name —
   give the link the same column gap. Manage buttons stack down the right edge at 32px
   (the global 44px !important tap rule made three of them cover the views sticker). */
.vcard > a{ display:flex; flex-direction:column; gap:8px; }
.vcard__place{ padding:0 2px; }
.vcard__mgmt{ position:absolute; top:8px; right:8px; z-index:3; display:flex; flex-direction:column; gap:6px; }
.vcard__mgmt .icon-btn{ width:32px !important; height:32px !important; font-size:15px; box-shadow:none; } /* calm — the Edit-profile button above is this screen's one hard shadow */
.vcard .sticker.tl{ position:absolute; top:8px; left:8px; z-index:2; width:max-content; max-width:calc(100% - 56px); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* ---------- Moments grid (normal user's page) — user-profile-preview.html ---------- */
.moments-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:4px; }
.m-tile{ position:relative; aspect-ratio:1/1; border-radius:9px; overflow:hidden; background:var(--card-2); display:block; }
.m-tile img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.m-tile .scrim{ position:absolute; left:0; right:0; bottom:0; height:52%; background:linear-gradient(transparent,rgba(0,0,0,.68)); }
.m-tile .place{
  position:absolute; left:6px; right:6px; bottom:5px; color:#fff; font:700 10px/1.2 var(--font-ui);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; z-index:2;
}
.m-tile .more{
  position:absolute; top:6px; right:6px; z-index:3; background:rgba(0,0,0,.55); color:#fff; border-radius:999px;
  padding:2px 7px; font:800 10px/1 var(--font-ui);
}

/* ---------- empty states ---------- */
.empty-moment{ text-align:center; padding:32px 20px; color:var(--muted); }
.empty-moment-ico{ font-size:28px; color:var(--muted-2); margin-bottom:10px; }
.empty-moment-title{ font:700 14px/1.4 var(--font-ui); color:var(--ink); margin-bottom:4px; }
.empty-moment .btn{ margin-top:12px; }

/* ---------- ⋯ menu: anchored popover (profile-preview.html / user-profile-preview.html's
   .menu-pop / .menu-item / .menu-divider, copied as-is) — under map-top-right, which is
   already position:relative. Both ⋯ buttons (top, and the normal-user profile-actions
   one) toggle this same instance; profMoreBtn2 just reaches up to the one in map-top-right
   rather than getting a second copy near itself. */
.menu-pop{
  position:absolute; top:48px; right:0; z-index:40; min-width:208px;
  background:#fff; border:var(--bd); border-radius:14px; box-shadow:var(--sh);
  overflow:hidden; padding:6px;
}
.menu-item{
  display:flex; align-items:center; gap:10px; width:100%; border:none; background:none;
  padding:11px 10px; font-family:inherit; font-size:14px; font-weight:700; color:var(--ink);
  border-radius:9px; text-align:left; cursor:pointer;
}
.menu-item i{ font-size:17px; color:var(--muted); width:18px; }
.menu-item.danger{ color:var(--red); }
.menu-item.danger i{ color:var(--red); }
.menu-divider{ height:1px; background:var(--line); margin:4px 2px; }
.menu-pop form{ margin:0; }
/* v226: the menu hangs below the 230px map banner, whose overflow:hidden cut off "Block" —
   let it show while the menu is open; and keep every row on one line (the long
   "Block @handle" wrapped to 2 lines and pushed its icon out of place) */
.map-header:has(.menu-pop:not([hidden])){ overflow:visible; z-index:30; }
.menu-pop{ width:max-content; max-width:calc(100vw - 32px); }
.menu-item{ white-space:nowrap; }
.menu-item i{ flex:0 0 18px; }
/* ---------- Report dialog (the ⋯ menu's "Report" row opens this) ----------
   Kept as the site's existing centred-modal pattern (same as pin.php's #reportModal,
   reels.js's #reelsReportModal) — the reference doesn't show a report FORM on this
   screen at all (just the menu, now built above), so there's no reference to match for
   the form itself. Self-contained — doesn't depend on another batch's lite-tools.css,
   which this page doesn't load. */
.modal-backdrop{ position:fixed; inset:0; background:rgba(20,21,24,.5); display:none; align-items:center; justify-content:center; z-index:900; padding:16px; }
.modal-backdrop.is-open{ display:flex; }
.modal{ background:#fff; border-radius:var(--r-card); border:var(--bd); box-shadow:var(--sh-lg); padding:18px; max-width:420px; width:100%; max-height:85vh; overflow-y:auto; }
.modal__head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:14px; }
.modal__head h3{ font:800 16px/1.2 var(--font-display); color:var(--ink); margin:0; display:flex; align-items:center; gap:6px; }

@media (min-width:481px){
  .map-header{ margin:0 -16px 0; }
}

/* ==========================================================================
   Hidden profile — migration 039, users.profile_hidden.
   Reference: lite5/user-profile-hidden-preview.html.
   ========================================================================== */
.hidden-wrap{ display:flex; flex-direction:column; align-items:center; padding:52px 28px 0; text-align:center; }
.ghost-avatar{
  width:96px; height:96px; border-radius:50%; background:var(--card-2);
  display:flex; align-items:center; justify-content:center; color:var(--muted-2); font-size:40px;
  margin-bottom:22px; border:1.5px solid var(--line);
}
.hidden-title{ font:800 19px/1.2 var(--font-display); color:var(--ink); margin-bottom:8px; }
.hidden-sub{ font:600 14.5px/1.5 var(--font-ui); color:var(--muted); margin-bottom:26px; max-width:280px; }
.info-card{ width:100%; margin-bottom:26px; }
.info-card .row{ align-items:flex-start; padding:15px 16px; }
.info-card .ico{ color:var(--muted); background:var(--card-2); }
.info-card p{ margin:0; font:600 13px/1.5 var(--font-ui); color:var(--muted); text-align:left; }
.report-link{
  background:none; border:none; font-family:inherit; font:700 13.5px/1 var(--font-ui); color:var(--muted);
  display:flex; align-items:center; gap:6px; padding:10px; cursor:pointer;
}
.report-link i{ font-size:15px; }

/* ==========================================================================
   v208: Collections row on a creator's public profile (between the category
   chips and the pins grid). Reference: profile-collections-preview.html.
   ========================================================================== */
.coll-row{display:flex;gap:12px;overflow-x:auto;scrollbar-width:none;margin:0 0 20px;padding:2px 0 4px;}
.coll-row::-webkit-scrollbar{display:none;}
.coll-card{flex:0 0 auto;width:168px;display:flex;flex-direction:column;gap:8px;color:inherit;text-decoration:none;}
.coll-cover{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;gap:3px;width:168px;height:168px;
  border-radius:var(--r-card);overflow:hidden;background:var(--card-2);border:1px solid var(--line);}
.coll-cover img{width:100%;height:100%;min-height:0;object-fit:cover;display:block;}
.coll-cover span{width:100%;height:100%;display:block;background:var(--card-2);}
/* v251: shape follows the number of photos (collections-fix-preview.html) */
.coll-cover.n1{grid-template-columns:1fr;grid-template-rows:1fr;}
.coll-cover.n2{grid-template-columns:1fr 1fr;grid-template-rows:1fr;}
.coll-cover.n3{grid-template-columns:1.25fr 1fr;grid-template-rows:1fr 1fr;}
.coll-cover.n3 > img:first-child{grid-row:1 / 3;}
.coll-more{position:relative;min-height:0;}
.coll-more::after{content:attr(data-more);position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:rgba(20,21,24,.55);color:#fff;font:800 22px/1 var(--font-display);letter-spacing:-.3px;}
.coll-cover.n0{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  border:2px dashed rgba(20,21,24,.22);background:#fafafb;color:var(--muted);}
.coll-cover.n0 i{font-size:26px;color:var(--ink);}
.coll-cover.n0 b{font:700 12.5px/1 var(--font-ui);}
.coll-name{font:700 14.5px/1.25 var(--font-display);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.coll-count{font:600 12.5px/1 var(--font-ui);color:var(--muted);}

/* launch review: owner's own "N of M done" checklist (.help-mine, assets/css/lite-tools.css)
   — this screen's one hard shadow is already the Edit-profile button (see .vcard__mgmt
   .icon-btn comment above), so the checklist card is flattened to a plain border here. */
.help-mine.help-mine--flat{box-shadow:none;border:1px solid var(--line,#e4e4e7);}
/* v277: an undone checklist item is a link straight to where it's fixed (edit-profile.php
   #anchor) — lite-tools.css's .help-mine__list li already colours text var(--ink), so the
   link needs its own colour; keep the row's own gap, don't let the link add underline. */
.help-mine__list li a.link-blue{text-decoration:none;}

/* ---------- v277: empty-state intro line, same slot as a reference's own "section-sub"
   (profile-empty-preview.html) — sits right under the section-head, above the ghost slot. */
.section-sub{font:500 12.5px/1.5 var(--font-ui);color:var(--muted);margin:-4px 0 12px;}

/* ---------- v277: ghost "add a clip" slot (profile-empty-preview.html) — same dashed-slot
   convention as the add-pin wizard's own photo slots (assets/css/lite-addpin.css's
   .wiz2-addslot / .ev2-addslot: dashed var(--line) on var(--card-2), not a brand colour,
   so it reads as "empty", never as an error). Reuses the real .vcard/.vcard__media shape
   (assets/css/lite.css) so a ghost clip is exactly the same size/radius as a real one. */
.vcard--ghost .vcard__media{
  border:1.5px dashed var(--line); background:var(--card-2);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px; text-align:center; padding:16px;
}
.vcard--ghost .ghost-ico{
  width:40px; height:40px; border-radius:50%; background:#fff; border:1.5px dashed var(--line);
  display:flex; align-items:center; justify-content:center; font-size:19px; color:var(--muted-2);
}
.vcard--ghost .ghost-label{font:700 12.5px/1.3 var(--font-ui); color:var(--muted); max-width:120px;}
.vcard--ghost{cursor:pointer;}
.vcard--ghost:focus-visible .vcard__media{outline:3px solid var(--blue); outline-offset:2px;}

/* ---------- v277: ghost "add a moment" tile + prompt row (profile-empty-preview.html) ---------- */
.m-tile--ghost{border:1.5px dashed var(--line); display:flex; align-items:center; justify-content:center; background:transparent;}
.m-tile--ghost i{font-size:18px; color:var(--muted-2);}
.m-tile--ghost:focus-visible{outline:3px solid var(--blue); outline-offset:2px;}
.moments-add-row{
  grid-column:1/-1; display:flex; align-items:center; justify-content:center; gap:4px; padding:10px 4px;
  font:700 12px/1.3 var(--font-ui); color:var(--muted); text-align:center;
}
