/* static/css/profile.css
   Profile page + My Sites + the toolbar-injected profile overlay (map.html).
   Split out of styles.css so pages that never touch any of this
   (admin_requests.html, analytics.html, index.html, terms.html, and
   map.html until the profile button is actually clicked) don't pay for
   it. Loaded eagerly by profile.html; lazy-loaded by toolbar.js's
   _ensureProfilePanelLoaded, right alongside the profile-forms.js/
   profile-panel.js it already lazy-loads for the exact same reason (see
   that function's own comment). Extracted mechanically — every
   declaration here still applies to exactly the same selector it always
   did, just relocated; nothing here should look different, only load
   later on pages that don't need it. */

/* ── Map profile overlay panel (toolbar-injected, lazy-loaded) ── */
.map-profile-overlay {
  /* position:fixed, not absolute — this panel (toolbar-injected into
     map.html) lives nested inside #map's own .leaflet-container, which
     has overflow:hidden (Leaflet's own tile-clipping rule). An
     absolute-positioned descendant is clipped by that ancestor same as
     any other; escaping it needs position:fixed specifically (viewport-
     relative, ignores ancestor overflow — the exact same fix
     .search-dropdown already uses for this identical container, see its
     own comment). Confirmed live: deeply-nested content (a My Sites
     card's own three-dot menu) was intermittently failing real click/
     actionability checks under position:absolute despite rendering
     visually correct — inset:0 now fills the actual viewport instead of
     .leaflet-container's own (possibly differently-clipped) box. */
  position: fixed;
  inset: 0;
  /* Above both #map .leaflet-top/.leaflet-bottom's 200000 !important (map
     chrome) and #dash-sheet's 200010 (styles.css) — the profile panel is
     a modal-like overlay and must sit over everything else in-map. */
  z-index: 200020;
  display: none;
  align-items: stretch;
  justify-content: stretch;
  padding: 0;
  background:
    radial-gradient(circle at 50% 30%, rgba(0, 0, 0, 0.10) 0%, rgba(0, 0, 0, 0.18) 40%, rgba(0, 0, 0, 0.34) 100%);
  backdrop-filter: blur(var(--glass-panel-blur));
  -webkit-backdrop-filter: blur(var(--glass-panel-blur));
}
.map-profile-overlay.active {
  display: flex;
}

/* Share dialog sits above map controls/toolbar/slide-up, AND above the
   profile overlay — it's re-parented to document.body (see toolbar.js's
   File-group Share button comment) precisely so it can be triggered
   without the profile panel ever becoming visible, but that only works
   if its own z-index actually beats the overlay's; below it, the dialog
   was invisible, hidden behind an overlay it's not even nested in. */
#share-site-modal-backdrop {
    z-index: 200025;
}

#map-profile-panel {
  position: absolute;
  top: 78px;
  left: 50%;
  transform: translateX(-50%);
  width: min(680px, calc(100vw - 40px));
  max-height: calc(100vh - 98px);
  overflow: hidden;
  pointer-events: auto;
  background: var(--glass-panel-bg);
  backdrop-filter: blur(var(--glass-panel-blur));
  -webkit-backdrop-filter: blur(var(--glass-panel-blur));
}
/* Edge-to-edge on desktop/tablet now, not var(--maximize-margin)-inset
   — the title bar can't actually reposition a maximized panel, so that
   margin never served a real purpose, just ate content space. Only the
   OUTER frame goes (inset to 0, corners/border/shadow stripped) —
   .map-profile-overlay-body and .auth-forms below keep their normal
   desktop padding/card treatment untouched, unlike mobile's own
   @media block further down, which also flattens THOSE. */
#map-profile-panel.maximized {
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: auto;
  max-height: none;
  transform: none;
  border-radius: 0;
  border: none;
  border-bottom: none;
  box-shadow: none;
}
#map-profile-panel.maximized .map-profile-overlay-body {
  max-height: calc(100vh - 52px);
}
.map-profile-overlay-body {
  /* overflow-y: scroll, not auto — scrollbar-gutter:stable (kept below)
     was meant to reserve the scrollbar's own width unconditionally so
     appearing/disappearing never changes the content box width, but
     confirmed live it wasn't fully preventing it: the same "first" My
     Sites card menu button resolved to two DIFFERENT cards' coordinates
     between two back-to-back reads, meaning .my-sites-gallery-grid's own
     auto-fill column count was still genuinely oscillating as content
     height (images loading, tabs switching) toggled the scrollbar. A
     narrower box on one pass can tip auto-fill from N to N-1 (wider)
     columns and back, and each card's own aspect-ratio-driven image
     height changes with it — which is what kept letting the image grow
     into the row below and cover the three-dot menu, however that menu
     itself was positioned. scroll (not auto) reserves the scrollbar's
     track unconditionally in every browser, not just ones honoring
     scrollbar-gutter, removing the oscillation at its actual source
     rather than chasing its symptoms further down in each card. */
  overflow-y: scroll;
  max-height: calc(100vh - 150px);
  scrollbar-gutter: stable;
}
@media (max-width: 768px) {
  /* Always maximized on mobile — same values .maximized already uses on
     desktop (top/left/right/bottom, no width/max-height), just applied
     unconditionally instead of behind the toggle button, which is
     hidden below since there's no other state left to toggle to.
     !important on every edge: #map-profile-panel.maximized (above) is
     more specific than this plain id, and would win over it — with
     real consequences (var(--maximize-margin) is a nonzero desktop
     value, not 0) — if that class were ever present here for any
     reason (a stale toggle, a future feature). On mobile these four
     edges are non-negotiable: full viewport, always, regardless of
     what else this element might otherwise match, present or future. */
  #map-profile-panel {
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    width: auto !important;
    max-height: none !important;
    transform: none !important;
    /* .layover-frame (styles.css, this panel's own class) is where its
       rounded corners come from — makes no sense once the panel fills
       the whole screen edge to edge. .auth-forms (the greeting/"What
       you measure…" quote's own wrapper, same shared rule in styles.css)
       gets the identical treatment below for the same reason: it's the
       inner content card, its corners were still visible even once the
       outer panel itself had nowhere left to round against. Same shared
       rule also draws a 1px border around each of them (--glass-panel-
       border) — the two thin lines still visible around the edge of the
       screen and around Explore/Following/etc even after the corners
       and shadow were already gone. */
    border-radius: 0 !important;
    border: none !important;
  }
  .map-profile-overlay-body {
    max-height: calc(100vh - 52px);
  }
  #map-profile-toggle-size {
    display: none;
  }
  /* .auth-forms (loadProfileContent, toolbar.js) is the fetched /profile
     page's own top-level wrapper, reused as-is inside this overlay — its
     30px padding is the only thing inseting every section (My Sites,
     Following, Explore) from the panel's edges; each section box has no
     horizontal margin of its own. Zeroing it here is the one change
     needed to make every section run flush to the now-edge-to-edge
     panel — nothing about the sections themselves changed. */
  #map-profile-panel .auth-forms {
    padding-left: 0;
    padding-right: 0;
    /* .auth-forms is also in styles.css's shared glass-panel list
       (border-radius: var(--glass-panel-radius)) — the greeting/"What
       you measure…" quote's own wrapper, still visibly rounded even
       once #map-profile-panel around it (above) had nowhere left to
       round against. Same shared rule's 1px border, too. */
    border-radius: 0;
    border: none;
  }
}
body.tile-dark .map-profile-overlay {
  background:
    radial-gradient(circle at 50% 30%, rgba(var(--darkTheme), 0.14) 0%, rgba(var(--darkTheme), 0.26) 40%, rgba(var(--darkTheme), 0.48) 100%);}
