/* ============================================================
   Shell — additions the Flask app needs that the prototype had
   no equivalent for.

   Kept separate so tokens/base/components/pages stay byte-comparable
   with _prototypes/customer-site/css and can be re-synced cleanly.
   ============================================================ */

/* ------------------------------------------------------------------
   FLASH MESSAGES
   Server-rendered, so there can be several at once. The prototype's
   .toast is a single fixed element; stack them instead of letting
   them pile up on the same coordinates.
   ------------------------------------------------------------------ */
.flash-stack {
  position: fixed;
  left: 50%;
  bottom: 26px;
  z-index: 200;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  max-width: min(560px, calc(100vw - 32px));
}

/* Neutralise the fixed positioning .toast sets for the JS-created one */
.toast--flash {
  position: static;
  left: auto;
  bottom: auto;
  transform: none;
  text-align: center;
  transition: opacity var(--dur) ease;
}

.toast--flash.is-dismissed { opacity: 0; }

.toast--error {
  background: var(--heart);
  color: #fff;
}

/* ------------------------------------------------------------------
   NAV — pages that do not exist yet
   Full visual weight so the header matches the design, but not
   interactive: no pointer cursor, no hover promise.
   ------------------------------------------------------------------ */
.site-nav__item.is-soon {
  cursor: default;
  opacity: .55;
}
.site-nav__item.is-soon:hover { color: var(--ink-soft); }

/* DM+ has no handler yet either; keep the lift on hover so it reads as
   live chrome, but do not offer a pointer. */
.dm-button[aria-disabled="true"] { cursor: default; }

/* ------------------------------------------------------------------
   ACCOUNT MENU — grouping
   The prototype's dropdown was a flat list of four items. Ours carries
   real destinations plus a screen-name switcher, which needs separating
   or the two kinds of item read as one list.
   ------------------------------------------------------------------ */
.account__group {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--line);
}

.account__label {
  display: block;
  padding: 2px 12px 5px;
  font-size: var(--text-xs);
  font-weight: 800;
  letter-spacing: .5px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.account__item--sub { font-size: 12.5px; }

/* Hairline rule between menu groups. */
.account__rule {
  height: 1px;
  background: var(--line);
  margin: 6px 4px;
}

/* Label-left, control-right row — used by Screen name and Theme. */
.account__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 7px 12px;
}

.account__row-label {
  font-size: 12px;
  color: var(--ink-soft);
}

.account__value {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--brand);
}
.account__value--static { color: var(--ink); }

.account__sublist { padding: 0 0 var(--space-2); }

/* Settings has no page yet; Log out is destructive-coloured. */
.account__item.is-soon { cursor: default; opacity: .5; }
.account__item--danger { color: var(--heart); }
.account__item--danger:hover { color: var(--heart); background: color-mix(in srgb, var(--heart) 10%, transparent); }

/* ------------------------------------------------------------------
   THEME SWITCH — active state
   The ported pages.css marks the selected side with --ink. The refined
   prototype uses --brand, which reads as a live selection rather than
   just a lighter background. Overridden here to keep pages.css a clean
   port of the original prototype.
   ------------------------------------------------------------------ */
.theme-switch__btn {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
}
.theme-switch__btn[aria-selected="true"] { color: var(--brand); }
.theme-switch__btn svg { flex: none; }

.account__row--content {
  flex-direction: column;
  align-items: stretch;
  gap: 7px;
}

.content-switch {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2px;
  width: 100%;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card-alt);
}

