/* ==========================================================================
   site.css — reindeer.gift new prototype
   Loaded after main.css/plugins.css: overrides Oomph's split-panel layout
   with a centered content window, adds the snow background, and defines
   the redesigned gift/comment card component.
   ========================================================================== */

/* Oomph's own scrollbar-thumb color (main.css) is #9e2525 — the same red
   used for delete/unclaim actions elsewhere, applied here as a generic
   sitewide default that has nothing to do with "danger", it just clashes
   with the gold/green palette everywhere a scrollbar shows up (most
   noticeably in the comment textareas). Firefox uses scrollbar-color
   instead of the ::-webkit-scrollbar-* pseudo-elements, so both are
   needed for the same fix to apply across browsers. The track/background
   (also themed gray by default, main.css) goes transparent rather than
   another color — a solid gray block behind a gold thumb looked like its
   own separate, unstyled UI element rather than part of the page. */
::-webkit-scrollbar-thumb {
  background-color: #c9a51c;
}

::-webkit-scrollbar-track,
::-webkit-scrollbar {
  background: transparent;
}

* {
  scrollbar-color: #c9a51c transparent;
}

/* ---------- Loading spinner / retry (comments, messages inbox, an open
   thread) — shown only while the very first fetch for that list is in
   flight, see loadComments()/loadConversations()/openThread() in site.js. */

.loading-spinner {
  display: flex;
  justify-content: center;
  padding: 2.5rem 0;
}

.loading-spinner__circle {
  width: 2.4rem;
  height: 2.4rem;
  border: 3px solid rgba(44, 52, 43, 0.15);
  border-top-color: #c9a51c;
  border-radius: 50%;
  animation: site-spin 0.8s linear infinite;
}

@keyframes site-spin {
  to {
    transform: rotate(360deg);
  }
}

.loading-error {
  text-align: center;
  padding: 2.5rem 1.5rem;
  color: #6b6555;
  font-size: 1.3rem;
}

.loading-error__retry {
  display: inline-block;
  margin-top: 0.75rem;
  background: none;
  border: 1px solid rgba(44, 52, 43, 0.2);
  border-radius: 20px;
  padding: 0.4rem 1.2rem;
  font-size: 1.15rem;
  font-weight: 600;
  color: #6b6555;
  cursor: pointer;
}

.loading-error__retry:hover {
  color: #2c342b;
  border-color: #2c342b;
}

/* Only shown while the Hub home-state is active (see site.js) */
.home-state--hub-only {
  display: none;
}
.home-state--hub-only.is-visible {
  display: block;
}

/* Center to match the rest of the centered-content design language
   (the theme's own default here is left-aligned, a leftover from the
   removed split-panel layout). */
.main__dataline {
  text-align: center;
}

/* ---------- Fullscreen snow background (behind everything) ---------- */

#snow-js {
  position: fixed !important;
  top: 0; left: 0; right: 0; bottom: 0;
  width: 100% !important;
  height: 100% !important;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 0%, #3a4638 0%, #232920 55%, #171c15 100%);
}

/* Let the home screen's own backgrounds go transparent so snow shows through */
.main,
.main__content {
  background-color: transparent !important;
}

/* ---------- Transition model: Home is a static base layer; sections are drawers
   that slide in from the right over it, and slide back out to reveal it again.
   (Oomph's original behavior slid Home away instead and faded sections in in
   place — this replaces that, and also fixes the old -50%/50% half-width slide
   values, which were calibrated for the removed two-column layout.) ---------- */

@media only screen and (min-width: 1200px) {
  .menu {
    width: 100%;
  }
}

/* Home never moves */
.main.move-out,
.main.move-in {
  -webkit-transform: none !important;
  -moz-transform: none !important;
  -ms-transform: none !important;
  transform: none !important;
}

/* The hamburger menu shouldn't do its own competing slide-away when a section
   opens (that reads as "a second thing flying across the screen"). It already
   fades via opacity (menu has `transition: all 0.6s`), so just drop its own
   slide and let it disappear cleanly while the section slides in on top. */
.menu.move-out {
  -webkit-transform: none !important;
  -moz-transform: none !important;
  -ms-transform: none !important;
  transform: none !important;
}

/* Sections rest off-screen to the right, and slide to cover the screen when open */
.inner {
  -webkit-transform: translateX(100%);
  -moz-transform: translateX(100%);
  -ms-transform: translateX(100%);
  transform: translateX(100%);
}
.inner.animate-in {
  -webkit-transform: translateX(0);
  -moz-transform: translateX(0);
  -ms-transform: translateX(0);
  transform: translateX(0);
}

/* While closing, .animate-in is still present alongside .animate-out/.to-back
   for part of the sequence — without !important here, the rule above (equal
   specificity, later in source order) would win and pin the section in place,
   so only opacity would visibly change instead of it sliding back out. */
.inner.animate-out,
.inner.to-back {
  -webkit-transform: translateX(100%) !important;
  -moz-transform: translateX(100%) !important;
  -ms-transform: translateX(100%) !important;
  transform: translateX(100%) !important;
}

/* ---------- Home hub ---------- */

/* .main itself normally gets its height from a `height: 100%` chain rooted
   at html/body, which can independently carry the same mobile-viewport bug
   as raw `vh` units (both were historically sized against the largest
   possible viewport, address bar collapsed). Since .main scrolls internally
   (overflow-y: auto from the theme), any extra height here becomes exactly
   the dead scroll space below correctly-centered content. Override it
   directly with the same corrected-height fallback chain used below. */
.main--centered {
  height: 100vh;
  height: calc(var(--vh, 1vh) * 100);
  height: 100dvh;
  scrollbar-gutter: stable both-edges;
}

/* The "scrolls internally" comment above is only true up to 1199px — the
   theme itself sets `.main { overflow: hidden; }` at 1200px+ (main.css),
   which was invisible while Hub content always fit in one screen. Now that
   it can genuinely be taller than the viewport (more tiles, the wish-list
   button), that hidden overflow makes anything past the fold completely
   unreachable, not just awkward to find, no amount of scrolling helps.
   Restoring auto here doesn't change anything when content already fits;
   it only matters once it doesn't. */
@media only screen and (min-width: 1200px) {
  .main--centered {
    overflow-y: auto;
    padding-right: 1.25rem;
    box-sizing: border-box;
  }
}

/* main.css also switches .main__dataline (the account bar) to
   position:absolute at this same breakpoint, pinned near the bottom of
   .main's own fixed-height box. That's fine exactly as long as content
   never grows past one screen — once it does, the bar stays pinned in
   place while the real content scrolls underneath it, hovering over
   whatever happens to land there (the countdown, now) instead of sitting
   after it like a normal page footer would. Putting it back in normal
   flow is what actually matches "naturally at the bottom of the page". */
@media only screen and (min-width: 1200px) {
  .main--centered .main__dataline {
    position: relative;
    bottom: auto;
    left: auto;
    /* Negative on purpose — .hub__stage's own bottom padding (6rem) was
       sized to pull short content (Login/Landing forms) up off
       dead-center, not as spacing before this bar. Safe to adjust here
       rather than there since this element is home-state--hub-only
       (invisible on every screen except Hub), so it can't affect any
       other screen's layout. Nets out to a much smaller, more
       intentional-looking gap above the bar. */
    margin-top: -3rem;
  }
}

/* Real content, not a margin, on purpose — see the HTML comment next to
   this element for why. flex-shrink: 0 keeps it from being squeezed away
   to nothing by the flex column it sits in. */
.hub__bottom-spacer {
  flex-shrink: 0;
  height: 2rem;
}

/* .main--centered is on the <section>, but .main__header/.hub__stage/
   .main__dataline are children of the inner .container-fluid.fullheight,
   not direct children of the section — the flex container needs to go
   there, or it never actually applies to them. */
.main--centered > .container-fluid {
  display: flex;
  flex-direction: column;
  min-height: 100vh; /* absolute fallback if JS is disabled (has the mobile bug) */
  min-height: calc(var(--vh, 1vh) * 100); /* JS-measured real visible height (site.js) — the most reliable cross-browser fix */
  min-height: 100dvh; /* wins over both above when the browser supports it natively, no JS needed */
}

/* The theme floats .main__header out of flow (position: absolute) at
   >=1200px, so it hovers over content instead of scrolling away with it —
   causing it to overlap the text underneath once a home-state's own content
   scrolls (each state manages its own scroll now, see .home-state.is-active
   below). Xavier wants it to stay in normal flow and scroll away with the
   page instead ("fixed on the page, not fixed on the screen"), so keep it
   position: relative at all sizes rather than letting the theme float it. */
.main--centered .main__header {
  position: relative;
}

/* The wordmark is a fixed-size SVG (main.css sets .logo img { width: auto },
   so it renders at its natural ~260px and never shrinks), while
   #menu-trigger sits pinned to the right edge of the same row. On a
   phone there isn't room for both: at 375px the logo ran to 298px and
   the trigger starts at 290px, putting the hamburger lines on top of the
   "S" in GIFTS, and at 320px the overlap grew to 52px. Same root cause
   as the .section-header/.section-close collision fixed earlier —
   nothing reserved space for a control positioned outside the text's own
   flow.
   Reserving that space on .logo (whose box already shares its right edge
   with the trigger) and letting the image shrink to fit is self-limiting:
   max-width only bites once the box is narrower than the logo's natural
   size, so wider screens are untouched. Scoped to phones anyway, since
   that's the range where the collision was actually measured. */
@media only screen and (max-width: 767px) {
  .main--centered .main__header .logo {
    padding-right: 62px;
  }

  .main--centered .main__header .logo img {
    max-width: 100%;
  }
}

/* .hub__stage no longer manages its own scroll or absolute-positions its
   children — only one .home-state is ever in the DOM's layout at a time
   (the rest are display:none), so the whole page (header included) scrolls
   together as one normal unit via .main's own overflow-y: auto, and the
   header genuinely scrolls away with the content instead of hovering fixed
   above a separately-scrolling pane. */
.hub__stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Asymmetric on purpose: less top padding than bottom pulls the
     auto-centered content up a bit, closer to the header, rather than
     sitting at a strict mathematical center that read as "too low". */
  padding: 1rem 1.5rem 6rem;
}

/* ---------- Home states (Landing / Login / Activate / Hub) ----------
   Only .is-active is shown; the rest are fully removed from layout
   (display: none) so an inactive state's content — e.g. Hub's tall
   headline + 4 tiles — can't inflate the page's height while hidden.
   site.js coordinates display:none/block around the opacity fade, since
   display can't itself be transitioned. */

.home-state {
  display: none;
  opacity: 0;
  width: 100%;
  transition: opacity 0.4s ease-in-out;
}

.home-state.is-active {
  display: flex; /* centers .hub__content horizontally via justify-content below */
  justify-content: center;
  opacity: 1;
  /* Main-axis auto-margin centering within .hub__stage's column flex —
     degrades gracefully to top-alignment if content is taller than the
     available space, instead of overflowing symmetrically off both edges. */
  margin-top: auto;
  margin-bottom: auto;
}

.hub__content {
  max-width: 640px;
  width: 100%;
  text-align: center;
}

/* A bit more room for the Hub state specifically, since it has 4 tiles to fit */
.home-state--hub .hub__content {
  max-width: 760px;
}

/* Oomph's .countdown is built to absolutely-position itself over a full-height
   hero section; here it sits inline in the Hub's centered content flow instead. */
.hub-countdown {
  position: static;
  -webkit-transform: none;
     -moz-transform: none;
      -ms-transform: none;
          transform: none;
  width: auto;
  margin-top: 1.5rem; /* now sits right under the greeting H1, not below the grid — tighter, more connected spacing */
}

/* Login / Activate UI */

.auth__buttons {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 360px;
  margin: 2.5rem auto 0;
}

.btn-auth {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 0.9rem 1.5rem;
  border-radius: 30px;
  border: none;
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 1.52rem;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.btn-auth:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
}

/* Real logo files instead of an icon font — sidesteps the font-loading
   race that caused Google/Yahoo's icons to intermittently render as
   missing-glyph boxes (that font only loads once the Login screen becomes
   visible, and sometimes lost the race against the ~3s font-display:block
   grace period). Fixed height, auto width so Yahoo's wider mark isn't
   squished into a square like Google's. */
.btn-auth__icon {
  height: 2rem;
  width: auto;
}

.btn-auth--google {
  background: #fff;
  color: #232920;
}

.btn-auth--yahoo {
  background: #6001d2;
  color: #fff;
}

.btn-auth--email {
  background: transparent;
  color: #f5efe3;
  border: 1px solid rgba(245, 239, 227, 0.5);
}

.activate-form,
.email-auth-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 360px;
  margin: 2.5rem auto 0;
}