/* ── Profile avatar ── */
.profile-avatar-wrap {
    text-align: center;
    margin-bottom: 18px; }
.profile-avatar {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 84px;
    height: 84px;
    border-radius: 50%;
    background: var(--glass-button-bg);
    cursor: pointer;
    overflow: hidden;
    border: 2px solid var(--control-glass-border); }
.profile-avatar-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%; }
.profile-avatar-initials {
  width: 62%;
  height: 62%;
  object-fit: contain;
  user-select: none;
  pointer-events: none; }
.profile-avatar-overlay {
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,0.42);
    color: #fff;
    font-size: 0.7rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.18s; }
.profile-avatar:hover .profile-avatar-overlay { opacity: 1; }
/* ── Greeting / name ── */
.profile-greeting::before { content: '"'; font-size: inherit; }
.profile-greeting::after { content: '"'; font-size: inherit; }
.profile-fullname {
    text-align: center;
    font-size: 1.05em;
    font-weight: 600;
    color: var(--control-glass-text);
    margin: -8px 0 14px 0;
    letter-spacing: 0.01em;
}
/* ── Profile view (read-only info) ── */
#profile-view p {
    color: rgba(var(--theme-fg), 0.55);
}
#profile-view p strong {
    color: var(--control-glass-text);
    font-weight: 500;
}
/* ── My Info accordion ── */
#my-info-section {
    box-sizing: border-box;
    margin-top: 14px;
    border-radius: var(--smallcorner);
    overflow: hidden;
    background: rgba(var(--theme-fg), 0.05);
    box-shadow: 0 0 0 1px rgba(255,255,255,0.08), 0 4px 24px rgba(0,0,0,0.18);
}
#my-info-section[open] {
    box-shadow: 0 0 0 1px rgba(255,255,255,0.12), 0 4px 24px rgba(0,0,0,0.22);
}
.my-info-title {
    justify-self: start;
}
.my-info-edit-toggles {
    display: flex;
    gap: 4px;
    justify-self: end;
}
#my-info-section:not([open]) .my-info-edit-toggles {
    display: none;
}
.profile-info-corner-btn svg {
    width: 1.1rem;
    height: 1.1rem;
    display: block;
    fill: currentColor !important;
    stroke: currentColor !important;
}
.profile-info-box {
    padding: 10px 24px;
}
/* ── My Sites gallery ── */
.my-sites-box,
#my-treecoins-section {
    margin-top: 18px;
}
.my-sites-box {
    box-sizing: border-box;
    border-radius: var(--smallcorner);
    overflow: hidden;
    background: rgba(var(--theme-fg), 0.05);
    box-shadow: 0 0 0 1px rgba(255,255,255,0.08), 0 4px 24px rgba(0,0,0,0.18);
}
/* Popover-open overflow escape is handled generically now
   (profile-panel.js's _syncMySitesMenuOverflow — walks the real ancestor
   chain and overrides inline overflow on whichever ones actually clip,
   in any container this markup ends up in), not a fixed has-open-menu
   class/selector pair here. */