.content-switch__btn {
  min-width: 0;
  min-height: 40px;
  padding: 5px 4px;
  border-radius: var(--radius-pill);
  overflow: hidden;
  color: var(--ink-soft);
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.content-switch__btn[aria-checked="true"] {
  background: var(--card);
  color: var(--brand);
  box-shadow: var(--shadow-sm);
}

@media (max-width: 760px) {
  .content-switch__btn { min-height: 44px; }
}

.account__item--sub.is-current {
  color: var(--brand);
  font-weight: 700;
}

.account__item--divide {
  margin-top: var(--space-2);
  padding-top: 11px;
  border-top: 1px solid var(--line);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}

/* Match the three signed-in desktop actions to the compact Home pill. Keep
   these overrides out of the <=760px layout, where Feedback becomes an icon
   target and the mobile header has its own touch-friendly dimensions. */
@media (min-width: 761px) {
  body[data-auth="1"] .site-header > .ux-v2-feedback-trigger--fan,
  body[data-auth="1"] .site-header > .dm-button,
  body[data-auth="1"] .site-header > .buy-credits {
    height: 32px;
    min-height: 32px;
  }

  body[data-auth="1"] .site-header > .ux-v2-feedback-trigger--fan {
    margin-right: 0;
    padding: 0 13px;
    font-size: 13px;
  }

  body[data-auth="1"] .site-header > .ux-v2-feedback-trigger--fan svg {
    width: 15px;
    height: 15px;
  }

  body[data-auth="1"] .site-header > .dm-button { width: 32px; }
  body[data-auth="1"] .site-header > .dm-button svg {
    width: 30px;
    height: 30px;
  }

  body[data-auth="1"] .site-header > .buy-credits {
    padding: 0 13px 0 36px;
    font-size: 13px;
  }

  body[data-auth="1"] .site-header > .buy-credits .icon {
    left: 10px;
    --icon-size: 18px;
  }
}

/* ------------------------------------------------------------------
   MOBILE SIGNED-IN HEADER
   Keep Buy credits with the logo and compact action icons, while the wider
   account selector gets a row of its own. This belongs in shell.css because
   Feedback and the real account menu do not exist in the design prototype.
   ------------------------------------------------------------------ */
@media (max-width: 680px) {
  body[data-auth="1"] .site-header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto auto;
    column-gap: 8px;
    row-gap: 8px;
  }

  body[data-auth="1"] .site-header > .logo {
    grid-column: 1;
    grid-row: 1;
    min-width: 0;
    white-space: nowrap;
  }

  body[data-auth="1"] .site-header > .u-spacer { display: none; }

  body[data-auth="1"] .site-header > .ux-v2-feedback-trigger--fan {
    grid-column: 2;
    grid-row: 1;
  }

  body[data-auth="1"] .site-header > .dm-button {
    grid-column: 3;
    grid-row: 1;
  }

  body[data-auth="1"] .site-header > .buy-credits {
    grid-column: 4;
    grid-row: 1;
    min-height: 36px;
    padding: 7px 10px 7px 30px;
    font-size: 12px;
  }

  body[data-auth="1"] .site-header > .buy-credits .icon {
    left: 7px;
    --icon-size: 17px;
  }

  body[data-auth="1"] .site-header > .account {
    grid-column: 1 / -1;
    grid-row: 2;
    min-width: 0;
  }

  body[data-auth="1"] .site-header > .account .account__trigger { max-width: 100%; }
  body[data-auth="1"] .site-header > .account .account__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* The account spans the header, so this is 8px inside the normal 14px
     mobile gutter rather than flush against the physical viewport edge. */
  body[data-auth="1"] .site-header > .account .account__menu {
    right: auto;
    left: 8px;
    width: min(238px, calc(100vw - 44px));
  }
}

/* Preserve the same first row on the narrowest supported phones by trimming
   only the signed-in chrome; public landing and login headers stay untouched. */
@media (max-width: 360px) {
  body[data-auth="1"] .site-header {
    grid-template-columns: minmax(0, 1fr) 34px 34px auto;
    column-gap: 6px;
  }

  body[data-auth="1"] .site-header > .logo {
    gap: 3px;
    font-size: 15px;
  }

  body[data-auth="1"] .site-header > .logo .logo__heart {
    width: 16px;
    height: 14px;
    margin-inline: 0;
  }

  body[data-auth="1"] .site-header > .ux-v2-feedback-trigger--fan,
  body[data-auth="1"] .site-header > .dm-button {
    width: 34px;
    height: 34px;
    min-height: 34px;
  }

  body[data-auth="1"] .site-header > .buy-credits {
    min-height: 34px;
    padding: 6px 8px 6px 27px;
    font-size: 11px;
  }

  body[data-auth="1"] .site-header > .buy-credits .icon {
    left: 6px;
    --icon-size: 15px;
  }
}