.activate-form input,
.email-auth-form input {
  padding: 0.85rem 1.2rem;
  border-radius: 30px;
  border: 1px solid rgba(245, 239, 227, 0.35);
  background: rgba(245, 239, 227, 0.08);
  color: #f5efe3;
  font-size: 1.52rem;
}

.activate-form input::placeholder,
.email-auth-form input::placeholder {
  color: rgba(245, 239, 227, 0.6);
}

/* Purely visual — the actual value is still whatever was typed (lowercase
   included); activate.php uppercases it server-side regardless. This just
   sets the right expectation while typing, since that's how the code is
   actually checked/stored. */
#activate-invite-code {
  text-transform: uppercase;
}

.activate-form .btn,
.email-auth-form .btn {
  margin-top: 0.5rem;
}

.email-auth-actions {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.email-auth-actions .btn {
  /* Oomph's base .btn assumes buttons sit inline with manual right-margin
     spacing; that only strips via :last-of-type, which left the first
     button uneven once these are gap-spaced instead. Neutralize it and
     let flex handle spacing in both the stacked and side-by-side layouts. */
  margin-right: 0;
}

@media (min-width: 640px) {
  .email-auth-actions {
    flex-direction: row;
  }

  .email-auth-actions .btn {
    /* Equal width regardless of "Sign In" vs "Sign Up" text width. */
    flex: 1 1 0;
    padding-left: 0;
    padding-right: 0;
  }
}

.home-back {
  display: inline-block;
  margin-top: 1.75rem;
  background: none;
  border: none;
  color: rgba(245, 239, 227, 0.7);
  font-size: 1.44rem;
  cursor: pointer;
  text-decoration: underline;
}

.home-back:hover {
  color: #f5efe3;
}

.stay-signed-in {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 1.25rem;
  color: rgba(245, 239, 227, 0.8);
  font-family: "Mulish", sans-serif;
  font-size: 1.44rem;
  cursor: pointer;
  user-select: none;
}

.stay-signed-in input[type="checkbox"] {
  width: 1.6rem;
  height: 1.6rem;
  accent-color: #c9a51c;
  cursor: pointer;
}

/* Unlike the other auth screens, Verify Email's button sits directly after
   its paragraph with no wrapping form/button-group element (.auth__buttons /
   .email-auth-form / .activate-form), so it never picked up the same
   margin-top those give — match it here for the same visual gap. */
#verify-email-continue {
  margin-top: 2.5rem;
}

.forgot-password-link {
  display: inline-block;
  margin-top: 1rem;
  color: rgba(245, 239, 227, 0.6);
  font-size: 1.36rem;
  text-decoration: underline;
}

/* Both Verify Email (resend link + back button) and Email (forgot-password
   link + back button) have two of these links stacked below their form —
   being inline-block by default otherwise lets them sit side by side if
   there's room, which reads as cramped rather than as two distinct actions.
   Force each onto its own line here without changing how they behave on
   Login/Forgot Password/Activate (those only ever have one such link, so
   this was never visible there). display:block alone isn't enough — a
   block box no longer centers via the parent's text-align (that only
   affects inline-level content), and drifts to the left edge instead.
   width:fit-content + auto side-margins restores the centering without
   touching each element's own margin-top. */
.home-state--verify-email .forgot-password-link,
.home-state--verify-email .home-back,
.home-state--email .forgot-password-link,
.home-state--email .home-back {
  display: block;
  width: fit-content;
  margin-left: auto;
  margin-right: auto;
}

.forgot-password-link:hover {
  color: #f5efe3;
}

.form-message {
  display: none;
  max-width: 360px;
  margin: 1.5rem auto 0;
  font: normal 400 1.44rem/1.5 "Mulish", sans-serif;
  color: #f5efe3;
}

.form-message.is-visible {
  display: block;
}

.form-message.is-error {
  color: #ff8a80;
}

/* .form-message's default colors (#f5efe3/#ff8a80) assume the dark auth
   screens it was built for — the Account section's avatar/photo area
   sits on a white .background-light panel instead, where that off-white
   text would be nearly invisible. */
.form-message--on-light {
  color: #2c342b;
}

.form-message--on-light.is-error {
  color: #9e2525;
}

.btn-auth:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn-auth:disabled:hover {
  transform: none;
  box-shadow: none;
}

/* ---------- Site-wide error banner ---------- */

.site-error-banner {
  position: fixed;
  top: 0.75rem;
  left: 50%;
  transform: translateX(-50%) translateY(-0.5rem);
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  max-width: calc(100% - 2rem);
  background: #5c2018;
  border: 1px solid #c9a51c;
  border-radius: 8px;
  padding: 0.75rem 1rem;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
}

.site-error-banner[hidden] {
  display: flex; /* keep transitioning instead of the attribute's default display:none */
}

.site-error-banner.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

.site-error-banner__text {
  font: normal 400 1.52rem/1.4 "Mulish", sans-serif;
  color: #ffffff;
}

.site-error-banner__close {
  flex-shrink: 0;
  border: none;
  background: transparent;
  color: rgba(255, 255, 255, 0.7);
  font-size: 2.24rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

.site-error-banner__close:hover {
  color: #ffffff;
}

.hub__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.25rem;
  margin-top: 3rem;
}

/* 3-across gives a clean 2-row layout for 6 tiles (was 4-across, back when
   there were only 4 tiles to show) */
@media (min-width: 640px) {
  .hub__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 479px) {
  .hub__grid {
    grid-template-columns: 1fr;
  }
}

/* ---------- Hamburger menu: resized for 6 entries ----------
   The theme's own sizing (main.css) was built for a dramatic 3-4-item
   marketing nav — link text alone scales up to 7rem (70px) at large
   desktop widths, plus 1.4rem vertical padding per item. That's fine for
   4 items but pushes 6 past the viewport height, forcing a scroll on
   desktop where none is wanted (mobile scrolling is fine, per Xavier).
   Overriding both the font sizes AND the padding together, since the
   mismatch is the scale itself, not just spacing. */
.navigation li {
  padding: 1rem 0;
}
.navigation li span {
  font-size: 2.2rem;
}
.navigation li a {
  font-size: 3.6rem;
}
@media only screen and (min-width: 768px) {
  .navigation li a {
    font-size: 4rem;
  }
}
@media only screen and (min-width: 1200px) {
  .navigation li span {
    font-size: 2.4rem;
  }
}
@media only screen and (min-width: 1400px) {
  .navigation li a {
    font-size: 4.6rem;
  }
}

/* main.css only defines staggered entrance timing up through the 5th nav
   item (built for a max of 5); 6th and 7th need the same treatment
   following the same +0.1s-per-item pattern. */
.menu.animate-in .transition-el-6 {
  transition: opacity 0.3s 1.2s, transform 0.3s 1.2s;
}
.menu.animate-in .transition-el-7 {
  transition: opacity 0.3s 1.3s, transform 0.3s 1.3s;
}

.hub__tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 2rem 1rem;
  border-radius: 14px;
  background: rgba(245, 239, 227, 0.06);
  border: 1px solid rgba(201, 165, 28, 0.35);
  color: #f5efe3;
  text-decoration: none;
  transition: transform 0.3s ease, background 0.3s ease, border-color 0.3s ease;
}

/* Count of unread threads (not messages) — set from session.php on page
   load (before My Messages has ever been opened) and kept live after
   that by loadConversations() itself, see site.js. */
.hub__tile-badge {
  position: absolute;
  top: -0.6rem;
  right: -0.6rem;
  min-width: 1.7rem;
  height: 1.7rem;
  padding: 0 0.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: #c9a51c;
  color: #2c342b;
  font-family: "Mulish", sans-serif;
  font-size: 1.15rem;
  font-weight: 700;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

.hub__tile-badge[hidden] {
  display: none;
}

.hub__tile:hover {
  transform: translateY(-6px);
  background: rgba(201, 165, 28, 0.12);
  border-color: #c9a51c;
  color: #f5efe3;
}

.hub__tile-icon {
  font-size: 3.2rem;
  color: #c9a51c;
  margin-bottom: 0.25rem;
}

.hub__tile-title {
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 1.84rem;
}

.hub__tile-text {
  font-size: 1.36rem;
  opacity: 0.75;
}

/* Standalone featured button — deliberately separate from .hub__grid, not
   just a bigger tile within it. My Wish List is the single most frequent
   action on this page, so it gets its own prominent spot above the grid
   rather than competing equally with everything else. */
.hub__hero-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  width: 100%;
  margin-top: 3rem;
  padding: 1.6rem 2rem;
  border-radius: 20px;
  background: #c9a51c;
  color: #2c342b;
  text-decoration: none;
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 2rem;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.hub__hero-btn i {
  font-size: 2.2rem;
}

.hub__hero-btn:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.3);
  color: #2c342b;
}

/* Family Chat, sitting directly on the Hub page below the tile grid rather
   than behind a tile — .hub__content has text-align:center for the
   headline content above it, which would otherwise center every line of
   chat text and the form controls too. */
.hub__chat {
  margin-top: 3rem;
  text-align: left;
}

.hub__chat-divider {
  height: 1px;
  margin-bottom: 2rem;
  background: linear-gradient(to right, transparent, rgba(201, 165, 28, 0.5), transparent);
}

.hub__chat-title {
  /* The theme's own h3 { color: #0A0A0A } (main.css) has no h3.light
     counterpart the way h1.light exists — only h1 got that treatment —
     so the .light class on this element was never actually doing
     anything for color. Set directly instead of relying on it. */
  color: #f5efe3;
  text-align: center;
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 2rem;
  margin-bottom: 1.25rem;
}

/* The standalone .inner sections get their white card look for free from
   the theme's own .panel class (background + rounding + shadow) — there's
   no such wrapper here, so .comment-thread needs its own version of that
   same treatment to read as a card floating on the dark Hub background. */
.comment-thread--panel {
  background: #fff;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}

/* ---------- Centered content sections (About / Gift Lists / My Claims) ---------- */

.inner--centered .inner__content {
  float: none;
}

.inner {
  scrollbar-gutter: stable both-edges;
}

.inner--centered .panel {
  border-radius: 18px;
  margin: 0 auto 2.5rem;
  max-width: 100%;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
}

.inner--centered .inner__block.panel {
  padding: 3rem 0;
}

.inner--centered .inner__block.panel:first-of-type {
  border-radius: 0 0 18px 18px;
}

@media (min-width: 1200px) {
  .inner--centered .inner__block.panel {
    padding: 3.5rem 0;
  }
}

@media only screen and (min-width: 1200px) {
  .inner__content {
    scrollbar-gutter: stable both-edges;
    padding-right: 1.25rem;
    box-sizing: border-box;
  }
}

/* ---------- Accordion (About section) ---------- */

.accordion-item {
  border-bottom: 1px solid #eee6d6;
}

.accordion-item:last-child {
  border-bottom: none;
}

.accordion-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  background: none;
  border: none;
  padding: 1.25rem 0;
  cursor: pointer;
  text-align: left;
}

.accordion-header .section__subtitle {
  margin: 0;
}

.accordion-icon {
  flex-shrink: 0;
  color: #c9a51c;
  font-size: 1.4rem;
  transition: transform 0.2s ease;
}

.accordion-item.is-open .accordion-icon {
  transform: rotate(90deg);
}

.accordion-panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.accordion-item.is-open .accordion-panel {
  max-height: 30rem;
}

.accordion-panel .section__text {
  padding-bottom: 1.25rem;
}

/* ---------- Gift list "whose list" tile menu ---------- */

/* Fixed 2-wide grid of large tiles, not the small auto-fill grid this
   used before the Gift List view became its own real page — with
   fewer, more deliberate destinations to choose from (one per family
   member) each one can afford to be a big, easy target rather than a
   dense row of small icons. Single column once there's no room for two
   at a reasonable size (matches the existing 768px breakpoint used
   elsewhere in this file). */
.giftlist-menu {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}

@media (max-width: 768px) {
  .giftlist-menu {
    grid-template-columns: 1fr;
  }
}

.giftlist-menu__tile {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  text-align: left;
  text-decoration: none;
  color: inherit;
  padding: 1.75rem 2rem;
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.06);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

/* A non-email visual cue that this person's list has changed since it
   was last opened — a small dot rather than reusing .hub__tile-badge's
   numeric-count shape, since there's nothing to count here (one list,
   either seen or not). */
.giftlist-menu__tile--unseen::after {
  content: "";
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 0.9rem;
  height: 0.9rem;
  border-radius: 50%;
  background: #c9a51c;
  box-shadow: 0 0 0 3px rgba(201, 165, 28, 0.25);
}

.giftlist-menu__tile:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.12);
  color: inherit;
}

.giftlist-menu__tile img {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid #c9a51c;
  flex-shrink: 0;
}

.giftlist-menu__tile--me {
  border: 2px solid #c9a51c;
}

.giftlist-menu__name {
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 2rem;
}