.my-sites-box[open] {
    box-shadow: 0 0 0 1px rgba(255,255,255,0.12), 0 4px 24px rgba(0,0,0,0.22);
}
.my-sites-title {
    justify-self: start;
}
.my-sites-invite-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    margin-left: 6px;
    border-radius: 999px;
    background: #e5484d;
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: normal;
    text-transform: none;
    vertical-align: middle;
}
.my-sites-empty {
    margin: 4px 2px;
    color: rgba(var(--theme-fg), 0.5);
    font-size: 0.9rem;
}
.my-sites-members {
    display: flex;
    align-items: center;
    margin-top: 6px;
}
.my-sites-member-avatar {
    width: 39px;
    height: 39px;
    border-radius: 50%;
    object-fit: cover;
    background: rgba(var(--theme-fg), 0.15);
    border: 3px solid rgba(var(--theme-fg), 0.1);
    margin-left: -13px;
}
.my-sites-member-avatar.my-sites-member-pending {
    opacity: 0.4;
}
.my-sites-members .my-sites-member-avatar:first-child {
    margin-left: 0;
}
.my-sites-gallery-img-wrap .my-sites-members {
    position: absolute;
    top: 6px;
    right: 6px;
    margin-top: 0;
    filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.6));
}
.my-sites-gallery-img-wrap .my-sites-member-avatar {
    width: 30px;
    height: 30px;
    border-width: 3px;
    margin-left: -12px;
}
.my-sites-gallery-img-wrap .my-sites-member-avatar-fallback,
.my-sites-gallery-img-wrap .my-sites-member-more {
    font-size: 1rem;
}
#explore-sites-section .my-sites-member-avatar {
    width: 78px;
    height: 78px;
    border-width: 6px;
    margin-left: -26px;
}
#explore-sites-section .my-sites-member-avatar-fallback,
#explore-sites-section .my-sites-member-more {
    font-size: 2.3rem;
}
#explore-sites-section .my-sites-gallery-img-wrap .my-sites-member-avatar {
    width: 30px;
    height: 30px;
    border-width: 3px;
    margin-left: -12px;
}
#explore-sites-section .my-sites-gallery-img-wrap .my-sites-member-avatar-fallback,
#explore-sites-section .my-sites-gallery-img-wrap .my-sites-member-more {
    font-size: 1rem;
}
.my-sites-carousel-label-row .my-sites-member-avatar {
    width: 30px;
    height: 30px;
    border-width: 3px;
    margin-left: -12px;
}
.my-sites-carousel-label-row .my-sites-member-avatar-fallback,
.my-sites-carousel-label-row .my-sites-member-more {
    font-size: 1rem;
}
#explore-sites-section .my-sites-carousel-label-row .my-sites-member-avatar {
    width: 30px;
    height: 30px;
    border-width: 3px;
    margin-left: -12px;
}
#explore-sites-section .my-sites-carousel-label-row .my-sites-member-avatar-fallback,
#explore-sites-section .my-sites-carousel-label-row .my-sites-member-more {
    font-size: 1rem;
}
.my-sites-member-avatar-fallback,
.my-sites-member-more {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--control-glass-text);
    background: rgba(var(--theme-fg), 0.18);
}
.my-sites-member-avatar-fallback-icon {
    width: 22px;
    height: 22px;
    pointer-events: none;
}
.my-sites-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    flex-shrink: 0;
}
.my-sites-tag-chip {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 999px;
    background: rgba(var(--theme-fg), 0.12);
    color: rgb(var(--theme-fg));
    font-size: 0.625rem;
    font-weight: 400;
    white-space: nowrap;
    opacity: 0.7;
}
.my-sites-gallery-card .my-sites-tags {
    padding: 4px 8px 6px;
}
.my-sites-carousel .my-sites-tags {
    justify-content: center;
    margin: -2px 0 4px;
}
.my-sites-layouts {
    display: flex;
    align-items: center;
    gap: 3px;
    font-size: 0.625rem;
    font-weight: 300;
    color: rgb(var(--theme-fg));
    opacity: 0.55;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.my-sites-layouts-icon {
    width: 11px;
    height: 11px;
    opacity: 0.85;
}
.my-sites-gallery-card .my-sites-layouts {
    padding: 0 8px 6px;
}
.my-sites-carousel .my-sites-layouts {
    justify-content: center;
    margin: -2px 0 4px;
}
.my-sites-view-toggles {
    display: flex;
    gap: 0.1875rem;
    justify-self: end;
    transition: opacity 0.24s ease;
}
.my-sites-fade-instant {
    transition: none !important;
}
body.my-sites-no-anim .my-sites-view-toggles,
body.my-sites-no-anim .my-sites-gallery-card,
body.my-sites-no-anim .my-sites-strip-card,
body.my-sites-no-anim .my-sites-row {
    transition: none !important;
}
.my-sites-box:not([open]) .my-sites-view-toggles {
    display: none;
}
.my-sites-view-btn {
    /* Same as #map-profile-close/#map-profile-toggle-size (styles.css's
       shared .btn-toggle rule) — was smaller before. */
    width: 1.615rem;
    height: 1.615rem;
    font-size: 0.8125rem;
    opacity: 0.5;
}
.my-sites-view-btn.active {
    opacity: 1;
    background: var(--glass-button-hover-bg);
}
.my-sites-view-btn svg {
    width: 1.21em;
    height: 1.21em;
    fill: currentColor;
}
.my-sites-accordion {
    display: flex;
    flex-direction: column;
    padding: 12px 12px 10px;
}
/* This rule's own `display: flex` above is author CSS, so it beats the
   browser's native `details:not([open]) > *:not(summary) { display:
   none }` rule regardless of selector specificity (author origin always
   wins over the UA stylesheet) — a closed My Sites tab's own accordion
   div (moved back into its own <details class="my-sites-box"> by
   _syncHubWrapPlacement, profile-panel.js) stayed fully laid out and
   geometrically overlapping the actually-open tab's content instead of
   collapsing, silently stealing clicks meant for the visible tab (e.g.
   its three-dot menu buttons landing on a closed tab's invisible cards
   instead). Restores the native hidden behavior explicitly. */
.my-sites-box:not([open]) > .my-sites-accordion {
    display: none;
}
.my-sites-thumb-flag {
    flex-shrink: 0;
    font-size: 0.75rem;
    line-height: 1;
}
.my-sites-thumb-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.my-sites-thumb-name,
.my-sites-thumb-flag {
    opacity: 0.5;
    transition: opacity 0.15s ease;
}
.my-sites-gallery-card:hover .my-sites-thumb-name,
.my-sites-gallery-card:hover .my-sites-thumb-flag {
    opacity: 1;
}
body.my-sites-cover-fit-contain { --my-sites-cover-fit: contain; }
body.my-sites-cover-fit-cover { --my-sites-cover-fit: cover; }
.my-sites-dimmed-section .my-sites-gallery-img-wrap,
.my-sites-dimmed-section .my-sites-carousel-img {
    opacity: 0.5;
}
/* List view has no image to dim — .my-sites-dimmed-section lands
   directly on the row itself there (_renderList, profile-panel.js), so
   it needs its own rule instead of a descendant one. */
.my-sites-row.my-sites-dimmed-section {
    opacity: 0.5;
}
.my-sites-gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(144px, 1fr));
    gap: 12px;
}
/* Strip — same frameless cards Gallery uses (.my-sites-gallery-card,
   reused as-is, see _galleryCardsHtml/profile-panel.js), just in a
   horizontally-scrolling row instead of a wrapping grid, and smaller
   (.my-sites-strip-card below caps each card's width, where Gallery's
   own grid instead grows them to fill available space). Plain native
   overflow-x scroll — no custom drag-to-scroll like Dock view's icon
   row needed (that one also drives a hover-magnify effect this doesn't
   have); a trackpad/scrollbar/shift+wheel already reaches it on
   desktop, a finger swipe on mobile. */