/* ------------------------------------------------------------------
   REQUEST ROW + ACTION BUTTONS
   Shared by the model profile's Requests tab and Discover's Special
   Requests directory. These lived in profile_v2.css, which Discover does
   not load — so its whole right-hand column rendered unstyled. Anything
   two pages use belongs here.
   ------------------------------------------------------------------ */
.profile-action {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 16px;
  border-radius: var(--radius-pill);
  font-weight: 700;
  font-size: 12.5px;
}

.profile-action--brand {
  background: color-mix(in srgb, var(--brand) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--brand) 30%, transparent);
  color: var(--brand);
  transition: border-color var(--dur-fast);
}
.profile-action--brand:hover { border-color: var(--brand); }


/* ------------------------------------------------------------------
   REQUESTS MENU
   ------------------------------------------------------------------ */
.req-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 760px;
}

.req {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 18px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
}

.req__main { flex: 1 1 520px; min-width: 0; }

.req__head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.req__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14.5px;
}

/* The model's own signature request. Pink so it reads as hers rather than
   as another system chip. */
.req__badge {
  padding: 2.5px 8px;
  border-radius: var(--radius-pill);
  background: var(--pink);
  color: #fff;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .5px;
}

.req__desc {
  margin-top: 2px;
  font-size: 12px;
  color: var(--ink-soft);
}

.req__price {
  flex: none;
  text-align: right;
}
.req__amount {
  font-weight: 700;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.req__turn { font-size: 11px; color: var(--ink-soft); }

.req__cta { flex: none; padding: 9px 15px; font-size: 12.5px; }

@media (max-width: 620px) {
  /* Stack rather than let the description squeeze to nothing. */
  .req { flex-wrap: wrap; gap: 10px; }
  .req__main { flex: 1 1 100%; }
  .req__price { text-align: left; }
}


/* ------------------------------------------------------------------
   MODEL CARD — whole-card link
   The prototype's model cards were onclick handlers. Real pages need a
   real anchor so the card is keyboard-reachable and middle-clickable.
   ------------------------------------------------------------------ */
.model-card__link { display: block; color: inherit; }
.model-card__link:hover { color: inherit; }
.model-card__link:hover .model-card__name { color: var(--brand); }

.model-card__name { display: block; transition: color var(--dur-fast); }
.model-card__body .model-card__meta:only-child { margin-top: 0; }

/* ------------------------------------------------------------------
   PLACEHOLDER CARDS
   Stand in when a feed is empty or unavailable. These keep a section's
   designed shape rather than dropping an error into the layout, so they
   must read as "nothing here yet" — static and quiet, never pulsing like
   the loading skeletons, which mean "still coming".

   Shared by the landing page and the dashboard; rendered by
   fans/js/cards.js.
   ------------------------------------------------------------------ */
.model-card.is-placeholder,
.post-card.is-placeholder,
.club-pill.is-placeholder {
  cursor: default;
  opacity: .55;
}

.club-pill.is-placeholder { pointer-events: none; }

/* The gradient media blocks carry the colour; mute them further so a grid
   of placeholders does not out-shout real content elsewhere on the page. */
.is-placeholder .ph { filter: saturate(.55); }

.placeholder-bar {
  display: block;
  border-radius: var(--radius-pill);
  background: var(--card-alt);
}

.is-placeholder .placeholder-bar--name  { height: 11px; width: 62%; margin-top: 4px; }
.is-placeholder .placeholder-bar--meta  { height: 9px;  width: 40%; margin-top: 8px; }
.is-placeholder .placeholder-bar--date  { height: 8px;  width: 28%; margin-top: 6px; }
.is-placeholder .placeholder-bar--title { height: 11px; width: 72%; }

/* Stands in for a price or count chip. Rendered by both the dashboard's
   trending hashtags and the profile's request rows, so it cannot live in
   either page's own sheet — which it did, invisibly, on the profile. */
.placeholder-bar--chip {
  height: 8px;
  width: 46px;
  background: var(--ink-soft);
  opacity: .35;
}

/* The About grid on a model profile: a short key over a longer value, sized
   to the real thing so the card does not resize once wired. */
.placeholder-bar--key   { height: 7px;  width: 44%; margin-bottom: 6px; }
.placeholder-bar--value { height: 10px; width: 74%; }
[data-placeholder] .placeholder-bar--key,
[data-placeholder] .placeholder-bar--value { opacity: .55; }

.club-pill.is-placeholder .placeholder-bar--name { width: 120px; }
.club-pill.is-placeholder .placeholder-bar--meta { width: 80px; }

.post-card.is-placeholder .post-card__body { display: flex; flex-direction: column; gap: 9px; }

/* ------------------------------------------------------------------
   LOADING SKELETONS
   Sized to match the real cards so grids do not reflow when a fetch
   resolves. These pulse; placeholders above do not.
   ------------------------------------------------------------------ */
.skeleton-card,
.skeleton-post,
.skeleton-pill {
  border-radius: 14px;
  background: var(--card-alt);
  animation: pulse 1.6s ease-in-out infinite;
}

.skeleton-card { aspect-ratio: 3 / 4.55; }

.skeleton-post {
  flex: 0 0 auto;
  width: 295px;
  height: 340px;
  border-radius: var(--radius-lg);
}

.skeleton-pill {
  flex: 0 0 auto;
  width: 232px;
  height: 71px;
  border-radius: var(--radius-lg);
}

/* ------------------------------------------------------------------
   SCREEN-READER-ONLY TEXT
   .u-hidden in base.css is display:none, which hides from assistive tech
   too. This is for text that should be announced but not seen — e.g.
   explaining a placeholder state whose cards are aria-hidden.
   ------------------------------------------------------------------ */
.u-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------------
   SPINNER
   The prototype had no pending state; forms that post to the server
   need one. Sized to sit inside a .btn next to its label.
   ------------------------------------------------------------------ */
.spinner {
  display: inline-block;
  flex: none;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  opacity: .85;
  animation: spin .6s linear infinite;
}

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

@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 1.6s; }
}