.giftlist-menu__tile small {
  display: block;
  color: #c9a51c;
  font-style: italic;
  font-size: 1.28rem;
  margin-top: 0.25rem;
}

/* ---------- Gift / comment card component ---------- */

/* Fixed 2 columns at every width, not auto-fill and not a responsive
   step-down — the design call is that grid vs. list is the owner's
   presentation choice (per section) and column count isn't a separate
   knob on top of that, so it stays constant from mobile to desktop
   rather than reading as a different layout depending on screen size. */
.gc-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}

@media (max-width: 479px) {
  .gc-grid {
    gap: 0.75rem;
  }

  .gc-grid .gc-card {
    padding: 0.85rem;
  }

  .gc-grid .gc-title {
    font-size: 1.4rem;
  }

  .gc-grid .gc-desc {
    font-size: 1.2rem;
  }

  .gc-grid .gc-meta {
    font-size: 1.05rem;
  }

  .gc-grid .gc-footer {
    margin-top: 0.75rem;
  }

  .gc-grid .gc-btn {
    font-size: 1.1rem;
    padding: 0.35rem 0.7rem;
  }

  .gc-grid .gc-badge {
    font-size: 1.05rem;
    padding: 0.3rem 0.6rem;
  }
}

.gc-card {
  position: relative;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.07);
  padding: 1.25rem;
  transition: transform 0.25s ease, box-shadow 0.25s ease;
  display: flex;
  flex-direction: column;
}

/* SortableJS's own state classes during a drag — a faint highlight on
   the placeholder slot and the element actually being dragged, so the
   interaction has some visual feedback beyond the browser's bare
   default. */
.sortable-ghost {
  opacity: 0.4;
}

.sortable-chosen {
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
}

.gc-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 14px 30px rgba(0, 0, 0, 0.12);
}

/* The whole tile opens the item's detail page (see the delegated click
   handler in site.js) — a pointer cursor over the card background is
   what actually signals that, since the hover-lift above already
   applies to every .gc-card regardless of whether it's clickable. */
.giftlist-item-card {
  cursor: pointer;
}

/* Same reasoning as .giftlist-item-card above — clicking a My Claims
   tile jumps to that item's own detail page. */
.my-claims-card {
  cursor: pointer;
}

/* My Wish List's own editing cards — the whole tile opens the item
   editor (or, for a note, its inline edit form) and is also the
   press-and-hold drag target (see initWishlistSortable() in site.js),
   so `grab` reads truer here than a plain pointer would. */
.wishlist-item-card,
.wishlist-note-card {
  cursor: grab;
}

.wishlist-item-card:active,
.wishlist-note-card:active {
  cursor: grabbing;
}

.gc-card--gift.is-claimed-by-me {
  border: 2px solid #c9a51c;
}

.gc-media {
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 1rem;
  background: #f4f1e6;
}

.gc-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.gc-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}

.gc-title {
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 1.84rem;
  color: #2c342b;
  margin: 0;
  line-height: 1.3;
}

.gc-qty {
  flex-shrink: 0;
  font-family: "Cinzel", serif;
  font-weight: 700;
  color: #c9a51c;
  font-size: 1.6rem;
  background: #f4f1e6;
  border-radius: 20px;
  padding: 0.15rem 0.6rem;
}

.gc-desc {
  font-size: 1.52rem;
  color: #444;
  margin: 0.5rem 0 0;
}

.gc-meta {
  font-size: 1.25rem;
  font-style: italic;
  color: #9a9384;
  margin-top: 0.5rem;
}

.gc-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 1rem;
  flex-wrap: wrap;
}

.gc-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 1.31rem;
  font-weight: 600;
  padding: 0.35rem 0.75rem;
  border-radius: 20px;
}

.gc-badge--open {
  background: #f4f1e6;
  color: #6b6555;
}

.gc-badge--partial {
  background: #fbe8c6;
  color: #8a5a00;
}

.gc-badge--full {
  background: #2c342b;
  color: #c9a51c;
}

.gc-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: none;
  border-radius: 20px;
  padding: 0.4rem 0.9rem;
  font-size: 1.36rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, transform 0.15s ease;
}

.gc-btn:active {
  transform: translateY(1px);
}

.gc-btn--claim {
  background: #c9a51c;
  color: #2c342b;
}

.gc-btn--claim:hover {
  background: #b3910c;
}

.gc-btn--unclaim {
  background: transparent;
  color: #9e2525;
  border: 1px solid #9e2525;
}

.gc-btn--unclaim:hover {
  background: #9e2525;
  color: #fff;
}

/* Distinct from --claim/--unclaim on purpose — those two are wired to the
   mock claim/unclaim toggle in site.js (`.gc-btn--claim` click handler), so
   reusing either class here would make an "Edit" button silently flip
   itself into "Unclaim" when clicked. */
.gc-btn--edit {
  background: transparent;
  color: #2c342b;
  border: 1px solid rgba(44, 52, 43, 0.35);
}

.gc-btn--edit:hover {
  background: #2c342b;
  color: #fff;
}

.gc-claimants {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0.6rem 0 0;
  border-top: 1px solid #eee6d6;
  font-size: 1.28rem;
  color: #6b6555;
}

.gc-claimants li {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  /* Space between the label and a per-claim retract button, when one
     is present — harmless with a single child (no retract control),
     which just sits flush left under space-between regardless. */
  justify-content: space-between;
}

.gc-claimants li + li {
  margin-top: 0.7rem;
}

.gc-claimants li i {
  color: #2c9e4a;
  font-size: 1.2rem;
}

.gc-claimants li.is-me {
  color: #8a5a00;
  font-weight: 600;
}

/* Comment card variant */

.gc-card--comment {
  background: #f4f1e6;
  justify-content: center;
  min-height: 160px;
}

.gc-quote-icon {
  color: #c9a51c;
  font-size: 2rem;
  margin-bottom: 0.5rem;
  opacity: 0.7;
}

.gc-comment-text {
  font-style: italic;
  font-size: 1.68rem;
  color: #2c342b;
  margin: 0;
}

/* Same red the site already uses for every other destructive hover
   state (.comment-item__delete-btn, etc.) — kept as its own variant
   rather than reusing .gc-btn--unclaim, since that class is wired to
   the claim/unclaim toggle specifically and reusing it here would make
   a "Delete" button silently behave like "Unclaim" if that handler ever
   changes. */
.gc-btn--delete {
  background: transparent;
  color: #9e2525;
  border: 1px solid rgba(158, 37, 37, 0.35);
}

.gc-btn--delete:hover {
  background: #9e2525;
  color: #fff;
}

/* ---------- My Wish List: sections, entry forms ---------- */

.wishlist-header__actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

/* Session-level controls (Edit List / Save Draft / Publish / Discard)
   — a distinct tinted, bordered chip so this row reads as "a different
   kind of button" at a glance, not just visually separated by
   position from Add Item/Note/Section below. Gold-tinted specifically
   (not the site's dark-green default) since gold is already this
   site's accent color for "the thing that matters most on this
   screen" elsewhere (Claim buttons, badges). Present (and harmless as
   a single-button chip) in the read view too, where it's just Edit
   List — same visual language for "this button controls the editing
   session" in both places. */
.wishlist-mode-actions {
  padding: 0.85rem 1rem;
  margin-bottom: 1.1rem;
  background: rgba(201, 165, 28, 0.08);
  border: 1px solid rgba(201, 165, 28, 0.3);
  border-radius: 10px;
}

.wishlist-entry-form {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.wishlist-entry-form__name,
.wishlist-entry-form__description,
.wishlist-entry-form__quantity,
.wishlist-entry-form__layout {
  width: 100%;
  padding: 0.9rem 1.2rem;
  border-radius: 8px;
  border: 1px solid rgba(44, 52, 43, 0.2);
  background: #fff;
  color: #2c342b;
  font-size: 1.36rem;
  font-family: "Mulish", sans-serif;
}

.wishlist-entry-form__description {
  resize: vertical;
  min-height: 5.5rem;
}

.wishlist-entry-form__qty-label {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 1.28rem;
  color: #6b6555;
}

.wishlist-entry-form__qty-label .wishlist-entry-form__quantity,
.wishlist-entry-form__qty-label .wishlist-entry-form__layout {
  width: auto;
  flex: 0 0 auto;
}

.wishlist-entry-form__field-label {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* Shared by every small field-group heading in the item editor (Name,
   Quantity, Links, Images) — bigger and bolder than the old muted
   caption style, specifically so it reads clearly as a heading next to
   the smaller "Primary" badge on the Links field, which the old,
   barely-bigger style didn't. */
.wishlist-field-label {
  font-size: 1.55rem;
  font-weight: 700;
  color: #2c342b;
}

.wishlist-quantity-field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.wishlist-quantity-field__row {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.wishlist-quantity-field__row .wishlist-entry-form__quantity {
  width: auto;
  flex: 0 0 auto;
}

.wishlist-quantity-unlimited {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 1.5rem;
  color: #6b6555;
  cursor: pointer;
}

/* main.css has a blanket "form input { height: 4.4rem; margin: 0 0
   2rem; }" meant for text inputs — it was also stretching this
   checkbox to 44px tall with a 20px bottom margin, which is why the
   row looked vertically off against the small icon/text next to it.
   Not really an icon-alignment problem — the checkbox itself was the
   wrong size. Reset back to its natural small checkbox size. */
.wishlist-entry-form__unlimited-check {
  display: inline-block;
  width: auto;
  height: auto;
  margin: 0;
  padding: 0;
}

.wishlist-entry-form__quantity:disabled {
  background: #f4f1e6;
  color: #9a9384;
  cursor: not-allowed;
}

.wishlist-entry-form__actions {
  display: flex;
  gap: 0.75rem;
}

/* Sits below the edit form as its own panel (see the HTML comment in
   index.html on why it can't just be a second <form> nested inside
   that one) — same field rhythm as .wishlist-entry-form via the shared
   gap, just not itself a <form>. */
.wishlist-remove-panel {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(44, 52, 43, 0.12);
}

/* Same reasoning as .comment-form[hidden] elsewhere in this file — a
   plain class selector's display:flex above wins a same-specificity
   tie against (rather than losing to) the browser's own
   [hidden]{display:none} by cascade order, so toggling the hidden
   attribute alone wouldn't actually hide this without this override. */
.wishlist-remove-panel[hidden] {
  display: none;
}

.wishlist-remove-panel__intro {
  font-size: 1.3rem;
  color: #6b6555;
  margin: 0;
}

/* One row per Hidden item — name/removal details on the left, Restore
   pinned to the right, same left-content/right-action shape as a
   message-list row. */
.wishlist-hidden-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 0;
  border-bottom: 1px solid rgba(44, 52, 43, 0.1);
}

.wishlist-hidden-item:last-child {
  border-bottom: none;
}

.wishlist-hidden-item__body {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}

.wishlist-hidden-item__name {
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 1.5rem;
  color: #2c342b;
}

.wishlist-hidden-item__meta {
  font-size: 1.2rem;
  font-style: italic;
  color: #9a9384;
}

/* ---------- Item editor: full-screen view ---------- */

/* Bigger than the shared .message-thread__title default (1.36rem) —
   scoped to this one id rather than changing that class itself, so
   Messages' own thread header stays exactly as it was. This is a
   full-screen title, not an inbox thread subject line, and read as
   too small at the same size as that. */
#wishlist-item-editor-title,
#wishlist-item-preview-title {
  font-size: 1.8rem;
}

.wishlist-preview-disclaimer {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 1.25rem 0;
  padding: 0.9rem 1.2rem;
  border-radius: 8px;
  background: #f4f1e6;
  color: #6b6555;
  font-size: 1.2rem;
}

.wishlist-preview-desc {
  font-size: 1.36rem;
  color: #2c342b;
  margin: 0.5rem 0;
}

/* Same reset-collision as the real editor's own rich-text output
   (.wishlist-richtext-editor) — plugins.css's `font: inherit`/
   `list-style: none` strips the browser defaults for b/i/lists, so
   this needs the identical restoration wherever rich description HTML
   renders outside the editor itself. */
.wishlist-preview-desc b,
.wishlist-preview-desc strong {
  font-weight: 700;
}

.wishlist-preview-desc i,
.wishlist-preview-desc em {
  font-style: italic;
}

.wishlist-preview-desc ul,
.wishlist-preview-desc ol {
  margin: 0;
  padding-left: 1.5rem;
}

.wishlist-preview-desc ul {
  list-style: disc;
}

.wishlist-preview-desc ol {
  list-style: decimal;
}

/* This is the eventual item-inspection page, not the compact grid
   tile — a single column, full width, room for a real image gallery
   and every link, not just a cover photo and a primary link. */
.wishlist-preview-detail {
  max-width: 640px;
  margin: 0 auto;
}

.wishlist-preview-gallery__main {
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: 10px;
  overflow: hidden;
  background: #f4f1e6;
  margin-bottom: 0.75rem;
}

.wishlist-preview-gallery__main img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.wishlist-preview-gallery__thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 1.5rem;
}