.my-sites-strip {
    /* min-width:0 — a flex item's default min-width is auto, which for a
       flex CONTAINER child effectively floors it at its own content's
       min-content size. Every card inside is flex:0 0 auto (never
       shrinks), so that floor was the sum of every card's width — 9396px
       measured live for one real list — overriding the "stretch to
       parent width" cross-axis behavior .my-sites-accordion's column
       flex would otherwise give it. The strip just grew past the page
       instead of staying page-width with its own scrollable overflow,
       which is what actually made it "stuck": there was nothing to
       scroll — overflow-x:auto below never had anywhere shorter than
       its own content to clip against. Same fix .my-sites-breadcrumb
       already uses for the identical reason. */
    min-width: 0;
    display: flex;
    gap: 12px;
    overflow-x: auto;
    /* mandatory, not proximity — iPadOS Safari specifically (not iPhone
       Safari) has a known bug where 'proximity' scroll-snap combined
       with no explicit touch-action can stop honoring further swipes
       after the first couple of snap points, as if the strip ran out of
       room to scroll even though later cards are still there.
       touch-action: pan-x makes the allowed gesture explicit rather than
       leaving it as 'auto' for WebKit to infer — same fix as the
       dash-embed iframe's own touch-action needed to be explicit rather
       than implicit for the same class of WebKit ambiguity. */
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
    padding-bottom: 2px;
}
.my-sites-strip-card {
    flex: 0 0 auto;
    width: 184px;
    scroll-snap-align: start;
}
.my-sites-gallery-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Row-by-row reveal on first render (Gallery's own grid) / just a
       plain fade-in (Strip, no meaningful "row" to stagger by). */
    transition: opacity 0.3s ease var(--anim-delay, 0ms),
                transform 0.3s ease var(--anim-delay, 0ms);
}
.my-sites-gallery-img-wrap {
    display: block;
    position: relative;
    width: 100%;
    /* align-self: stretch — .my-sites-gallery-card's own align-items:
       center (above) means a plain width:100% here has no definite
       parent width to resolve against (the card doesn't stretch its
       children by default), which made the aspect-ratio-driven height
       below a genuine layout race — confirmed live, the same card
       measured 108px tall one render and 146px the next. A 146px image
       physically overlaps the caption/menu row underneath it, which is
       exactly the "three-dot menu click lands on the photo and
       navigates the whole page" bug this fixes. align-self here (not
       changing the card's own align-items, which other children may
       still want) forces this element's own width to be definite. */
    align-self: stretch;
    aspect-ratio: 4 / 3;
    border-radius: var(--smallcorner);
    overflow: hidden;
    cursor: pointer;
    background: transparent;
}
.my-sites-gallery-img-wrap img {
    width: 100%;
    height: 100%;
  object-fit: var(--my-sites-cover-fit, contain);
    display: block;
    transition: transform 0.2s ease;
}
.my-sites-gallery-card:hover .my-sites-gallery-img-wrap img {
    transform: scale(1.06);
}
.my-sites-gallery-caption {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 6px;
    width: 100%;
    margin-top: 6px;
    padding: 0 4px;
    font-size: 0.875rem;
    color: rgb(var(--theme-fg));
    text-align: left;
    /* No position/z-index here any more — this being position:relative
       made IT (the menu's own actual DOM parent, closer than the card)
       the containing block for .my-sites-gallery-card .my-sites-menu's
       new position:absolute, silently defeating that fix (top:6px/
       left:6px resolved against the caption's own top, i.e. right where
       the menu already sat, not the card's top-left corner). Confirmed
       live, the only rule anywhere that references this class — nothing
       depends on it having its own stacking context. */
}
.my-sites-carousel {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 160px;
    margin-bottom: 36px;
}
.my-sites-carousel-img {
  width: 100%;
    max-width: 100%;
    max-height: 220px;
    border-radius: var(--smallcorner);
    display: block;
  object-fit: var(--my-sites-cover-fit, contain);
}
.my-sites-carousel-label-row {
    position: absolute;
    left: 0; right: 0; bottom: -20px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    opacity: 0.5;
    transition: opacity 0.15s ease;
}
.my-sites-carousel:hover .my-sites-carousel-label-row {
    opacity: 1;
}
.my-sites-carousel-label {
    font-size: 0.6875rem;
    color: rgb(var(--theme-fg));
}
.my-sites-carousel-label-row .my-sites-members {
    margin-top: 0;
}
.my-sites-add-slide {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px dashed var(--control-glass-border);
    color: rgba(var(--theme-fg), 0.4);
    cursor: pointer;
    transition: border-color 0.18s, background 0.18s, color 0.18s;
}
.my-sites-add-slide:hover {
    border-color: rgba(var(--theme-fg), 0.9);
    background: rgba(var(--theme-fg), 0.08);
    color: rgba(var(--theme-fg), 1);
}
.my-sites-add-row {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    color: rgba(var(--theme-fg), 0.55);
    transition: color 0.15s;
}
.my-sites-add-row:hover { color: rgba(var(--theme-fg), 1); }
.my-sites-display-name {
    display: block;
    font-weight: 600;
    font-size: 0.75rem;
    color: rgb(var(--theme-fg));
}
.my-sites-flag {
    margin-right: 4px;
}
.my-treecoins-value {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--control-glass-text);
    padding: 4px 12px 8px;
}
.my-sites-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 2px 6px;
    border-radius: 8px;
    transition: background 0.15s,
                opacity 0.3s ease var(--anim-delay, 0ms),
                transform 0.3s ease var(--anim-delay, 0ms);
}
.my-sites-row:hover {
    background: rgba(var(--theme-fg), 0.05);
}
.my-sites-gallery-card.my-sites-reveal-hidden,
.my-sites-row.my-sites-reveal-hidden {
    opacity: 0;
    transform: translateY(6px);
}
.my-sites-gallery-card.my-sites-reveal-instant,
.my-sites-row.my-sites-reveal-instant {
    transition: none !important;
}
/* Wraps controlsHtml (profile-panel.js's _renderList) — either the five
   hover-only icon buttons (Make Public/Private, Rename, Tags, Share,
   Remove) or the three-dot menu, depending on bucket. flex-shrink:0
   reserves their real width unconditionally, even while opacity:0 and
   invisible at rest — previously nothing grouped them, so a long
   breadcrumb (flex:1 below) could grow right over where they'd need to
   land, and they only became reachable by widening the window enough
   for both to fit on one line at once. order:1 keeps them to the right
   of the breadcrumb (order:0, default) for every bucket now, not just
   the plain 5-icon case, which previously had that same ordering on
   each icon individually but not on the three-dot menu case. */