/* ------------------------------------------------------------------
   DM+ OVERLAY
   Deliberately frameless: the service provides its own chrome, so a
   header bar and padding around it just doubled up. The panel is the
   iframe, with a close control floating over the corner.
   ------------------------------------------------------------------ */
.overlay--dm {
  align-items: center;
  padding: clamp(10px, 3vh, 34px) clamp(10px, 3vw, 34px);
}

.dm-shell {
  position: relative;
  width: min(1080px, 100%);
  height: min(860px, 100%);
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: var(--card);
  box-shadow: var(--shadow-lift);
  animation: pop var(--dur) ease;
}

.dm-frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Over the frame rather than above it, so nothing is added to the layout.
   Solid backing because whatever the service renders underneath is unknown. */
.dm-close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-pill);
  background: var(--card);
  border: 1px solid var(--line);
  color: var(--ink-soft);
  box-shadow: var(--shadow);
}
.dm-close:hover { color: var(--ink); }

@media (max-width: 620px) {
  /* Full bleed on a phone — a 10px inset around a chat view is wasted space. */
  .overlay--dm { padding: 0; }
  .dm-shell { width: 100%; height: 100%; border-radius: 0; }
}

/* ------------------------------------------------------------------
   ACCOUNT TABLES MODAL
   Memberships and unlocked extras. Rendered by fans/js/account_tables.js
   from markup in base-fans.html, so these rules must be reachable from
   every signed-in page — hence shell.css rather than a page sheet.
   ------------------------------------------------------------------ */
.modal--wide { width: 860px; }

/* Keep the account chrome inside the visual viewport. The body itself does
   not scroll: its content pane does, leaving both the title and tabs in view. */
#tables-modal { overflow: hidden; }

#tables-modal .modal--account {
  display: flex;
  flex-direction: column;
  width: 1080px;
  max-height: calc(100vh - 72px);
  max-height: calc(100dvh - 72px);
}

#tables-modal .modal__head { flex: none; }

#tables-modal .modal__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
}

/* .segmented centres its buttons by default; here it is a heading-level
   control and should start at the edge of the body. */