.wishlist-preview-gallery__thumbs img {
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 8px;
  cursor: pointer;
  opacity: 0.7;
  outline: 2px solid transparent;
  outline-offset: 2px;
  transition: opacity 0.15s ease, outline-color 0.15s ease;
}

.wishlist-preview-gallery__thumbs img:hover {
  opacity: 0.9;
}

.wishlist-preview-gallery__thumbs img.is-active {
  opacity: 1;
  outline-color: #c9a51c;
}

.wishlist-preview-detail__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  /* Now sits below the gallery (moved back per Xavier's call) rather
     than leading the page — needs its own top spacing since the
     gallery has no bottom margin of its own to provide it. Harmless
     when there's no gallery (add mode, pre-first-photo) too, since
     it just adds a bit of breathing room under the panel's own
     padding instead. */
  margin: 1rem 0 0.5rem;
}

.wishlist-preview-detail__name {
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 2.1rem;
  color: #2c342b;
  margin: 0;
}

/* The bare .wishlist-field-label span just before this has no margin
   of its own (its other uses all sit inside a flex parent that
   handles spacing via gap) — scoped here so it doesn't crowd whatever
   came before it in this plain block-flow context. */
.wishlist-preview-detail .wishlist-field-label {
  display: block;
  margin-top: 1.25rem;
}

.wishlist-preview-links {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0.5rem 0 1rem;
}

.wishlist-preview-link {
  color: #2c342b;
  text-decoration: none;
  font-size: 1.28rem;
}

.wishlist-preview-link:hover {
  text-decoration: underline;
}

.wishlist-preview-link--primary {
  font-weight: 700;
  color: #8a5a00;
}

/* Its own card, not just another stacked block — this is the one part
   of the page someone's actually here to act on (claim), sitting right
   after the gallery and ahead of the description/links so a long
   description never stands between "I opened this" and "I can claim
   it." Bigger badge/button than the base .gc-badge/.gc-btn (which stay
   their normal compact size everywhere else — the #works mockup, and
   eventually the real Gift List viewer) since this is meant to read as
   a clearly separate, easy-to-hit action area. */
.wishlist-preview-claims {
  background: #f4f1e6;
  border-radius: 10px;
  padding: 1.25rem 1.5rem;
  margin: 1.25rem 0;
}

.wishlist-preview-claims .gc-footer {
  margin-top: 0;
}

.wishlist-preview-claims .gc-badge {
  font-size: 1.5rem;
  padding: 0.55rem 1.1rem;
}

.wishlist-preview-claims .gc-btn {
  font-size: 1.5rem;
  padding: 0.75rem 1.5rem;
}

/* Claim disables at the quantity cap — same dimmed/no-cursor treatment
   used for other disabled controls on this page, scoped here rather
   than site-wide since no other .gc-btn use sets the disabled
   attribute yet. */
.wishlist-preview-claims .gc-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Shared toggle for both the item-level (detail page body) and
   list-level (detail-view header) Watch buttons — same pill shape as
   .message-thread__archive-btn, its own class rather than reusing that
   one since it's wired to a different pair of endpoints per level
   (watch/unwatch item vs. watch/unwatch list) and shouldn't silently
   inherit Archive's own click handler if that ever changes. */
.giftlist-watch-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: none;
  border: 1px solid rgba(44, 52, 43, 0.2);
  border-radius: 20px;
  padding: 0.4rem 1rem;
  font-size: 1.15rem;
  font-weight: 600;
  color: #6b6555;
  cursor: pointer;
  margin-left: auto;
}

.giftlist-watch-btn:hover {
  color: #2c342b;
  border-color: #2c342b;
}

.giftlist-watch-btn.is-watching {
  color: #2c342b;
  border-color: #c9a51c;
  background: #c9a51c;
}

.giftlist-watch-btn.is-watching:hover {
  background: #b3910c;
  border-color: #b3910c;
}

/* The item-level button sits in the detail body, not the header — it
   has no header flex-row to be pushed right by, so the shared class's
   margin-left: auto would just collapse to nothing here; unset it and
   give it its own breathing room under the name/qty row instead. */
.giftlist-watch-item-btn {
  margin-left: 0;
  margin-top: 0.75rem;
}

.wishlist-preview-claims .gc-btn--claim:disabled:hover {
  background: #c9a51c;
}

/* Its own background distinct from the muted card around it, rather
   than the plain top-border separator .gc-claimants uses elsewhere —
   a real sub-panel for "who's already claimed this" rather than a
   quiet trailing list. */
.wishlist-preview-claims .gc-claimants {
  background: #fff;
  border-top: none;
  border-radius: 8px;
  margin: 1rem 0 0;
  padding: 0.9rem 1.1rem;
}

/* Shared between the Preview simulation and the real Gift List cards —
   both need the exact same "claim anonymously" checkbox, per-claim
   label, and per-claim retract button. Named generically (gc-*, not
   wishlist-preview-*) since Preview was only ever the first of two real
   consumers, not the only one. The label's icon and text are wrapped
   in their own flex span (rather than left as direct li children) so
   li's own gap/justify-content only ever has two items — the label and
   the button — to space apart, keeping the icon-to-text gap fixed
   regardless of that. */
.gc-claimant-label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.gc-claim-remove-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  border: 1px solid #9e2525;
  background: transparent;
  color: #9e2525;
  cursor: pointer;
  font-size: 1.1rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.4rem 0.8rem;
  border-radius: 20px;
  white-space: nowrap;
}

.gc-claim-remove-btn:hover {
  background: #9e2525;
  color: #fff;
}

/* Same flex/gap/color shape as .message-compose__anonymous — a plain
   checkbox + label row read the same way in both places. */
.gc-claim-anon {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.9rem;
  font-size: 1.2rem;
  color: #6b6555;
}

/* Same reset as .message-compose__anonymous-check — a lone class
   already beats the blanket "form input" rule on specificity, this
   just resets the properties that rule would otherwise set. */
.gc-claim-anon-check {
  display: inline-block;
  width: auto;
  height: auto;
  margin: 0;
}

/* Claims History — the full log of every claim/unclaim event ever, not
   just current state, so it deliberately reads differently from Active
   Claims above it: a plain trailing list (no muted card background),
   since this is reference material to scroll past, not the thing
   someone's here to act on. Item detail page only. */
.wishlist-claims-history {
  margin-top: 1.5rem;
}

.wishlist-claims-history-list {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  font-size: 1.28rem;
  color: #6b6555;
}

.wishlist-claims-history-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0;
  border-top: 1px solid #eee6d6;
}

.wishlist-claims-history-item:first-child {
  border-top: none;
}

.wishlist-claims-history-item i {
  color: #9a9384;
  font-size: 1.2rem;
}

.wishlist-claims-history-empty {
  font-style: italic;
  color: #9a9384;
}

.wishlist-claims-history-show-more {
  padding-top: 0.9rem;
  text-align: center;
}

/* Same label-above-field shape as .wishlist-quantity-field — extra
   margin-top for breathing room after Images, same value used there. */
.wishlist-description-field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.75rem;
}

.wishlist-richtext-field {
  display: flex;
  flex-direction: column;
  border: 1px solid rgba(44, 52, 43, 0.2);
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
}

.wishlist-richtext-toolbar {
  display: flex;
  gap: 0.25rem;
  padding: 0.5rem;
  background: #f4f1e6;
  border-bottom: 1px solid rgba(44, 52, 43, 0.2);
}

.wishlist-richtext-btn {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  border: none;
  background: transparent;
  color: #6b6555;
  cursor: pointer;
  font-size: 0.95rem;
}

.wishlist-richtext-btn:hover {
  background: rgba(44, 52, 43, 0.1);
  color: #2c342b;
}

/* Touch selection (iOS/Android) pops up a native copy/cut/paste bubble
   right next to wherever you've selected text — it's OS-level UI, not
   part of the page, so no z-index here can win against it. The only
   real fix is keeping the toolbar out of the space directly above the
   text, which is exactly where that bubble wants to render. Below this
   breakpoint (or on any coarse/touch pointer, regardless of screen
   width — covers a touchscreen at desktop width, or a phone driving a
   desktop-size viewport through remote-control software) the toolbar
   moves below the text box instead of above it, via flex `order`
   (higher than the editor's default 0, not equal — equal order falls
   back to DOM order, which is toolbar-first), and grows to an actual
   touch target size. */
@media (max-width: 768px), (pointer: coarse) {
  .wishlist-richtext-toolbar {
    order: 1;
    border-bottom: none;
    border-top: 1px solid rgba(44, 52, 43, 0.2);
    gap: 0.5rem;
    padding: 0.6rem;
  }

  .wishlist-richtext-btn {
    width: 44px;
    height: 44px;
    font-size: 1.2rem;
  }
}

.wishlist-richtext-editor {
  min-height: 8rem;
  padding: 0.9rem 1.2rem;
  font-size: 1.36rem;
  font-family: "Mulish", sans-serif;
  color: #2c342b;
  outline: none;
}

.wishlist-richtext-editor:empty::before {
  content: attr(data-placeholder);
  color: #9a9384;
}

/* Same reset-collision as the b/i rule below — plugins.css sets
   `ol, ul { list-style: none; }` site-wide, so insertUnorderedList/
   insertOrderedList were building correct <ul>/<ol><li> structure with
   no visible bullets/numbers to show for it. Restored explicitly per
   list type rather than a shared rule, since ul and ol need different
   markers. */
.wishlist-richtext-editor ul,
.wishlist-richtext-editor ol {
  margin: 0;
  padding-left: 1.5rem;
}

.wishlist-richtext-editor ul {
  list-style: disc;
}

.wishlist-richtext-editor ol {
  list-style: decimal;
}

/* The site's CSS reset (plugins.css, Eric Meyer's) sets `font: inherit`
   on b/i/strong/em/u alike — that shorthand wipes out the browser's
   default bold/italic styling but leaves text-decoration untouched,
   which is why underline "worked" and bold/italic silently didn't.
   Restoring the two here explicitly rather than relying on the UA
   default the reset already removed. */
.wishlist-richtext-editor b,
.wishlist-richtext-editor strong {
  font-weight: 700;
}

.wishlist-richtext-editor i,
.wishlist-richtext-editor em {
  font-style: italic;
}

/* ---------- Item editor: images (act immediately) ---------- */

/* Extra breathing room above Images specifically — the form's own
   uniform gap between all fields reads fine everywhere else, but felt
   too tight right after the links list (which already has its own
   "+ Add Link" row immediately before this one). */
.wishlist-item-editor-images {
  margin-top: 0.75rem;
}

.wishlist-image-thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.wishlist-image-thumb {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: 8px;
  overflow: hidden;
  background: #f4f1e6;
}

/* Cover photo indicator — outline rather than a text badge, which
   wouldn't have room to sit legibly on an 80px thumbnail. Same gold
   accent used for the primary link badge elsewhere in this editor.
   outline-offset keeps it from touching the image itself. */
.wishlist-image-thumb--primary {
  outline: 2px solid #c9a51c;
  outline-offset: 2px;
}