.my-sites-row-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    order: 1;
}
.my-sites-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.05rem;
    height: 1.05rem;
    padding: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    opacity: 0;
    color: rgb(var(--theme-fg));
    transition: opacity 0.15s, color 0.15s;
}
.my-sites-row:hover .my-sites-icon-btn { opacity: 0.5; }
.my-sites-icon-btn:disabled { cursor: default; }
.my-sites-row:hover .my-sites-icon-btn:hover:not(:disabled) { opacity: 1; }
.my-sites-icon-btn-icon { display: block; width: 100%; height: 100%; }
.my-sites-icon-btn-icon svg { display: block; width: 100%; height: 100%; fill: currentColor; }
.my-sites-icon-btn-emoji {
    display: block;
    font-size: 0.85rem;
    line-height: 1.05rem;
    text-align: center;
}
.my-sites-menu {
    position: relative;
    display: inline-flex;
    flex-shrink: 0;
}
/* Gallery cards specifically: the three-dot menu moves out of the caption
   row's normal flow entirely and becomes a fixed badge anchored to the
   card's own top-left corner (top-right is already .my-sites-members'
   spot — see that rule above), same "floats on the photo" pattern that
   badge already uses. Anchoring to the CARD (top:/left:, not flowing
   after the image) makes its position immune to the image's own height —
   .my-sites-gallery-img-wrap's aspect-ratio-driven height briefly
   disagreeing with the grid's own auto-fill column count mid-reflow
   (confirmed live: the same card measuring 108px tall one render, 146px
   the next, as the grid's column count flickered with the overlay's own
   scrollbar appearing/disappearing) used to let the image visually grow
   into the caption row below, covering the menu button — a click meant
   for it then landed on the photo instead and navigated the whole page,
   which is what "the dropdown menu opens a map/image" turned out to be. */
.my-sites-gallery-card .my-sites-menu {
    position: absolute;
    top: 6px;
    left: 6px;
    z-index: 3;
    background: rgba(0, 0, 0, 0.45);
    border-radius: 999px;
    padding: 2px 4px;
    filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5));
}
.my-sites-gallery-card .my-sites-menu-btn {
    color: #fff;
    opacity: 0.85;
}
.my-sites-gallery-card .my-sites-menu-btn:hover { opacity: 1; }
/* Carousel view's own slide (.my-sites-carousel, already position:
   relative, same as .my-sites-gallery-card above) gets the identical
   floating badge treatment — its menu used to just flow inline in
   .my-sites-carousel-label-row's plain dark-on-light text row, looking
   like a different, unstyled component next to Gallery's photo badge. */
.my-sites-carousel > .my-sites-menu {
    position: absolute;
    top: 6px;
    left: 6px;
    z-index: 3;
    background: rgba(0, 0, 0, 0.45);
    border-radius: 999px;
    padding: 2px 4px;
    filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5));
}
.my-sites-carousel > .my-sites-menu .my-sites-menu-btn {
    color: #fff;
    opacity: 0.85;
}
.my-sites-carousel > .my-sites-menu .my-sites-menu-btn:hover { opacity: 1; }
.my-sites-menu-btn {
    background: transparent;
    border: none;
    color: rgb(var(--theme-fg));
    opacity: 0.55;
    cursor: pointer;
    line-height: 1;
    padding: 0 3px;
    display: inline-flex;
    align-items: center;
    transition: opacity 0.15s;
}
.my-sites-menu-btn:hover { opacity: 1; }
.my-sites-menu-icon svg {
    width: 0.875rem;
    height: 0.875rem;
    display: block;
    fill: currentColor;
}
/* Popover box + item look now shared with every other dropdown's own list
   (styles.css's .custom-dropdown-list/.custom-dropdown-option — see that
   rule's own comment). Only the show/hide toggle stays here: JS
   (profile-panel.js's _wireSiteMenus) still just adds/removes this class. */
.my-sites-menu-popover.hidden { display: none; }
.my-sites-confirm-text {
    flex: 1;
    min-width: 0;
    font-size: 0.6875rem;
    font-weight: 300;
    color: rgba(var(--theme-fg), 0.7);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.my-sites-confirm-yes,
.my-sites-confirm-no {
    flex-shrink: 0;
    cursor: pointer;
    font-size: 0.6875rem;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: var(--smallcorner);
    transition: background 0.15s, color 0.15s;
}
.my-sites-confirm-yes { color: #c00; }
.my-sites-confirm-no  { color: rgba(var(--theme-fg), 0.6); }
.my-sites-confirm-yes:hover,
.my-sites-confirm-no:hover { background: rgba(var(--theme-fg), 0.08); }
.my-sites-box .my-sites-breadcrumb,
#my-sites-hub-content .my-sites-breadcrumb {
    display: block;
    flex: 1;
    min-width: 0;
    padding: 6px 0;
    font-size: 0.6875rem;
    font-weight: 300;
    color: rgb(var(--theme-fg));
    line-height: 1.3;
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: opacity 0.15s;
}
.my-sites-row:not(.my-sites-add-row) .my-sites-breadcrumb {
    opacity: 0.5;
}
.my-sites-row:not(.my-sites-add-row):hover .my-sites-breadcrumb {
    opacity: 1;
}
.my-sites-box .my-sites-breadcrumb:hover,
#my-sites-hub-content .my-sites-breadcrumb:hover {
    color: rgb(var(--theme-fg));
}
/* ── Share-site modal ── */
.share-site-modal.dragged {
    position: fixed;
    margin: 0;
}
.share-site-panel-bar {
    margin: -22px -22px 14px;
    background: rgba(var(--theme-fg), 0.05);
}
.share-site-form {
    display: flex;
    flex-direction: column;
}
.share-site-success {
    text-align: center;
    font-size: 0.8125rem;
    color: rgb(var(--theme-fg));
    padding: 10px 4px 4px;
}
.share-site-subtitle {
    font-size: 0.75rem;
    color: rgba(var(--theme-fg), 0.6);
    text-align: center;
    margin: -6px 0 14px; }