.segmented--start { align-self: flex-start; }

.account-tabs-bar {
  position: sticky;
  top: 0;
  z-index: 4;
  display: flex;
  flex: none;
  align-self: stretch;
  padding-bottom: 2px;
  background: var(--card);
}

.account-tabs {
  max-width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  white-space: nowrap;
}

.account-tabs .segmented__btn { flex: 0 0 auto; }

.account-modal__content {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  flex-direction: column;
  gap: var(--space-4);
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
}

.u-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Wide layouts keep the compact table treatment; the responsive card rules
   below remove this horizontal scroller at the mobile/tablet breakpoint. */
.dtable-wrap {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}

.dtable {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
  white-space: nowrap;
}

.dtable th {
  padding: 10px 12px;
  background: var(--card-alt);
  text-align: left;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .4px;
  text-transform: uppercase;
  color: var(--ink-soft);
  position: sticky;
  top: 0;
}

.dtable td {
  padding: 11px 12px;
  border-top: 1px solid var(--line);
  vertical-align: middle;
}

.dtable tbody tr:hover td { background: var(--card-alt); }

.dtable__num { text-align: right; font-variant-numeric: tabular-nums; }
.dtable__status {
  position: sticky;
  right: 136px;
  min-width: 92px;
  box-shadow: -1px 0 0 var(--line);
}
.dtable__actions {
  position: sticky;
  right: 0;
  min-width: 136px;
  text-align: right;
  box-shadow: -1px 0 0 var(--line);
}

/* Keep the renewal control in view while the facts to its left scroll. Each
   sticky cell needs an opaque token-based surface of its own; otherwise rows
   show through it, especially in dark mode. */
.dtable th.dtable__actions {
  z-index: 3;
  background: var(--card-alt);
}

.dtable th.dtable__status {
  z-index: 3;
  background: var(--card-alt);
}

.dtable td.dtable__actions {
  z-index: 1;
  background: var(--card);
}

.dtable td.dtable__status {
  z-index: 2;
  background: var(--card);
}

.dtable tbody tr:hover td.dtable__actions {
  background: var(--card-alt);
}
.dtable tbody tr:hover td.dtable__status {
  background: var(--card-alt);
}
.dtable__model { font-weight: 600; color: var(--brand); }
.dtable__model:hover { text-decoration: underline; }

/* The desktop membership table has nine columns. Give each fact a stable
   share of the wider account modal so the two pinned cells cannot cover
   Next renewal or Fanclub price. Long model/screen names stay on one line,
   with their full value available from the element tooltip. */
@media (min-width: 1025px) {
  #accountPanelMemberships .dtable {
    min-width: 1028px;
    table-layout: fixed;
  }

  #accountPanelMemberships .dtable__model-cell { width: 176px; }
  #accountPanelMemberships .dtable__screen-name { width: 122px; }
  #accountPanelMemberships .dtable__date { width: 96px; }
  #accountPanelMemberships .dtable__time-left { width: 84px; }
  #accountPanelMemberships .dtable__renewal { width: 116px; }
  #accountPanelMemberships .dtable__price { width: 110px; }
  #accountPanelMemberships .dtable__status { width: 92px; }
  #accountPanelMemberships .dtable__actions { width: 136px; }

  #accountPanelExtras .dtable__model-cell {
    width: 176px;
    max-width: 176px;
  }

  #accountPanelExtras .dtable__screen-name {
    width: 122px;
    max-width: 122px;
  }

  #accountPanelMemberships .dtable__truncate,
  #accountPanelExtras .dtable__truncate {
    display: block;
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

#accountPanelMemberships .dtable__model-cell,
#accountPanelMemberships .dtable__screen-name,
#accountPanelExtras .dtable__model-cell,
#accountPanelExtras .dtable__screen-name {
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.35;
}

.membership-action {
  min-width: 112px;
  white-space: nowrap;
}

.membership-action-copy {
  margin: 0;
  color: var(--ink-soft);
  line-height: 1.55;
}

.membership-action-error {
  margin: 0;
  padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--heart) 45%, var(--line));
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--heart) 10%, var(--card));
  color: var(--heart);
  font-size: 12px;
}