.wishlist-image-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.wishlist-image-thumb__delete {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  font-size: 0.9rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.wishlist-image-thumb__move {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  background: rgba(0, 0, 0, 0.55);
}

.wishlist-image-thumb__move button {
  flex: 1;
  border: none;
  background: none;
  color: #fff;
  padding: 0.25rem 0;
  cursor: pointer;
  font-size: 0.85rem;
}

.wishlist-image-thumb__move button:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.wishlist-image-upload-btn {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: 8px;
  border: 2px dashed rgba(44, 52, 43, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #9a9384;
  cursor: pointer;
  font-size: 1.5rem;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.wishlist-image-upload-btn:hover {
  border-color: #c9a51c;
  color: #c9a51c;
}

/* Absolutely positioned rather than stacked in flow below the icon —
   that way the + icon stays exactly centered in the box regardless of
   the label's presence, and the text just pins to the bottom edge
   without needing to shrink or reflow anything else. color: inherit
   is what keeps it matching the button's own color in both states
   (default grey, gold on hover) with no separate hover rule needed. */
.wishlist-image-upload-btn__text {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6px;
  text-align: center;
  font-size: 1.05rem;
  font-family: "Mulish", sans-serif;
  line-height: 1;
  white-space: nowrap;
  color: inherit;
}

/* Without this, the [hidden] attribute on the real file input has no
   effect — main.css has a blanket "form input, form textarea { display:
   block; }" rule, and an author stylesheet rule always beats the
   browser's own built-in [hidden]{display:none} regardless of
   specificity (origin precedence, not a specificity contest — [hidden]
   is a user-agent-stylesheet rule, not an authored one). Same root
   cause as the other [hidden] overrides already in this file, just
   triggered by a different conflicting rule. Without this, the native
   "Choose File" button renders right next to the + icon and spills out
   of the dashed box. The item editor no longer has its own inline
   upload input at all (photos come from the picker screen now) — this
   now guards the picker's own upload input instead. */
.wishlist-image-picker-upload-input[hidden] {
  display: none;
}

/* ---------- Item editor: links (part of Save) ---------- */

.wishlist-link-rows-field {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  align-items: flex-start;
  width: 100%;
}

.wishlist-link-rows {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: 100%;
}

.wishlist-link-row {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

/* Fixed width regardless of how many of the 3 buttons inside are
   actually showing — otherwise hiding one via display:none frees up
   space that the flex: 2 / flex: 1 url/label fields immediately
   absorb, visibly resizing those fields row to row. 3 buttons × 28px +
   2 gaps × 0.5rem holds all three at once; justify-content: flex-start
   is what makes fewer buttons slide left within this fixed box rather
   than staying pinned to the right edge. */
.wishlist-link-row__actions {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.5rem;
  flex-shrink: 0;
  width: 94px;
}

/* Move Up on the first row / Move Down on the last are dead clicks, and
   the primary row's Remove is never clickable at all — all three use
   display:none (not visibility) so the remaining buttons in that row
   collapse together and slide left to fill the gap, rather than
   leaving isolated buttons floating with dead space around them.
   Covers the single-link case for free, since that row is
   simultaneously --primary and --last. Only the badge below still uses
   the visibility trick, since the URL/label columns starting the row
   are what actually benefit from staying aligned — the trailing
   buttons don't need to. */
.wishlist-link-row--primary .wishlist-link-row__move-up,
.wishlist-link-row--last .wishlist-link-row__move-down,
.wishlist-link-row--primary .wishlist-link-row__remove {
  display: none;
}

/* The primary badge always renders (even on non-primary rows, just
   hidden via visibility not display) so every row's URL/label inputs
   stay column-aligned regardless of which row currently holds it. */
.wishlist-link-row__primary-badge {
  flex-shrink: 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: #c9a51c;
  white-space: nowrap;
  visibility: hidden;
}

.wishlist-link-row--primary .wishlist-link-row__primary-badge {
  visibility: visible;
}

/* With only one link, there's nothing for "Primary" to distinguish it
   from yet — stays hidden even though that lone row is still
   --primary underneath (Remove still needs to stay disabled on it).
   3-class selector so this reliably wins over the rule above
   regardless of source order, rather than relying on which one
   happens to come later in the file. */
.wishlist-link-rows--single .wishlist-link-row--primary .wishlist-link-row__primary-badge {
  visibility: hidden;
}

.wishlist-link-row__url {
  flex: 2;
  min-width: 0;
  padding: 0.6rem 0.9rem;
  border-radius: 8px;
  border: 1px solid rgba(44, 52, 43, 0.2);
  font-size: 1.2rem;
  font-family: "Mulish", sans-serif;
}

.wishlist-link-row__label {
  flex: 1;
  min-width: 0;
  padding: 0.6rem 0.9rem;
  border-radius: 8px;
  border: 1px solid rgba(44, 52, 43, 0.2);
  font-size: 1.2rem;
  font-family: "Mulish", sans-serif;
}

.wishlist-link-row__move-up,
.wishlist-link-row__move-down,
.wishlist-link-row__remove {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid rgba(44, 52, 43, 0.2);
  background: #fff;
  color: #6b6555;
  cursor: pointer;
  font-size: 0.9rem;
}

.wishlist-link-row__remove:hover {
  border-color: #9e2525;
  color: #9e2525;
}

/* Same understated look as .btn-small--cancel, deliberately its own
   class rather than reusing that one — see the comment where this
   class is applied in site.js for why. */
.wishlist-add-link-row-btn {
  background: transparent;
  color: #6b6555;
  text-decoration: underline;
}

.wishlist-add-link-row-btn:hover {
  color: #2c342b;
}

.wishlist-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.wishlist-section-title {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  /* Takes the remaining space so the drag handle and edit button stay
     put at either end regardless of title length, rather than relying
     on the header's own justify-content: space-between to keep three
     children (handle/title/edit) apart — which only reads right for
     exactly two. */
  flex: 1;
  font-family: "Cinzel", serif;
  font-size: 1.8rem;
  color: #2c342b;
  margin: 0;
}

.wishlist-section-drag-handle {
  background: none;
  border: none;
  padding: 0.3rem;
  color: #9a9384;
  cursor: grab;
  font-size: 1.3rem;
  flex-shrink: 0;
}

.wishlist-section-drag-handle:hover {
  color: #2c342b;
}

.wishlist-section-drag-handle:active {
  cursor: grabbing;
}

/* The default catch-all grid — no header, no rounded/backgrounded
   container (unlike .wishlist-section below), just the entries
   themselves sitting above the real sections. Margin instead of a
   .panel's own spacing, since there's no panel here to carry it. */
.wishlist-default-grid {
  margin-bottom: 2.5rem;
}

.wishlist-section-edit-btn {
  background: none;
  border: none;
  padding: 0;
  color: #9a9384;
  cursor: pointer;
  font-size: 1.3rem;
}

.wishlist-section-edit-btn:hover {
  color: #2c342b;
}

/* List layout: single column, cards read top-to-bottom in position
   order — the default, and the one that keeps a note's "get this or
   that" meaning unambiguous relative to its neighbors. Grid is the
   opt-in alternative (.gc-grid, already defined above), chosen per
   section rather than site-wide. */
.gc-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* ---------- Bottom account bar (Hub state only) ---------- */

.account-bar {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 1.05rem 0.55rem 0.55rem;
  border-radius: 30px;
  background: rgba(245, 239, 227, 0.08);
  border: 1px solid rgba(245, 239, 227, 0.2);
}

.account-bar__profile {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  color: #f5efe3;
  text-decoration: none;
  transition: opacity 0.2s ease;
}

.account-bar__profile:hover {
  opacity: 0.8;
  color: #f5efe3;
}

.account-bar__avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  border: 1.5px solid #c9a51c;
}

.account-bar__name {
  font-size: 1.52rem;
  font-weight: 600;
}

.account-bar__divider {
  color: rgba(245, 239, 227, 0.4);
}

.account-bar__logout {
  font-size: 1.52rem;
  color: rgba(245, 239, 227, 0.7);
  text-decoration: underline;
}

.account-bar__logout:hover {
  color: #f5efe3;
}

/* ---------- Events ---------- */

.event-list {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.event-card {
  display: flex;
  gap: 1.25rem;
  align-items: flex-start;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.07);
  padding: 1.25rem 1.5rem;
}

.event-date {
  flex-shrink: 0;
  width: 64px;
  text-align: center;
  background: #2c342b;
  color: #c9a51c;
  border-radius: 12px;
  padding: 0.6rem 0;
}

.event-date__day {
  display: block;
  font-family: "Cinzel", serif;
  font-weight: 700;
  font-size: 2.4rem;
  line-height: 1;
}

.event-date__month {
  display: block;
  text-transform: uppercase;
  font-size: 1.12rem;
  letter-spacing: 0.05em;
  margin-top: 0.2rem;
}

.event-title {
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 1.84rem;
  color: #2c342b;
  margin: 0 0 0.35rem;
}

.event-meta {
  font-size: 1.36rem;
  color: #9a9384;
  margin: 0 0 0.5rem;
}

.event-meta i {
  color: #c9a51c;
  margin-right: 0.2rem;
}

.event-desc {
  font-size: 1.52rem;
  color: #444;
  margin: 0;
}

/* ---------- Account ---------- */

.account-avatar-panel {
  display: flex;
  justify-content: center;
}

.account-avatar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.8rem;
  max-width: 32rem;
  text-align: center;
}

.account-avatar img {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid #c9a51c;
}

.account-avatar__text {
  margin: 0;
  font-size: 1.36rem;
  color: #6b6555;
}

.account-avatar .form-message {
  margin: 0.25rem 0 0;
}

.account-avatar .btn-auth {
  min-width: 18rem;
  background: #2c342b;
  color: #ffffff;
  border: 1px solid #2c342b;
}

.account-avatar .btn-auth:hover {
  background: #565d55;
  border-color: #565d55;
}

/* ---------- My Images (Account section) ----------
   Deliberately separate classes from the wishlist item editor's own
   .wishlist-image-thumb, even though the visual treatment is
   identical — these two image systems aren't connected yet (this
   library is step one of a bigger decoupling of photos from specific
   wishlist items, still in progress), and this page's own thumbnails
   have no per-item "cover photo" or manual ordering concept to carry
   over. Consolidate into one shared set of classes once the wishlist
   editor actually starts picking from this library instead of
   uploading directly to an item. */

.user-images-count {
  margin: 0.4rem 0 0;
  font-size: 1.2rem;
  color: #6b6555;
}

.user-images-toolbar {
  margin-bottom: 1rem;
}

/* Same dimmed/no-cursor disabled treatment used elsewhere on this page
   (e.g. the preview claim buttons) — shown once the account's 200
   image cap is reached, so there's nothing left to click into. */
.user-image-upload-trigger:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.user-image-thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.user-image-thumb {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: 8px;
  overflow: hidden;
  background: #f4f1e6;
}

.user-image-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.user-image-thumb__delete {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  font-size: 0.9rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Fixed 80px tiles are a sensible dense grid on desktop, but they're
   both too small to comfortably tap and too small to tell apart on a
   phone. A real 3-column grid instead of "however many 80px tiles
   happen to fit" makes each tile scale up with the screen — bigger
   photo, bigger delete target — same touch breakpoint used elsewhere
   in this file (screen width OR a direct coarse-pointer check, so a
   touchscreen at desktop width still gets it). */
@media (max-width: 768px), (pointer: coarse) {
  .user-image-thumbs {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.6rem;
  }

  .user-image-thumb {
    width: auto;
    height: auto;
    aspect-ratio: 1;
  }

  .user-image-thumb__delete {
    width: 32px;
    height: 32px;
    top: 5px;
    right: 5px;
    font-size: 1.2rem;
  }

  /* .btn-small's default padding/font-size reads fine for the other
     small text buttons on this page, but this is the one people are
     most likely to reach for right after opening this panel on a
     phone — worth a genuine touch-sized target rather than the same
     compact sizing every other small button here uses. Two classes
     (not just .user-image-upload-trigger alone) so this reliably beats
     .btn-small's own rule regardless of which one happens to come
     later in the file — same equal-specificity/source-order gotcha
     already hit a few times elsewhere in this file. */
  .btn-small.user-image-upload-trigger {
    padding: 0.75rem 1.4rem;
    font-size: 1.3rem;
  }
}

/* Same main.css "form input { display: block }" collision as the
   wishlist item editor's own upload input — see the detailed comment
   at .wishlist-image-upload-input[hidden] for the full explanation. */
.user-image-upload-input[hidden] {
  display: none;
}

.user-images-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 1.25rem;
}

/* Shared with the item editor's own image picker screen — same pager,
   different class names on its buttons only (so the two screens'
   delegated click handlers, both bound broadly on document, can never
   double-fire on each other's Prev/Next). */
.user-images-pager__prev,
.user-images-pager__next,
.wishlist-image-picker-pager__prev,
.wishlist-image-picker-pager__next {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid rgba(44, 52, 43, 0.25);
  background: #fff;
  color: #2c342b;
  cursor: pointer;
}

.user-images-pager__prev:hover,
.user-images-pager__next:hover,
.wishlist-image-picker-pager__prev:hover,
.wishlist-image-picker-pager__next:hover {
  border-color: #c9a51c;
  color: #c9a51c;
}

.user-images-pager__prev:disabled,
.user-images-pager__next:disabled,
.wishlist-image-picker-pager__prev:disabled,
.wishlist-image-picker-pager__next:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  border-color: rgba(44, 52, 43, 0.25);
  color: #2c342b;
}

.user-images-pager__status,
.wishlist-image-picker-pager__status {
  font-size: 1.2rem;
  color: #6b6555;
}

/* The picker's own thumbnails are click-to-select, not delete targets
   — a hover cue makes that obvious even though the tile itself has no
   other interactive children the way the My Images/item editor
   versions do. */
.wishlist-image-picker-thumb {
  cursor: pointer;
  transition: opacity 0.15s ease, outline-color 0.15s ease;
  outline: 2px solid transparent;
  outline-offset: 2px;
}

.wishlist-image-picker-thumb:hover {
  opacity: 0.85;
  outline-color: #c9a51c;
}

.wishlist-image-picker-url-row {
  display: flex;
  gap: 0.75rem;
  margin-top: 0.5rem;
  align-items: center;
}

/* Not inside a <form>, so the site-wide "form input" block-stretch
   rule doesn't reach this one — but reset explicitly anyway, the same
   defensive pattern used at every other input-outside-a-form in this
   file, so it can't silently break if this ever moves inside one. */
.wishlist-image-picker-url-input {
  display: block;
  flex: 1;
  height: auto;
  margin: 0;
  padding: 0.6rem 0.9rem;
  font-size: 1.3rem;
  border: 1px solid #d8d2c0;
  border-radius: 8px;
}

.wishlist-image-picker-url-row .btn-small {
  flex-shrink: 0;
}

/* This panel is its own separate .background-light block (unlike
   .account-fields above, which sits on the section's dark opening
   panel) — dark text on purpose, not the pale account-fields color. */
.account-section-title {
  margin: 0 0 1.25rem;
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 1.6rem;
  color: #2c342b;
}

.account-settings {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.account-settings__row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 1.36rem;
  color: #444;
  cursor: pointer;
}

/* ---------- Account: Watching list ---------- */

/* Sits inside the same Notifications panel as the two global toggles
   above, separated by a rule rather than split into its own panel —
   it's the same subject ("what emails you"), just expressed as a list
   of individual subscriptions instead of a pair of switches. */
.watching-block {
  margin-top: 2rem;
  padding-top: 1.75rem;
  border-top: 1px solid #eee6d6;
}

.watching-block__title {
  margin: 0 0 0.4rem;
  font-family: "Cinzel", serif;
  font-size: 1.5rem;
  font-weight: 600;
  color: #2c342b;
}

.watching-block__intro {
  margin: 0 0 1.25rem;
  font-size: 1.25rem;
  color: #6b6555;
}

.watching-group {
  margin-bottom: 1.5rem;
}

.watching-group:last-child {
  margin-bottom: 0;
}

.watching-group__label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #9a9384;
}