/* ── Member info popup ── */
#member-info-panel {
    width: min(220px, 80vw);
    padding: 14px 14px 12px;
}
#share-site-close-btn svg,
#my-sites-notice-close-btn svg,
#site-tags-close-btn svg {
    width: 1.0925rem;
    height: 1.0925rem;
    display: block;
    fill: currentColor;
}
/* ── Site tags modal ── */
.site-tags-list {
    display: flex;
    flex-direction: column;
    gap: 7px;
    margin: 4px 0 14px;
    max-height: 260px;
    overflow-y: auto;
}
.site-tags-item {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8125rem;
    font-weight: normal;
    color: var(--control-glass-text);
    cursor: pointer;
}
.site-tags-item input[type="checkbox"] {
    flex-shrink: 0;
    width: auto !important;
    margin: 0;
}
#member-info-close-btn svg {
    width: 0.8rem;
    height: 0.8rem;
    display: block;
    fill: currentColor;
}
.member-info-body {
    text-align: center;
    padding: 2px 2px 2px;
}
.member-info-avatar-wrap {
    display: flex;
    justify-content: center;
    margin-bottom: 8px;
}
.member-info-photo,
.member-info-initials {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
    background: rgba(var(--theme-fg), 0.15);
}
.member-info-initials {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--control-glass-text);
}
.member-info-name {
    font-weight: 600;
    font-size: 0.9rem;
    margin: 0 0 3px;
}
.member-info-tagline {
    font-size: 0.78rem;
    color: rgba(var(--theme-fg), 0.65);
    margin: 0;
}
.member-info-message-btn {
    margin: 8px auto 0;
}
.member-info-message-btn svg {
    width: 0.9rem;
    height: 0.9rem;
    display: block;
    fill: currentColor;
}
.member-info-compose {
    margin-top: 10px;
    text-align: left;
}
.member-info-compose-text-wrap {
    position: relative;
}
.member-info-compose-text {
    /* border-box, not the default content-box — without it width:100%
       stops at the content edge and the border+padding add on top of
       that, pushing the right edge past the card's own edge (the left
       edge lines up fine, so all the overflow shows up on the right). */
    box-sizing: border-box;
    width: 100%;
    min-height: 64px;
    resize: vertical;
    background: rgba(var(--theme-fg), 0.05);
    border: 1px solid var(--control-glass-border);
    border-radius: 8px;
    padding: 0.45rem 0.6rem;
    font-size: 0.8125rem;
    color: var(--control-glass-text);
    font-family: inherit;
}
.member-info-compose-text-wrap::after {
    content: '';
    position: absolute;
    right: 1px;
    bottom: 1px;
    width: 12px;
    height: 12px;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.12s;
    background: linear-gradient(135deg,
        transparent 40%,
        rgba(var(--blackRGB),0.35) 40%,
        rgba(var(--blackRGB),0.35) 55%,
        transparent 55%,
        transparent 65%,
        rgba(var(--blackRGB),0.35) 65%,
        rgba(var(--blackRGB),0.35) 80%,
        transparent 80%
    );
}
.member-info-compose-text-wrap:focus-within::after {
    opacity: 1;
}
#member-info-compose-message {
    font-size: 0.75rem;
    margin: 4px 0 0;
}
.share-site-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.75rem;
    color: var(--control-glass-text);
    margin-bottom: 12px; }
.share-site-field input,
.share-site-field select {
    background: rgba(var(--theme-fg), 0.05);
    border: 1px solid var(--control-glass-border);
    border-radius: 8px;
    padding: 0.45rem 0.6rem;
    font-size: 0.8125rem;
    color: var(--control-glass-text); }
.share-site-lookup {
    margin: -4px 0 12px;
    min-height: 20px;
    display: flex;
    align-items: center; }
.share-site-spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid rgba(var(--theme-fg), 0.2);
    border-top-color: rgb(var(--theme-fg));
    animation: share-site-spin 0.7s linear infinite; }
.share-site-match {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: 8px;
    background: rgba(var(--theme-fg), 0.06);
    font-size: 0.8125rem;
    width: 100%; }
.share-site-match-photo {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    object-fit: cover;
    background: rgba(var(--theme-fg), 0.15); }
.share-site-notfound {
    font-size: 0.75rem;
    color: rgba(var(--theme-fg), 0.6); }
/* ── Landing / auth gate ── */
.auth-gate-card {
  padding-top: 56px;
}
.auth-gate-card .auth-gate-logo-link {
  position: absolute;
  top: 12px;
  left: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
}
.auth-gate-card .auth-gate-logo {
  width: 32px;
  height: auto;
  display: block;
  opacity: 0.92;
}
#show-register-link { color: var(--midcolor); }
#show-register-link:hover { color: var(--pill-fg); }

/* Admin-only Admin/Pitch/Analytics shortcut row (My Info) — same
   theme-aware --theme-fg token this file already uses everywhere else,
   applied to both the label and the icon (svg ships with a hardcoded
   fill, so it needs the explicit currentColor override every other
   icon-button context in this app already applies). */
.admin-shortcuts-row a,
.admin-shortcuts-row a:visited {
  color: rgba(var(--theme-fg), 0.92) !important;
  text-decoration: none;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
}
.admin-shortcuts-row a svg,
.admin-shortcuts-row a svg path {
  fill: currentColor;
}
.admin-shortcuts-row span {
  font-size: 0.7rem;
}
/* ── Birthdate field ── */
.birthdate-field {
  position: relative;
  width: 100%;
}
.birthdate-inline-btn {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  width: 22px;
  height: 22px;
  border: 0;
  background: transparent;
  color: var(--control-glass-text-muted);
  padding: 0;
  margin: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  opacity: 0.72;
  transition: opacity 0.16s ease, transform 0.16s ease;
  filter: none;
}
.birthdate-inline-btn:hover,
.birthdate-inline-btn:focus-visible {
  opacity: 1;
  transform: translateY(-50%) scale(1.05);
  color: inherit;
  background: transparent !important;
  border-color: transparent !important;
  box-shadow: none !important;
  filter: none;
}
.birthdate-inline-btn:active {
  transform: translateY(-50%) scale(1.02);
}
.birthdate-inline-btn svg {
  width: 20px;
  height: 20px;
  display: block;
  color: inherit;
  fill: currentColor;
}
.birthdate-field > input[type="date"].birthdate-native-picker-anchor {
  display: block !important;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 42px;
  width: calc(100% - 42px);
  height: 100%;
  opacity: 0;
  pointer-events: none;
  z-index: 0;
}
body.login-gate-page .auth-gate-logo-link {
  position: absolute;
  top: 12px;
  left: 12px;
  width: 64px;
  height: 64px;
  display: block;
  line-height: 0;
  overflow: hidden;
}
body.login-gate-page .auth-gate-logo {
  width: 64px !important;
  height: 64px !important;
  max-width: 64px !important;
  max-height: 64px !important;
  display: block;
  object-fit: contain;
}
/* ── Terms checkbox ── */
.terms-checkbox-container {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    margin-top: 4px;
    margin-bottom: 4px;}