/* The screen-name row is scrollable to, so nothing is lost by dropping the
   least load-bearing columns first on a narrow screen. */
@media (max-width: 700px) {
  .dtable__dim { display: none; }
}

.dtable__state td {
  padding: 28px 20px;
  white-space: normal;
  text-align: center;
  color: var(--ink-soft);
}

.dtable__state-content {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  min-height: 34px;
}

.dtable__state-copy {
  line-height: 1.5;
}

.dtable__state-action {
  flex: 0 0 auto;
}

.account-history {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.account-history__item {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  min-height: 68px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--card);
}

.account-history__media {
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  flex: none;
  color: var(--ink-soft);
  font-size: 12px;
  font-weight: 800;
}

.account-history__media--post {
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background-position: center;
  background-size: cover;
  cursor: pointer;
  appearance: none;
}

.account-history__media--post:hover,
.account-history__media--post:focus-visible {
  border-color: var(--brand);
  box-shadow: 0 0 0 2px var(--brand-soft);
}

.account-history__post-open[aria-busy="true"] { cursor: wait; }

.account-history__copy { min-width: 0; }

.account-history__primary {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 7px;
}

.account-history__model {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink);
  font-weight: 750;
}

a.account-history__model:hover { color: var(--brand); }

.account-history__detail,
.account-history__meta {
  margin: 3px 0 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-history__detail { color: var(--ink); font-size: 12px; }
.account-history__meta { color: var(--ink-soft); font-size: 11px; }

.account-history__detail--post {
  display: block;
  max-width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
  appearance: none;
}

.account-history__detail--post:hover,
.account-history__detail--post:focus-visible {
  color: var(--brand);
  text-decoration: underline;
}

.account-history__credits {
  justify-self: end;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  font-weight: 800;
}

.account-history__credits.is-negative { color: var(--ink); }
.account-history__credits.is-positive { color: var(--online); }

.account-history__footer {
  display: flex;
  justify-content: center;
  padding-top: 10px;
}

.account-history__state {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  min-height: 92px;
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  color: var(--ink-soft);
  text-align: center;
}

.account-history__item--loading { grid-template-columns: 48px 1fr; }
.account-history__skeleton-avatar { width: 48px; height: 48px; }
.account-history__skeleton-copy { display: grid; gap: 9px; }
.account-history__skeleton-copy .dtable__skeleton:first-child { width: 42%; }
.account-history__skeleton-copy .dtable__skeleton:last-child { width: 68%; }

@media (max-width: 700px) {
  .account-history__item {
    grid-template-columns: 42px minmax(0, 1fr);
    gap: 10px;
  }
  .account-history__media { width: 42px; height: 42px; }
  .account-history__credits {
    grid-column: 2;
    justify-self: start;
    margin-top: -3px;
  }
  .account-history__skeleton-avatar { width: 42px; height: 42px; }
}

.dtable__skeleton {
  display: block;
  height: 9px;
  width: 60px;
  border-radius: var(--radius-pill);
  background: var(--card-alt);
  animation: pulse 1.6s ease-in-out infinite;
}

.dtable-note {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--ink-soft);
}