.watching-row {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid #f4f1e6;
}

.watching-row:last-child {
  border-bottom: none;
}

.watching-row__avatar,
.watching-row__thumb {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  object-fit: cover;
}

.watching-row__avatar {
  border-radius: 50%;
}

.watching-row__thumb {
  border-radius: 6px;
}

/* Holds the same 32px slot as a real thumbnail so every row's name
   starts at the same left edge — see the comment where this is
   rendered in site.js. */
.watching-row__thumb--empty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #f4f1e6;
  font-size: 1.2rem;
  color: #c9bfa4;
}

/* A real button (it opens that item/list), styled as a plain link so
   it reads as the row's own label rather than competing with the X
   next to it for "this is the action here." */
.watching-row__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  border: none;
  background: none;
  padding: 0;
  text-align: left;
  font-size: 1.3rem;
  font-weight: 600;
  color: #2c342b;
  cursor: pointer;
}

.watching-row__name:hover {
  color: #b3910c;
  text-decoration: underline;
}

.watching-row__owner {
  flex-shrink: 0;
  font-size: 1.15rem;
  font-style: italic;
  color: #9a9384;
}

.watching-row__remove {
  flex-shrink: 0;
  border: none;
  background: none;
  padding: 0.3rem 0.5rem;
  font-size: 1.3rem;
  line-height: 1;
  color: #9a9384;
  cursor: pointer;
}

.watching-row__remove:hover {
  color: #9e2525;
}

.watching-empty {
  margin: 0;
  font-size: 1.25rem;
  font-style: italic;
  color: #9a9384;
}

/* The owner suffix is the first thing worth dropping on a narrow
   screen — the item name and the X are what actually matter here, and
   which list it's on is recoverable by just opening it. */
@media only screen and (max-width: 600px) {
  .watching-row__owner {
    display: none;
  }
}

.account-security {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.account-security__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.account-security__hint {
  margin: 0;
  font-size: 1.15rem;
  color: #6b6555;
}

/* ---------- My Wish List ---------- */

/* Same icon used on the matching Hub tile — repeated here so a section
   carries its own visual identity over from the tile you actually
   clicked to get here, rather than that association only existing on
   the Hub screen. Not the Hub tile's own gold, though — that's the
   site's "act on this" accent color (buttons, links, active states),
   and reused here it made a plain decorative icon look like a control.
   #6b6555 is the site's own muted secondary-text tone, already used for
   de-emphasized copy elsewhere (.message-item__preview, etc.). */
.section-header {
  display: flex;
  align-items: center;
  gap: 2.25rem;
  /* The theme keeps .inner__container's own right padding and
     .section-close's (X) `right` offset locked to the same value at
     every breakpoint (10% / 8rem / 10rem) — meaning the X's 24px-wide
     box sits flush against the content area's own right edge, eating
     into it rather than living in genuinely reserved space outside
     it. A heading that legitimately fills its box right up to that
     edge (any of this site's longer ones — "Gift Lists", "My Wish
     List", "My Messages", "My Account" — not just at phone widths, any
     width where the layout is still single-column) runs straight
     under the X. Reserving a bit more room here, only for this row,
     is what actually keeps clear of it — shrinking the heading
     wrapper alone (see the min-width: 0 rule below) still lets text
     legally reach that same shared edge, since the edge itself is the
     problem, not the wrapper's ability to shrink. */
  padding-right: 3rem;
}

/* The h2/subtitle wrapper is a flex item with no shrink floor by
   default (min-width: auto), so at narrower widths it won't shrink
   below the heading's own unbroken text width — it just overflows the
   header's box instead of wrapping. Needed alongside the padding-right
   above: without this, a long heading would rather overflow past even
   that reserved edge than wrap onto a second line. */
.section-header > div {
  flex: 1;
  min-width: 0;
}

.section-header__icon {
  flex-shrink: 0;
  /* Deliberately bigger than the h2 text box itself, not just matched to
     it — matching size 1:1 still read visually smaller than the h2 once
     rendered, since the icon glyph fills its box edge-to-edge while the
     heading's own capital letters (Cinzel) only fill a portion of theirs.
     Sized to actually dominate/anchor the header the way the reference
     showed, not just sit alongside it at the same scale. */
  font-size: 6.5rem;
  color: #6b6555;
}


@media (min-width: 768px) {
  .section-header__icon {
    font-size: 7.5rem;
  }
}

/* ---------- My Messages ---------- */

.message-list {
  display: flex;
  flex-direction: column;
}

.message-item {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.5rem;
  text-decoration: none;
  color: inherit;
  border-bottom: 1px solid #eee6d6;
  transition: background 0.2s ease;
}

.message-item:last-child {
  border-bottom: none;
}

.message-item:hover {
  background: #f9f6ee;
  color: inherit;
}

.message-item__avatar {
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
}

.message-item__avatar--anon {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #2c342b;
  color: #c9a51c;
  font-size: 1.6rem;
}

.message-item__body {
  flex: 1;
  min-width: 0;
}

.message-item__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}

/* The subject is the row's primary title now (matching the open-thread
   header's own title/subtitle order) — .message-item__with below is the
   "Conversation with X" line, one step down in visual weight. */
.message-item__subject {
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 1.36rem;
  color: #2c342b;
}

.message-item__time {
  flex-shrink: 0;
  font-size: 1.12rem;
  color: #9a9384;
}

.message-item__with {
  display: block;
  margin: 0.15rem 0 0;
  font-size: 1.15rem;
  color: #9a9384;
}

.message-item__with,
.message-thread__with {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.message-item__with-text,
.message-thread__with-text {
  min-width: 0;
}

.message-thread__with-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.message-anon-badge {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.22rem 0.6rem;
  border-radius: 999px;
  background: rgba(44, 52, 43, 0.08);
  color: #6b6555;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}

.message-anon-badge i {
  font-size: 0.9em;
}

.message-anon-badge--revealed {
  background: rgba(201, 165, 28, 0.14);
  color: #2c342b;
}

.message-item__preview {
  margin: 0.2rem 0 0;
  font-size: 1.36rem;
  color: #6b6555;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.message-item.is-unread .message-item__subject,
.message-item.is-unread .message-item__preview {
  color: #2c342b;
  font-weight: 600;
}

/* A leading dot rather than new markup — .is-unread is already toggled
   correctly per row (site.js), this just gives it a clearer "something's
   new here" marker than bold text alone was. */
.message-item.is-unread .message-item__subject::before {
  content: "";
  display: inline-block;
  width: 0.8rem;
  height: 0.8rem;
  margin-right: 0.5rem;
  border-radius: 50%;
  background: #c9a51c;
  vertical-align: middle;
}

.message-inbox__header {
  padding: 0 1.5rem 1.25rem;
}

/* No color set here inherits the site's global (light/cream) body text
   color, which is invisible on this panel's white background — this
   panel needs its own dark color like every other white-panel text
   elsewhere (.message-item__subject, .comment-item__text, etc.). */
.message-list__empty {
  margin: 0;
  padding: 0 1.5rem 1.25rem;
  font-size: 1.3rem;
  color: #6b6555;
}

.message-inbox__header .btn {
  width: 100%;
  /* Deliberately left fully square — unlike the reply box's rounded
     bottom, this button is meant to stand out from the rest of the
     rounded card, not blend into its shape. */
}

/* The accordion pattern (see "Accordion (About section)" below) assumes
   its own horizontal padding comes from a padded parent — that's true in
   About, but this whole panel is .no-padding so .message-list's rows can
   run edge-to-edge. Restoring the padding here just on the accordion
   header/panel keeps it lined up with .message-item's own 1.5rem sides
   instead of sitting flush against the panel edge. */
.message-archive .accordion-header {
  padding: 1.25rem 1.5rem;
}

.message-archive .accordion-panel.is-open,
.message-archive.is-open .accordion-panel {
  max-height: none;
}

.message-archive .message-list--archived {
  max-height: 24rem;
  overflow-y: auto;
}

.message-archive .message-list__empty {
  padding: 0 1.5rem 1.25rem;
}

/* Same pill treatment for both, and the same icon+text combination the
   thread header's own Archive/Restore toggle uses — an icon-only button
   read as unclear on its own, and text-only here would've been
   inconsistent with that other one. */
.message-item__restore-btn,
.message-item__archive-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: none;
  border: 1px solid rgba(44, 52, 43, 0.2);
  border-radius: 20px;
  padding: 0.4rem 1rem;
  font-size: 1.15rem;
  font-weight: 600;
  color: #6b6555;
  cursor: pointer;
}

.message-item__restore-btn:hover,
.message-item__archive-btn:hover {
  color: #2c342b;
  border-color: #2c342b;
}

/* ---------- Compose / thread header (My Messages) ---------- */

.message-thread__header {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid #eee6d6;
}

/* Same root cause as .section-header's own right-edge fix above, one
   level worse here: .section-header never overrides .inner__container's
   own responsive padding (0 10% / 8rem / 10rem — the exact values
   .section-close's own `right` offset is kept in lockstep with at
   every breakpoint), so its content naturally lines up with the X.
   This header overrides that down to a flat 1.5rem for its own
   compact, close-to-the-edge look — which means its content box
   extends 10%-1.5rem (base), 6.5rem (>=1200px), or 8.5rem (>=1400px)
   further right than where the X actually sits, deep past it. A long
   title's own flex/min-width/overflow truncation (below) only clips
   against that oversized box, so plenty of real text can still render
   fully within it, right through the X, without ever engaging the
   ellipsis. Restoring the container's own real right padding here —
   plus the same +3rem buffer for the X's own width the section-header
   fix uses — is what actually keeps clear, same as there; `calc()`
   lets the base rule mix the container's percentage with the flat
   buffer in one declaration. */
.message-thread__header {
  padding-right: calc(10% + 3rem);
}
@media only screen and (min-width: 1200px) {
  .message-thread__header {
    padding-right: 11rem;
  }
}
@media only screen and (min-width: 1400px) {
  .message-thread__header {
    padding-right: 13rem;
  }
}

.message-back {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0;
  font-size: 1.6rem;
  color: #6b6555;
  cursor: pointer;
}

.message-back:hover {
  color: #2c342b;
}

.message-thread__avatar-wrap {
  flex-shrink: 0;
}

.message-thread__avatar {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
}

/* Same masked-identity treatment as .message-item__avatar--anon and
   .message-bubble__avatar--anon — width/height/border-radius already
   come from the shared .message-thread__avatar class above. */
.message-thread__avatar--anon {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #2c342b;
  color: #c9a51c;
  font-size: 1.6rem;
}

.message-thread__heading {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* Subject is the primary title, "Conversation with X" (.message-thread__with
   below) is the subtitle — subject is what you're actually here to read,
   who it's with is secondary context, same ordering as the inbox row's
   own .message-item__subject/__with above. */
.message-thread__title {
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 1.36rem;
  color: #2c342b;
}

/* Unlike the Messages thread header, where .message-thread__title sits
   inside .message-thread__heading (already flex: 1; min-width: 0), the
   Gift List headers use this title as a bare flex item alongside the
   back button — with no shrink floor it just grows to fit a long list
   owner name or item name, pushing the header's own box wider than its
   container and running the text underneath the theme's absolutely-
   positioned .section-close (X) button, which isn't part of this flex
   row at all and so never fights back for space. Capping the title
   itself to shrink-and-truncate keeps the header's box within its
   container no matter how long the name is, which is what actually
   keeps clear of the X — its position never depends on this box. */
#giftlist-detail-title,
#giftlist-item-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.message-thread__with {
  font-size: 1.15rem;
  color: #9a9384;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Same pill treatment as the inbox row's own Archive/Restore buttons —
   an icon-only toggle here read as unclear the same way theirs did. */
/* The Gift List detail header's own second row, sitting below
   .message-thread__header's border rather than crammed into that same
   flex row — the header row is already fighting the theme's own
   absolutely-positioned section-close (X) button for the same corner,
   and a right-pushed watch toggle there collided with it. Plain
   .inner__container's own base padding (0 10%) and 5rem margin-bottom
   are wrong here (misaligned from the header's tighter 1.5rem inset,
   and way too much trailing space for a single button row) — this
   overrides both. */
.giftlist-detail-actions {
  display: flex;
  justify-content: flex-end;
  padding: 1rem 1.5rem 0;
  margin-bottom: 0;
}

/* .inner__container's own base 5rem margin-bottom normally collapses
   away via its :last-of-type rule when the header is the only
   container in the block — true everywhere else this class is used,
   but no longer true here now that .giftlist-detail-actions follows
   it. Without this override that unwanted 5rem reappears as a huge
   gap above the watch button, on top of .giftlist-detail-actions' own
   1rem top padding. */
#giftlist-detail-view .message-thread__header {
  margin-bottom: 0;
}

.message-thread__archive-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: none;
  border: 1px solid rgba(44, 52, 43, 0.2);
  border-radius: 20px;
  padding: 0.4rem 1rem;
  font-size: 1.15rem;
  font-weight: 600;
  color: #6b6555;
  cursor: pointer;
}

.message-thread__archive-btn:hover {
  color: #2c342b;
  border-color: #2c342b;
}

.message-thread__reveal-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: none;
  border: 1px solid rgba(44, 52, 43, 0.2);
  border-radius: 20px;
  padding: 0.4rem 1rem;
  font-size: 1.15rem;
  font-weight: 600;
  color: #6b6555;
  cursor: pointer;
}