.terms-checkbox-container input[type="checkbox"] {
    flex-shrink: 0;
    width: auto !important;
    margin: 0;}
.terms-checkbox-container label {
    display: inline;
    font-weight: normal;
    margin-bottom: 0; }
.terms-checkbox-container a {
    text-decoration: none;}
.loginhere {
    text-decoration: none;}
/* ── Form status messages ── */
#registration-message,
#login-message,
#profile-message {
    margin-top: 15px;
    font-size: 1.1em;
    font-weight: bold;
    text-align: center;}
/* #profile-message sits between My Info and My Sites in the DOM (its
   own error/success line, profile-forms.js), empty almost all the time
   — an empty <p> still keeps its own margin-top above, which was the
   actual reason My Info→My Sites looked like a wider gap than My Sites→
   Following→Explore (nothing sits between those). Collapses to nothing
   until profile-forms.js actually puts text in it via .textContent. */
#profile-message:empty {
    display: none;
}
/* ── Map profile panel — close/maximize buttons ── */
#map-profile-panel #map-profile-close {
  position: relative !important;
  top: auto !important;
  right: auto !important;
}
#map-profile-panel #map-profile-toggle-size {
  position: relative;
  font-size: 0.9375rem;
  line-height: 1;
}
#map-profile-panel #map-profile-toggle-size::before {
  content: '';
  display: block;
  width: var(--icon-arrow-size);
  height: var(--icon-arrow-size);
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-image: url('/static/icons/menu/Maximize.svg');
  mask-image: url('/static/icons/menu/Maximize.svg');
  pointer-events: none;
}
/* Restore.svg, not Maximize.svg rotated — a real "shrink back down" glyph
   instead of literally the same icon spun 180°. */
#map-profile-panel.maximized #map-profile-toggle-size::before {
  -webkit-mask-image: url('/static/icons/menu/Restore.svg');
  mask-image: url('/static/icons/menu/Restore.svg');
}
#map-profile-panel #map-profile-close,
#map-profile-panel #map-profile-toggle-size { z-index: 10002; position: relative; }

/* ── Mobile overrides (My Info column layout, edge-to-edge sections) ──
   Deliberately placed at the very end of this file, not inline where
   each rule conceptually belongs (as it originally was) — #my-info-
   section/.my-sites-box's own base rules (border-radius, box-shadow)
   have the exact same specificity (a single id/class) as these
   overrides, and a media query does not win a specificity tie on its
   own; only source order does. Placed earlier in the file, the later,
   unconditional base rules kept winning even on a narrow viewport,
   which is why border-radius/box-shadow silently kept showing despite
   being "fixed" here already. Being last in the file is what makes
   these actually win now. */
@media (max-width: 768px) {
    #profile-view {
        display: grid;
        grid-template-columns: 1fr 1fr;
        column-gap: 14px;
        align-items: start;
    }
    #profile-view p {
        grid-column: 1;
        margin: 0 0 10px;
    }
    #profile-view #view-address {
        grid-column: 1 / -1;
    }
    .profile-info-photo-col {
        grid-column: 2;
        grid-row: 1;
    }
    /* My Info/My Sites/Following/Explore/My TreeCoins run fully
       adjacent, edge to edge — one continuous list instead of a stack
       of separately-rounded, gapped cards. Targeted by id directly
       (rather than .tools-drawer/.my-sites-box) since those classes'
       own margin-top and .tools-drawer + .tools-drawer's adjacent-
       sibling margin are each more specific than a plain class
       override would be — an id here beats all of them regardless of
       which one otherwise wins. */
    #my-info-section,
    #my-sites-section,
    #invited-sites-section,
    #following-sites-section,
    #explore-sites-section,
    #my-treecoins-section {
        margin-top: 0;
        border-radius: 0;
    }
    /* A 1px hairline instead of the removed shadow/glow — contracted
       edge-to-edge with no margin AND no shadow between them, adjacent
       sections read as one merged block with no boundary at all.
       #my-info-section is first (nothing above it to separate from) so
       it's the only one of the six left out. */
    #my-sites-section,
    #invited-sites-section,
    #following-sites-section,
    #explore-sites-section,
    #my-treecoins-section {
        border-top: 1px solid rgba(var(--theme-fg), 0.1);
    }
    /* View-mode icons (grid/thumbnail/list/carousel) only ever showed
       any background at all on :hover — meaningless on a touch screen,
       so every one of them read as flat/non-interactive except
       whichever was already active. Same background every one of them
       already gets on hover (and .active already carries permanently),
       now on by default; opacity still separates active from the rest. */
    .my-sites-view-btn {
        background: var(--glass-button-hover-bg);
    }
    /* The section bar itself (the row reading "Following"/"Explore"/etc,
       full width) only ever got its background on :hover too (styles.css
       #my-info-section > .tools-drawer-summary:hover, .my-sites-box >
       .tools-drawer-summary:hover) — same fix, the same background now
       shows without needing a hover that can't happen on a touch screen.
       No border-radius re-added here — sections are edge-to-edge now
       (above), so a rounded top corner on just the bar would look
       wrong against square section edges. The :hover variant of this
       selector is repeated explicitly (not just the plain one) because
       that original rule's own :hover pseudo-class makes IT more
       specific than a plain override — source order alone (this block
       being last in the file) only wins actual ties, not a selector
       that's genuinely more specific; matching its exact specificity
       here is what let the round corner keep showing on tap/hover. */
    #my-info-section > .tools-drawer-summary,
    #my-info-section > .tools-drawer-summary:hover,
    .my-sites-box > .tools-drawer-summary,
    .my-sites-box > .tools-drawer-summary:hover {
        background: rgba(var(--theme-fg), 0.09);
        border-radius: 0;
    }
    /* Glow/shadow (the card look) removed now that sections sit flush
       against each other rather than as separated floating cards —
       a shadow between two touching edges reads as a seam/dirt line,
       not depth. */
    #my-info-section,
    #my-info-section[open],
    .my-sites-box,
    .my-sites-box[open] {
        box-shadow: none;
    }
    /* Strip and Gallery only — List and Carousel stay desktop-only view
       modes. If either happened to be the active mode already (picked
       on desktop, then the window narrowed), fall back to Gallery so
       there's never a hidden button left switched on with no way to
       tell which view is actually showing. */
    .my-sites-view-btn[data-mode="list"],
    .my-sites-view-btn[data-mode="carousel"] {
        display: none;
    }
    /* Admin/Pitch/Dashboard + Log Out — stacked instead of one wrapping
       row, since sections run edge-to-edge on mobile (above) and this
       row needs its own breathing room back: shortcuts centered with a
       side margin, Log Out on its own line below, right-aligned with
       the same margin. */
    .profile-footer-row {
        flex-direction: column;
        align-items: stretch;
    }
    .profile-admin-shortcuts {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        gap: 8px;
        margin: 0 12px 8px;
    }
    #logout-btn {
        align-self: flex-end;
        margin: 0 12px 0 auto !important;
    }
}