@media (max-width: 1024px) {
  /* A definite dynamic-viewport height lets max-height: 100% account for the
     notch and home indicator via the overlay's safe-area padding. */
  #tables-modal {
    height: 100vh;
    height: 100dvh;
    padding:
      max(12px, env(safe-area-inset-top))
      max(12px, env(safe-area-inset-right))
      max(12px, env(safe-area-inset-bottom))
      max(12px, env(safe-area-inset-left));
  }

  #tables-modal .modal--account {
    height: 100%;
    max-height: 100%;
  }

  #tables-modal .modal__close {
    width: 44px;
    height: 44px;
  }

  .account-tabs .segmented__btn {
    min-height: 44px;
  }

  /* Membership and extra-content rows become label/value cards. Account
     history keeps its purpose-built list presentation. */
  #accountPanelMemberships .dtable-wrap,
  #accountPanelExtras .dtable-wrap {
    overflow: visible;
    overscroll-behavior: auto;
    border: 0;
    border-radius: 0;
  }

  #accountPanelMemberships .dtable,
  #accountPanelExtras .dtable {
    display: block;
    max-width: 100%;
    white-space: normal;
  }

  #accountPanelMemberships .dtable thead,
  #accountPanelExtras .dtable thead {
    display: none;
  }

  #accountPanelMemberships .dtable tbody,
  #accountPanelExtras .dtable tbody {
    display: grid;
    gap: 12px;
  }

  #accountPanelMemberships .dtable tr,
  #accountPanelExtras .dtable tr {
    display: block;
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    background: var(--card);
  }

  /* Give each real account record its own tinted surface on narrow screens.
     State rows (loading, empty and error) deliberately keep the neutral modal
     surface so they still read as messages rather than membership cards. */
  #accountPanelMemberships .dtable tr:not(.dtable__state):not([aria-hidden="true"]),
  #accountPanelExtras .dtable tr:not(.dtable__state):not([aria-hidden="true"]) {
    background: var(--card-alt);
    box-shadow: var(--shadow);
  }

  #accountPanelMemberships .dtable tr:not(.dtable__state):not([aria-hidden="true"]) > td,
  #accountPanelExtras .dtable tr:not(.dtable__state):not([aria-hidden="true"]) > td,
  #accountPanelMemberships .dtable tr:not(.dtable__state):not([aria-hidden="true"]):hover > td,
  #accountPanelExtras .dtable tr:not(.dtable__state):not([aria-hidden="true"]):hover > td {
    background: transparent;
  }

  #accountPanelMemberships .dtable td,
  #accountPanelExtras .dtable td {
    display: block;
    width: 100%;
    min-width: 0;
    padding: 10px 12px;
    border-top: 1px solid var(--line);
    white-space: normal;
    overflow-wrap: anywhere;
    text-align: left;
  }

  #accountPanelMemberships .dtable tr > td:first-child,
  #accountPanelExtras .dtable tr > td:first-child {
    border-top: 0;
  }

  #accountPanelMemberships .dtable td[data-label],
  #accountPanelExtras .dtable td[data-label] {
    display: grid;
    grid-template-columns: minmax(96px, .8fr) minmax(0, 1.2fr);
    align-items: start;
    gap: 12px;
  }

  #accountPanelMemberships .dtable td[data-label]::before,
  #accountPanelExtras .dtable td[data-label]::before {
    content: attr(data-label);
    color: var(--ink-soft);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .4px;
    line-height: 1.45;
    text-transform: uppercase;
  }

  #accountPanelMemberships .dtable td[data-label] > *,
  #accountPanelExtras .dtable td[data-label] > * {
    min-width: 0;
  }

  /* Restore columns hidden by the old horizontal-table breakpoint and
     neutralise the desktop-only pinned status/action cells. */
  #accountPanelMemberships .dtable__dim,
  #accountPanelExtras .dtable__dim {
    display: grid;
  }

  #accountPanelMemberships .dtable__status,
  #accountPanelMemberships .dtable__actions,
  #accountPanelExtras .dtable__status,
  #accountPanelExtras .dtable__actions {
    position: static;
    z-index: auto;
    right: auto;
    min-width: 0;
    box-shadow: none;
    background: transparent;
    text-align: left;
  }

  #accountPanelMemberships .membership-action {
    max-width: 100%;
    min-width: 0;
    white-space: normal;
  }

  #accountPanelMemberships .dtable__state td,
  #accountPanelExtras .dtable__state td {
    padding: 24px 16px;
    border-top: 0;
    text-align: center;
  }
}

@media (max-width: 520px) {
  #tables-modal .modal__head { padding: 12px 14px; }
  #tables-modal .modal__body {
    gap: 12px;
    padding: 14px;
  }

  .account-modal__content { gap: 12px; }
  .account-tabs-bar { padding-bottom: 0; }

  .account-tabs {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    width: 100%;
    overflow: visible;
    white-space: normal;
    border-radius: var(--radius-md);
  }

  .account-tabs .segmented__btn {
    width: 100%;
    min-width: 0;
    padding: 9px 8px;
    text-align: center;
    white-space: nowrap;
  }
}