.message-thread__reveal-btn:hover {
  color: #2c342b;
  border-color: #2c342b;
}

.message-thread__reveal-btn[hidden] {
  display: none;
}

.message-thread__identity-notice {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 1rem 1.5rem 0;
  padding: 1rem 1.25rem;
  border: 1px solid #eee6d6;
  border-radius: 14px;
  background: #f9f6ee;
  color: #2c342b;
}

.message-thread__identity-notice[hidden] {
  display: none;
}

.message-thread__identity-notice i {
  color: #c9a51c;
  font-size: 1.1em;
}

.message-thread__identity-notice-text {
  font-size: 1.15rem;
  font-weight: 600;
}

/* Filled gold once archived (Restore) — same "this is the state that
   needs attention" treatment .btn-small--save uses elsewhere, rather
   than just a color change on an otherwise-identical outline. */
.message-thread__archive-btn.is-archived {
  color: #2c342b;
  border-color: #c9a51c;
  background: #c9a51c;
}

.message-thread__archive-btn.is-archived:hover {
  background: #b3910c;
  border-color: #b3910c;
}

/* ---------- Message bubbles ---------- */

.message-thread__list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1.5rem;
}

/* Both wraps are sticky (not fixed) so they stay within the panel's own
   width instead of the full viewport (this panel is a centered card
   with open space on either side at desktop widths; position:fixed
   would float the buttons out in that empty space instead of over the
   card). Whichever of #messages/.inner__content actually scrolls at the
   current breakpoint (see getMessagesScrollEl() in site.js) is what
   "top"/"bottom" here stick against. pointer-events:none on the wrap
   (and auto on the button itself) keeps the empty space on either side
   of the centered button from blocking clicks on whatever's underneath. */
.message-thread__top-wrap,
.message-thread__scroll-actions {
  position: sticky;
  display: flex;
  justify-content: center;
  padding: 0 1.5rem;
  pointer-events: none;
  z-index: 2;
}

.message-thread__top-wrap {
  top: 1rem;
}

.message-thread__scroll-actions {
  bottom: 1rem;
}

.message-thread__top-btn,
.message-thread__reply-jump-btn {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: none;
  border-radius: 20px;
  padding: 0.6rem 1.1rem;
  font-size: 1.15rem;
  font-weight: 600;
  color: #2c342b;
  background: #c9a51c;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
  cursor: pointer;
}

.message-thread__top-btn:hover,
.message-thread__reply-jump-btn:hover {
  background: #b3910c;
}

.message-thread__top-btn {
  border-radius: 50%;
  padding: 0.7rem;
}

/* Same reasoning as .comment-form[hidden] elsewhere in this file — these
   buttons' own display:inline-flex is equal specificity to (and later
   than) the browser's [hidden]{display:none}, so toggling the hidden
   attribute alone wouldn't actually hide them without this override. */
.message-thread__top-btn[hidden],
.message-thread__reply-jump-btn[hidden] {
  display: none;
}

/* Full-width off-colored rows rather than left/right-aligned chat
   bubbles — with every message already carrying its own avatar/name
   (see renderMessageBubble() in site.js), a narrow aligned bubble was
   reading too much like a texting app, which isn't the tone here.
   .message-thread__list's own flex-direction:column already stretches
   each row to the container's full width by default (no explicit
   width/align-self needed). */
.message-bubble {
  padding: 1rem 1.25rem;
  border-radius: 8px;
  background: #f9f6ee;
}

.message-bubble--mine {
  background: #eee6d6;
}

.message-bubble__header {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin-bottom: 0.4rem;
}

.message-bubble__avatar {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
}

.message-bubble__avatar--anon {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #2c342b;
  color: #c9a51c;
  font-size: 1.1rem;
}

.message-bubble__sender {
  font-size: 1.2rem;
  font-weight: 600;
  color: #2c342b;
}

.message-bubble__text {
  margin: 0;
  font-size: 1.36rem;
  color: #444;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.message-bubble--deleted .message-bubble__text {
  font-style: italic;
  color: #9a9384;
}

.message-bubble__meta {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.3rem;
}

.message-bubble__time {
  font-size: 1.05rem;
  color: #9a9384;
}

.message-bubble__edited-tag {
  font-size: 1.05rem;
  font-style: italic;
  color: #9a9384;
}

.message-bubble__edit-btn,
.message-bubble__delete-btn {
  background: none;
  border: none;
  padding: 0;
  font-size: 1.05rem;
  font-weight: 600;
  color: #9a9384;
  cursor: pointer;
  text-decoration: underline;
}

.message-bubble__edit-btn:hover {
  color: #2c342b;
}

.message-bubble__delete-btn:hover {
  color: #9e2525;
}

.message-thread__archived-notice {
  margin: 0;
  padding: 1rem 1.5rem;
  font-size: 1.2rem;
  color: #9a9384;
  border-top: 1px solid #eee6d6;
}

.message-thread__form {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  margin: 0 1.5rem 1.5rem;
  width: calc(100% - 3rem);
  box-sizing: border-box;
  padding: 1rem 1.25rem;
  border: 1px solid #eee6d6;
  border-radius: 14px;
  background: #f9f6ee;
}

/* Same reasoning as .comment-form[hidden] elsewhere in this file — this
   rule's own display:flex is equal specificity to (and later than) the
   browser's [hidden]{display:none}, so .prop("hidden", true) alone
   doesn't actually hide the reply form on an archived thread without
   this override. */
.message-thread__form[hidden] {
  display: none;
}

.message-thread__form .message-thread__input {
  flex: 1;
  /* This textarea had no styling of its own before — it was inheriting
     nothing but the theme's generic border:none/transparent-background
     reset (main.css), so on some mobile browsers it fell back to native
     textarea chrome (square corners, its own default border) instead of
     the site's own look. Same treatment as .comment-form__input/
     .message-compose__input elsewhere, for the same reason. */
  resize: none;
  height: 8.6rem;
  min-height: 40px;
  max-height: 140px;
  padding: 0.9rem 1.2rem;
  border-radius: 8px;
  border: 1px solid rgba(44, 52, 43, 0.2);
  background: #fff;
  color: #2c342b;
  font-size: 1.36rem;
  font-family: "Mulish", sans-serif;
}

/* A gold focus ring on whatever text field currently has focus, across
   every text input/textarea/select in Messages and comments — without
   one, a textarea with nothing typed in it yet gave no visual sign you
   were actually in it, which is especially easy to lose track of on
   mobile once the keyboard has shoved the rest of the page (including
   the "back to top" button) out of view. */
.comment-form__input:focus,
.message-thread__input:focus,
.message-compose__input:focus,
.message-compose__subject:focus,
.message-compose__recipient-select:focus {
  outline: none;
  border-color: #c9a51c;
  box-shadow: 0 0 0 3px rgba(201, 165, 28, 0.25);
}

/* ---------- Compose (New Message) ---------- */

.message-compose__form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.5rem;
}

.message-compose__field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  font-size: 1.2rem;
  font-weight: 600;
  color: #6b6555;
}

.message-compose__recipient-select,
.message-compose__subject,
.message-compose__input {
  font-family: "Mulish", sans-serif;
  font-size: 1.36rem;
  color: #2c342b;
  border: 1px solid rgba(44, 52, 43, 0.2);
  border-radius: 8px;
  padding: 0.7rem 1rem;
  background: #fff;
  /* The theme's own "form input, form textarea" rule (main.css) sets a
     2rem bottom margin meant for its own stacked contact-form fields —
     this form uses its own gap between fields instead. */
  margin: 0;
}

.message-compose__input {
  resize: none;
  height: 8.6rem;
  min-height: 40px;
  max-height: 140px;
}

.message-compose__anonymous {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 1.2rem;
  color: #6b6555;
}

/* Same theme-wide "form input" rule as above forces every <input> in any
   <form> to display:block/width:100%/height:4.4rem — fine for the text
   fields, but it stretches this checkbox to the same full-width block,
   which is what made it render as a giant rectangle instead of a normal
   checkbox. A single class already beats "form input"'s two-element
   selector on specificity, so this simply resets the properties that
   rule set. */
.message-compose__anonymous-check {
  display: inline-block;
  width: auto;
  height: auto;
  margin: 0;
}

/* Same reasoning as .comment-form[hidden] above — .message-compose__field
   sets display:flex at equal specificity to (and later in the cascade
   than) the browser's own [hidden]{display:none}, so without this the
   attribute alone doesn't actually hide whichever of
   recipient-field/recipient-fixed isn't in use. */
.message-compose__field[hidden] {
  display: none;
}

/* ---------- Comment thread (Family Chat now; Events/Gift Lists/items later) ----------
   One level of replies only, matching the comments table's parent_id +
   reply_to_user_id design — a reply's own Reply button is hidden below,
   there's no third level to open. */

.comment-thread {
  display: flex;
  flex-direction: column;
}

.comment-list {
  display: flex;
  flex-direction: column;
}

.comment-item {
  display: flex;
  gap: 1rem;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid #eee6d6;
}

.comment-list > .comment-item:last-child {
  border-bottom: none;
}

.comment-item__avatar {
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
}

.comment-item__body {
  flex: 1;
  min-width: 0;
}