/* ── My Sites hub (desktop) — one connected box, four sections as tabs ──
   #my-sites-hub wraps My Sites/Invited/Following/Explore (html/
   profile.html). Each section keeps its own .my-sites-box look on
   mobile (default, no media query needed — untouched); here on wider
   screens each <details> (.my-sites-box) always stays sized to just
   its own <summary> (flex: 0 0 auto) — its content div is physically
   moved out into the shared #my-sites-hub-content element by JS
   (_syncHubWrapPlacement, profile-panel.js) whenever that section is
   the one open, and moved back when it closes. That's what keeps a
   tab pinned in the tab row when selected: the <details> box never
   grows to hold content, so it never needs to be reflowed onto its own
   line the way an earlier `display: contents` version did (unreliable
   flex-item promotion across browsers — WebKit in particular — was
   losing track of sibling tabs entirely once one section opened). */
@media (min-width: 769px) {
  #my-sites-hub {
    margin-top: 18px;
    display: flex;
    flex-wrap: wrap;
    border-radius: var(--smallcorner);
    overflow: hidden;
    background: rgba(var(--theme-fg), 0.05);
    box-shadow: 0 0 0 1px rgba(255,255,255,0.08), 0 4px 24px rgba(0,0,0,0.18);
  }
  #my-sites-hub .my-sites-box {
    flex: 0 0 auto;
    margin-top: 0;
    width: auto;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }
  /* Tabs: pale by default, sharp on hover (not the reverse — this
     overrides .tools-drawer-summary's own hover rule, which dims), a
     little background fill while hovered, and a light fill + always-
     sharp text while selected — narrower padding than the old vertical-
     accordion header so all four comfortably fit one row. */
  #my-sites-hub .my-sites-box > .tools-drawer-summary {
    padding: 7px 9px;
    border-bottom: 2px solid transparent;
    border-radius: var(--smallcorner) var(--smallcorner) 0 0;
    color: rgba(var(--theme-fg), 0.5);
    background: transparent;
    transition: color 0.15s ease, background-color 0.15s ease;
  }
  #my-sites-hub .my-sites-box > .tools-drawer-summary:hover {
    color: rgb(var(--theme-fg));
    background: rgba(var(--theme-fg), 0.06);
  }
  #my-sites-hub .my-sites-box[open] > .tools-drawer-summary {
    color: rgb(var(--theme-fg));
    background: rgba(var(--theme-fg), 0.1);
    border-bottom-color: rgba(var(--theme-fg), 0.55);
  }
  #my-sites-hub .my-sites-box[open] > .tools-drawer-summary:hover {
    background: rgba(var(--theme-fg), 0.14);
  }
  /* Shared content slot — whichever section's .my-sites-accordion JS
     has moved in here (or empty, e.g. right after the collapse button
     closes everything, in which case :empty hides it so no stray
     border/height is left behind). */
  #my-sites-hub-content {
    flex: 1 1 100%;
    /* min-width:0 — same flex-item min-width:auto floor as
       .my-sites-strip's own fix, one level further up: this slot is
       itself a flex item (of #my-sites-hub, the tab row), and Strip
       view's own unshrinkable cards inside it pushed THIS container's
       effective floor to their full combined width too, overriding
       flex:1 1 100% above and the strip's own min-width:0 fix both —
       confirmed live, the strip was still 9396px wide with that fix
       alone until this one was added as well. */
    min-width: 0;
    order: 5;
    border-top: 1px solid rgba(var(--theme-fg), 0.1);
  }
  #my-sites-hub-content:empty {
    display: none;
  }
  /* Tabs don't each need their own expand/collapse arrow or view-toggle
     row — one shared collapse button and one shared view-toggle row
     (both below) cover the whole bar instead. */
  #my-sites-hub .my-sites-box > .tools-drawer-summary > .crumb-arrow,
  #my-sites-hub .my-sites-box > .tools-drawer-summary > .my-sites-view-toggles {
    display: none;
  }
  /* One line: collapse triangle (left) — tabs (left) — view toggles
     (right, flush — no side padding, so all four fit without wrapping).
     Tabs and the collapse button keep source order (order: 0, the
     default); #my-sites-hub-content's own order: 5 (above) puts it on
     its own full-width row under this one. */
  #my-sites-hub-collapse-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    order: -1;
    width: 26px;
    align-self: stretch;
    padding: 0;
    border: none;
    background: transparent;
    color: rgba(var(--theme-fg), 0.55);
    cursor: pointer;
  }
  #my-sites-hub-collapse-btn:hover {
    color: rgba(var(--theme-fg), 0.9);
  }
  #my-sites-hub-collapse-btn .tri-arrow {
    transition: transform 0.15s ease;
  }
  #my-sites-hub-view-toggles {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    order: 4;
    margin-left: auto;
    padding: 0 4px;
  }
}
@media (max-width: 768px) {
  #my-sites-hub-collapse-btn,
  #my-sites-hub-view-toggles {
    display: none;
  }
}