.comment-item__top {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.comment-item__name {
  font-family: "Cinzel", serif;
  font-weight: 600;
  font-size: 1.36rem;
  color: #2c342b;
}

.comment-item__time {
  font-size: 1.12rem;
  color: #9a9384;
}

.comment-item__reply-to {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 1.12rem;
  color: #c9a51c;
  font-weight: 600;
}

.comment-item__text {
  margin: 0.3rem 0 0;
  font-size: 1.44rem;
  color: #444;
  line-height: 1.5;
}

.comment-item__edited-tag {
  margin-left: 0.4rem;
  font-size: 1.1rem;
  font-style: italic;
  color: #9a9384;
}

.comment-item__actions {
  display: flex;
  gap: 1rem;
  margin-top: 0.5rem;
}

.comment-item__reply-btn,
.comment-item__edit-btn,
.comment-item__delete-btn,
.comment-item__message-btn {
  display: inline-block;
  background: none;
  border: none;
  padding: 0;
  font-size: 1.2rem;
  font-weight: 600;
  color: #9a9384;
  cursor: pointer;
  text-decoration: underline;
}

.comment-item__reply-btn:hover,
.comment-item__edit-btn:hover {
  color: #2c342b;
}

.comment-item__delete-btn:hover {
  color: #9e2525;
}

.comment-item__message-btn:hover {
  color: #c9a51c;
}

/* The name doubles as a second, faster way to start a PM with that
   person (site.js) — this is what keeps it from reading as plain static
   text like it used to. Gold rather than the usual dark hover color,
   matching the "Message" action-row link's own hover color, so the two
   entry points to the same action read as connected. */
.comment-item__name--link {
  cursor: pointer;
}

.comment-item__name--link:hover {
  color: #c9a51c;
  text-decoration: underline;
}

.comment-edit-form {
  margin-top: 0.5rem;
}

/* Deliberately no separate textarea styling here — it shares
   .comment-form__input with the reply/post boxes so all three look and
   resize identically. */

.comment-edit-form__actions {
  display: flex;
  gap: 0.75rem;
  margin-top: 0.5rem;
}

.btn-small {
  border: none;
  border-radius: 20px;
  padding: 0.3rem 0.9rem;
  font-size: 1.2rem;
  font-weight: 600;
  cursor: pointer;
}

.btn-small--save {
  background: #c9a51c;
  color: #2c342b;
}

.btn-small--save:hover {
  background: #b3910c;
}

.btn-small--save:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn-small--cancel {
  background: transparent;
  color: #6b6555;
  text-decoration: underline;
}

.btn-small--cancel:hover {
  color: #2c342b;
}

.btn-small--delete {
  background: transparent;
  color: #9e2525;
  text-decoration: underline;
}

.btn-small--delete:hover {
  color: #7a1c1c;
}

/* Same bordered look as .gc-btn--edit — a neutral secondary action,
   visually distinct from Cancel's understated underline (dismissive)
   and Save's solid dark fill (committing), since Preview is neither. */
.btn-small--preview {
  background: transparent;
  color: #2c342b;
  border: 1px solid rgba(44, 52, 43, 0.35);
}

.btn-small--preview:hover {
  background: rgba(44, 52, 43, 0.08);
}

.wishlist-section-empty {
  grid-column: 1 / -1;
  font-size: 1.36rem;
  color: #9a9384;
  font-style: italic;
  margin: 0;
}

/* A section's title bar and its entries are one visual unit, not two
   independent panels — the site's default .panel spacing (2.5rem gap,
   rounded on all 4 corners) is right for genuinely separate groupings
   elsewhere (Account's Avatar/Notifications/Security panels), but reads
   as two disconnected boxes here where they're actually one section.
   Zeroing the gap and splitting the rounding between just the outer top
   and outer bottom corners is what makes the two panels read as a
   single continuous shape instead. */
.wishlist-section .inner__block.panel:first-child {
  margin-bottom: 0;
  border-radius: 18px 18px 0 0;
}

.wishlist-section .inner__block.panel:last-child {
  border-radius: 0 0 18px 18px;
}

.wishlist-section-add-row {
  display: flex;
  gap: 0.75rem;
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid #eee6d6;
}

.wishlist-section-add-form {
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid #eee6d6;
}

.comment-item__replies {
  display: flex;
  flex-direction: column;
  margin-top: 1rem;
  padding-left: 1.5rem;
  border-left: 2px solid #eee6d6;
}

.comment-item__replies .comment-item {
  padding: 0.9rem 0;
  border-bottom: none;
}

.comment-item__replies .comment-item__avatar {
  width: 36px;
  height: 36px;
}

.comment-form,
.comment-reply-form {
  display: flex;
  align-items: flex-start;
  gap: 2rem;
}

.comment-form {
  padding: 1.25rem 1.5rem;
  border-top: 1px solid #eee6d6;
  background: #f9f6ee;
}

/* Without this, the [hidden] attribute in the static HTML has no actual
   effect — .comment-form's own "display: flex" above is equal
   specificity and later in the cascade, so it silently wins over the
   browser's default [hidden]{display:none} and the form shows on page
   load regardless of the attribute. jQuery's .hide()/.show() elsewhere
   in this file still work fine afterward either way, since an inline
   style always overrides any external stylesheet rule. */
.comment-form[hidden] {
  display: none;
}

.comment-add-trigger {
  display: block;
  width: calc(100% - 3rem);
  margin: 1.25rem 1.5rem;
}

.comment-reply-form {
  margin-top: 0.75rem;
}

.comment-reply-form__input-group {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.comment-form__avatar {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
}

.comment-form__input {
  flex: 1;
  resize: none;
  /* The rows="3" attribute in the markup is kept only for accessibility/
     semantics — actual sizing is this explicit height instead, because
     browsers size a rows-based textarea using the font's own internal
     line metrics rather than this element's CSS line-height, which for
     this font/size combo rendered at the full max-height (140px) instead
     of anything resembling 3 lines. */
  height: 8.6rem;
  min-height: 40px;
  max-height: 140px;
  padding: 0.9rem 1.2rem;
  /* Smaller than the site's usual 20px pill radius on purpose — this box
     is tall enough to scroll, and a straight-edged scrollbar sitting
     right at a heavily-rounded corner is what made it look like it was
     spilling out past the edge. A softer, smaller radius keeps some
     roundness without that clash. */
  border-radius: 8px;
  border: 1px solid rgba(44, 52, 43, 0.2);
  background: #fff;
  color: #2c342b;
  font-size: 1.36rem;
  font-family: "Mulish", sans-serif;
}

.comment-form__submit {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: #c9a51c;
  color: #2c342b;
  font-size: 1.36rem;
  cursor: pointer;
  transition: background 0.2s ease;
}

.comment-form__submit:hover {
  background: #b3910c;
}

.comment-form__submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Shown inline under a comment/reply form when posting fails — both
   forms sit on white panels, so dark/red text (matching the site's
   existing error color elsewhere) reads fine here, unlike .form-message
   which assumes a dark background. */
.comment-form__error {
  display: block;
  width: 100%;
  margin-top: 0.5rem;
  font-size: 1.2rem;
  color: #9e2525;
}

/* ---------- Phone touch targets ---------- */

/* Placed at the very end of this file on purpose: several rules below
   deliberately override earlier mobile media queries at equal
   specificity (notably `.gc-grid .gc-btn`, which shrinks buttons to an
   11px font on small screens), and at equal specificity the later rule
   wins. Moving this block earlier would silently undo it.

   The problem being fixed: a fingertip covers roughly 44px, but on a
   phone the Claim button measured 60x19, the back arrow 14x18, and the
   anonymous-claim checkbox 13x13 — all well under half the tappable
   area they need, on the site's most important action. The theme was
   making controls *smaller* exactly where they switch from a mouse to a
   finger. 44px is Apple's floor (Material's is 48); this aims at 44 as
   the compromise that costs the least visual weight.

   Scoped to phones only, so desktop's more compact proportions are
   untouched. */
@media only screen and (max-width: 767px) {
  /* Both selectors needed: the bare class for detail-page buttons, and
     the .gc-grid-scoped one to beat the shrink rule above. */
  .gc-btn,
  .gc-grid .gc-btn {
    min-height: 44px;
    padding: 0.7rem 1.4rem;
    font-size: 1.3rem;
  }

  .giftlist-watch-btn {
    min-height: 44px;
    padding: 0.7rem 1.4rem;
    font-size: 1.25rem;
  }

  /* The arrow glyph stays its current size — only the hit area grows,
     via padding rather than width/height, so the icon doesn't scale up
     with it. The negative margin keeps the arrow optically where it was
     despite the bigger box, so the header doesn't visibly shift. */
  .message-back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    margin-left: -0.8rem;
  }

  /* The whole label is the tap target, not just the 13px box — this is
     the single easiest control on the page to miss, and missing it
     silently changes whether a claim is anonymous. */
  .gc-claim-anon {
    display: flex;
    align-items: center;
    min-height: 44px;
  }

  .gc-claim-anon-check {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
  }
}

/* Continues the touch-target block above (kept separate only so the two
   passes stay legible; both must remain at the end of this file to win
   on source order). This pass covers the shared controls the first one
   missed — measured by walking every section at 375px and collecting
   anything under 44px.

   .btn-small is deliberately handled by its base class rather than per
   screen: it's the Save/Cancel/Delete control used throughout the
   wishlist editor, image picker, link rows and comment forms, so fixing
   it here covers Edit Mode too, which is otherwise awkward to audit
   without creating a draft. */
@media only screen and (max-width: 767px) {
  .btn-small {
    min-height: 44px;
    padding: 0.5rem 1.2rem;
  }

  /* Checkbox rows: the <label> is the real tap target, so it carries the
     44px floor while the box itself only grows enough to be visible.
     Both notification toggles live in this pattern. */
  .account-settings__row {
    min-height: 44px;
  }

  .account-settings__row input[type="checkbox"] {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
  }

  /* Watching list rows (Account > Notifications). The name is a real
     click-through and the X cancels the subscription, so both need to be
     hittable without zooming. */
  .watching-row__name {
    min-height: 44px;
  }

  .watching-row__remove {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Cancels the wider box's own edge so the X stays optically aligned
       with the row's right edge rather than appearing inset. */
    margin-right: -0.5rem;
  }

  .user-images-pager__prev,
  .user-images-pager__next {
    min-width: 44px;
    min-height: 44px;
  }

  .accordion-header {
    min-height: 44px;
  }
}

/* Last of the sub-44px controls found by the sweep — the sign-in
   provider buttons on the logged-out screen, 3px short. Trivial, but
   it's the very first thing a new family member taps, so it may as well
   clear the same floor as everything else. */
@media only screen and (max-width: 767px) {
  .btn-auth {
    min-height: 44px;
  }
}

/* iOS Safari auto-zooms the whole page when you focus a text field whose
   font-size is under 16px, then leaves you zoomed in and panning to get
   back. Every field on this site was under that threshold (most 13.6px,
   the image-picker URL box 13px), which is almost certainly why
   index.html's viewport meta carried `maximum-scale=1` — that suppresses
   the zoom, but at the cost of disabling pinch-to-zoom entirely for
   everyone. Bad trade on a site whose users include people who need to
   zoom in to read at all, so both halves are fixed together: fields go
   to 16px here, and that meta restriction is lifted.

   16px is a literal, not a rem: it's a hard threshold iOS defines in CSS
   pixels, and this stylesheet sits on a 62.5% root (1rem = 10px), so
   expressing it relatively would be fragile if that root ever changed.
   Phones only — desktop keeps its more compact fields.

   `!important` is deliberate and load-bearing here. Every field carries
   its own component class (.comment-form__input, .message-compose__subject
   and so on) at specificity 0,1,0, which outranks a bare `textarea` or
   `select` selector at 0,0,1 — a first attempt without it left all eight
   textareas and selects still at 13.6px while the inputs happened to win
   on their longer :not() chain. Rather than enumerate every current class
   (which silently regresses the moment a new styled field is added), this
   states the rule as what it actually is: a floor that component styling
   is not permitted to drop below. */
@media only screen and (max-width: 767px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]),
  textarea,
  select,
  [contenteditable="true"] {
    font-size: 16px !important;
  }
}

/* Two bits of secondary text that fall below comfortable reading size on
   a phone. Nudged rather than normalised to body size, so they still read
   as secondary: the group label stays a small uppercase category marker,
   and the hint stays quieter than the control it explains. Worth doing at
   all because this family includes people who find small type genuinely
   hard, which is the same reason pinch-to-zoom was restored above. */
@media only screen and (max-width: 767px) {
  .watching-group__label {
    font-size: 1.2rem;
  }

  .account-security__hint {
    font-size: 1.3rem;
  }
}

/* Section headings on phones. 4.4rem (44px) is a desktop display size;
   at 375px a single long word like "ACCOUNT" or "MESSAGES" is wider than
   the space left beside the icon, and because `.section-header > div`
   carries `min-width: 0` (needed so the header box itself stops short of
   the close X) the box shrinks while the glyphs simply overflow it. Net
   result: the heading text rendered straight through the X, overlapping
   it by 62px, even though every box-based measurement said there was
   clearance. Measuring a Range over the text rather than the element is
   what actually catches this.

   Reducing the size is the right fix rather than breaking the word:
   hyphenating a display heading mid-word ("ACCO-UNT") looks far worse
   than a slightly smaller title, and 44px was outsized on a phone anyway.
   overflow-wrap is kept only as a backstop so no future longer word can
   reintroduce the overflow. */
@media only screen and (max-width: 767px) {
  .section-header h2 {
    font-size: 2.6rem;
    overflow-wrap: break-word;
  }
}

/* Scaling the heading down above left the script subtitle at 34px,
   i.e. LARGER than the 26px title it sits under, inverting the
   hierarchy (desktop is 44 vs 34, which reads correctly). Brought down
   to preserve roughly the original ratio, which also stops "Your
   profile & photo" wrapping onto a second line and reclaims some
   vertical space at the top of every section on a phone. */
@media only screen and (max-width: 767px) {
  .section-header .section__subtitle {
    font-size: 2rem;
  }
}
