/* ═══════════════════════════════════════════════════════════════
   Joinery Default UI Kit  ·  custom.css  ·  v2.12.0
   Pure Slate design. Themeable values live in --jy-* tokens on
   :root so branded themes can override them without understanding
   internals. Component rules are scoped under .jy-ui to prevent
   collisions with any active branded theme's stylesheets.
   ═══════════════════════════════════════════════════════════════ */

/* ─── Design Tokens ─────────────────────────────────────────── */
:root {
  /* Neutrals */
  --jy-color-bg:            #ffffff;
  --jy-color-surface:       #f7f8fa;
  --jy-color-surface-alt:   #eff1f5;
  --jy-color-border:        #e1e4ea;
  --jy-color-border-strong: #c8ccd4;
  --jy-color-text:          #1a1d23;
  --jy-color-text-muted:    #5a6170;
  --jy-color-text-subtle:   #8990a0;

  /* Accent */
  --jy-color-primary:       #5b7a99;
  --jy-color-primary-hover: #4a6886;
  --jy-color-primary-text:  #ffffff;
  --jy-color-link:          #4a6886;

  /* Semantic */
  --jy-color-success:       #2f7d4f;
  --jy-color-success-bg:    #e6f4ec;
  --jy-color-warning:       #b87914;
  --jy-color-warning-bg:    #fbf1de;
  --jy-color-danger:        #b3261e;
  --jy-color-danger-bg:     #fbeae9;
  --jy-color-info:          #2d6a9e;
  --jy-color-info-bg:       #e6f0f9;

  /* Typography */
  --jy-font-sans:    'Inter', system-ui, -apple-system, sans-serif;
  --jy-font-display: 'Inter', system-ui, -apple-system, sans-serif;
  --jy-font-mono:    ui-monospace, 'SF Mono', Menlo, monospace;
  --jy-text-xs:    12px;
  --jy-text-sm:    14px;
  --jy-text-base:  16px;
  --jy-text-lg:    18px;
  --jy-text-xl:    22px;
  --jy-text-2xl:   28px;
  --jy-text-3xl:   36px;
  --jy-text-4xl:   48px;
  --jy-leading-tight:  1.25;
  --jy-leading-base:   1.6;
  --jy-tracking-tight: -0.01em;

  /* Space scale */
  --jy-space-1:  4px;
  --jy-space-2:  8px;
  --jy-space-3:  12px;
  --jy-space-4:  16px;
  --jy-space-5:  24px;
  --jy-space-6:  32px;
  --jy-space-8:  48px;
  --jy-space-10: 64px;

  /* Radius */
  --jy-radius-sm:   4px;
  --jy-radius-md:   6px;
  --jy-radius-lg:   10px;
  --jy-radius-full: 999px;

  /* Shadow */
  --jy-shadow-sm: 0 1px 2px rgba(20,25,35,0.04);
  --jy-shadow-md: 0 2px 8px rgba(20,25,35,0.06);
  --jy-shadow-lg: 0 6px 24px rgba(20,25,35,0.08);

  /* Control heights */
  --jy-control-h-sm: 32px;
  --jy-control-h-md: 40px;
  --jy-control-h-lg: 48px;
}

/* ─── Baseline (default theme only) ─────────────────────────
   Scoped to body.jy-default so these rules only fire when the
   default theme is active. Branded themes are unaffected even
   though base.css/custom.css load on every page.
   ─────────────────────────────────────────────────────────── */

/* The hidden attribute means hidden, on every theme. The browser's own rule
   for it is a plain display:none that any author rule with a display value
   overrides — so a component styled display:flex and closed with
   el.hidden = true stayed on screen as an empty box (the Drive context menu,
   the AI drawer overlay, the mailbox bulk bar all hit this and each grew a
   local .x[hidden] rule). One rule here, and no component needs its own. */
[hidden] { display: none !important; }

/* No default body margin, and a stable scrollbar gutter: both keep the
   header from shifting when navigating between scrolling pages and
   viewport-fit app pages. */
html:has(body.jy-default) { scrollbar-gutter: stable; }
body.jy-default {
  margin: 0;
  font-family: var(--jy-font-sans);
  font-size: var(--jy-text-base);
  line-height: var(--jy-leading-base);
  color: var(--jy-color-text);
  background: var(--jy-color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body.jy-default h1, body.jy-default h2, body.jy-default h3,
body.jy-default h4, body.jy-default h5, body.jy-default h6 {
  font-family: var(--jy-font-display);
  font-weight: 600;
  line-height: var(--jy-leading-tight);
  letter-spacing: var(--jy-tracking-tight);
  color: var(--jy-color-text);
  margin-bottom: var(--jy-space-3);
}
body.jy-default h1 { font-size: var(--jy-text-4xl); font-weight: 700; }
body.jy-default h2 { font-size: var(--jy-text-3xl); }
body.jy-default h3 { font-size: var(--jy-text-2xl); }
body.jy-default h4 { font-size: var(--jy-text-xl); }
body.jy-default h5 { font-size: var(--jy-text-lg); }
body.jy-default h6 { font-size: var(--jy-text-base); }

body.jy-default p { margin-bottom: var(--jy-space-4); }
body.jy-default p:last-child { margin-bottom: 0; }
/* :where() keeps these at bare-element specificity so any component rule
   that declares its own link color/decoration (.jy-logo, .jy-nav-links a,
   .jy-member-subnav-link, dropdown menus, …) wins without escalation. */
:where(body.jy-default) a { color: var(--jy-color-link); text-decoration: none; }
:where(body.jy-default) a:hover { text-decoration: underline; }
body.jy-default small { font-size: var(--jy-text-sm); }

body.jy-default code {
  font-family: var(--jy-font-mono);
  font-size: 0.9em;
  background: var(--jy-color-surface-alt);
  padding: 0.1em 0.35em;
  border-radius: var(--jy-radius-sm);
}

body.jy-default blockquote {
  border-left: 3px solid var(--jy-color-border-strong);
  padding: var(--jy-space-2) var(--jy-space-5);
  color: var(--jy-color-text-muted);
  font-style: italic;
  margin: var(--jy-space-5) 0;
}

/* ─── Default Theme Nav ──────────────────────────────────────
   Styles for HTML generated by includes/PublicPage.php.
   Unscoped because the nav sits outside .jy-ui.
   When a branded theme is active it provides its own nav;
   these rules are unused in that context.
   ─────────────────────────────────────────────────────────── */

.jy-site-header {
  background: var(--jy-color-bg);
  border-bottom: 1px solid var(--jy-color-border);
  position: sticky;
  top: 0;
  z-index: 100;
}

.jy-header-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--jy-space-5);
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--jy-space-5);
}

.jy-logo {
  display: flex;
  align-items: center;
  gap: var(--jy-space-2);
  text-decoration: none;
  color: var(--jy-color-text);
  font-family: var(--jy-font-display);
  font-size: var(--jy-text-xl);
  font-weight: 700;
  letter-spacing: var(--jy-tracking-tight);
  flex-shrink: 0;
}
.jy-logo:hover { text-decoration: none; color: var(--jy-color-text); }
.jy-logo-img { height: 32px; width: auto; display: block; }
.jy-logo-text { white-space: nowrap; }

.jy-header-right {
  display: flex;
  align-items: center;
  gap: var(--jy-space-4);
  flex: 1;
  justify-content: flex-end;
}

/* Secondary member nav (Profile / Email / Calendar / Drive / AI ...).
   Rendered by PublicPageBase::render_member_subnav() on every theme, so the
   base rules stay position-neutral — a theme with its own sticky header opts
   into a sticky bar by pinning it below that header, as .jy-default does. */
.jy-member-subnav {
  background: var(--jy-color-bg);
  border-bottom: 1px solid var(--jy-color-border);
}
.jy-default .jy-member-subnav {
  position: sticky;
  top: 60px;
  z-index: 99;
}
.jy-member-subnav-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--jy-space-5);
  display: flex;
  gap: var(--jy-space-1);
  overflow-x: auto;
  scrollbar-width: none;
}
.jy-member-subnav-inner::-webkit-scrollbar { display: none; }
.jy-member-subnav-link {
  display: inline-block;
  padding: var(--jy-space-3) var(--jy-space-3);
  color: var(--jy-color-text-muted);
  font-size: var(--jy-text-sm);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
}
.jy-member-subnav-link:hover { color: var(--jy-color-text); text-decoration: none; }
.jy-member-subnav-link.active {
  color: var(--jy-color-primary);
  border-bottom-color: var(--jy-color-primary);
  font-weight: 600;
}
/* On a phone the member section nav folds behind the hamburger at the left
   of the header (.jy-member-menu-toggle): a panel under the header, one link
   per line, shown by the `open` class that script.js toggles. */
@media (max-width: 768px) {
  .jy-default .jy-member-subnav {
    display: none;
    position: fixed;
    top: 61px;
    left: 0;
    right: 0;
    z-index: 99;
    box-shadow: var(--jy-shadow-md);
  }
  .jy-default .jy-member-subnav.open { display: block; }
  .jy-member-subnav-inner { flex-direction: column; gap: 0; padding: var(--jy-space-2) 0; overflow: visible; }
  .jy-member-subnav-link {
    display: block;
    padding: var(--jy-space-3) var(--jy-space-5);
    border-bottom: none;
    font-size: var(--jy-text-base);
  }
  .jy-member-subnav-link.active { background: var(--jy-color-surface); }
}

.jy-nav-links {
  display: flex;
  align-items: center;
  gap: var(--jy-space-1);
}
.jy-nav-links a {
  display: block;
  padding: var(--jy-space-2) var(--jy-space-3);
  color: var(--jy-color-text);
  font-size: var(--jy-text-sm);
  font-weight: 500;
  border-radius: var(--jy-radius-md);
  transition: background 0.15s, color 0.15s;
  text-decoration: none;
}
.jy-nav-links a:hover,
.jy-nav-links a.active {
  background: var(--jy-color-surface);
  color: var(--jy-color-primary);
  text-decoration: none;
}

.jy-nav-dropdown { position: relative; }
.jy-nav-dropdown-menu {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  min-width: 180px;
  background: var(--jy-color-bg);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-md);
  box-shadow: var(--jy-shadow-md);
  padding: var(--jy-space-2) 0;
  z-index: 200;
}
.jy-nav-dropdown:hover .jy-nav-dropdown-menu { display: block; }
.jy-nav-dropdown-menu a {
  display: block;
  padding: var(--jy-space-2) var(--jy-space-4);
  font-size: var(--jy-text-sm);
  color: var(--jy-color-text);
  white-space: nowrap;
}
.jy-nav-dropdown-menu a:hover {
  background: var(--jy-color-surface);
  color: var(--jy-color-primary);
  text-decoration: none;
}

.jy-header-icons {
  display: flex;
  align-items: center;
  gap: var(--jy-space-2);
}

.jy-header-cart-link {
  display: inline-flex;
  align-items: center;
  gap: var(--jy-space-1);
  color: var(--jy-color-text);
  padding: var(--jy-space-2);
  border-radius: var(--jy-radius-md);
  transition: background 0.15s;
  text-decoration: none;
  position: relative;
}
.jy-header-cart-link:hover { background: var(--jy-color-surface); text-decoration: none; }
.jy-cart-count {
  position: absolute;
  top: 0;
  right: 0;
  background: var(--jy-color-primary);
  color: var(--jy-color-primary-text);
  font-size: 10px;
  font-weight: 700;
  min-width: 16px;
  height: 16px;
  border-radius: var(--jy-radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
}

.jy-header-icon-link,
.jy-header-icons .header-messages-link,
.jy-header-icons .header-notifications-link {
  display: inline-flex;
  align-items: center;
  color: var(--jy-color-text);
  padding: var(--jy-space-2);
  border-radius: var(--jy-radius-md);
  transition: background 0.15s;
  text-decoration: none;
  position: relative;
}
.jy-header-icon-link:hover,
.jy-header-icons .header-messages-link:hover,
.jy-header-icons .header-notifications-link:hover { background: var(--jy-color-surface); text-decoration: none; }
.jy-icon-badge,
.jy-header-icons .messages-count,
.jy-header-icons .notifications-count {
  position: absolute;
  top: 0;
  right: 0;
  background: var(--jy-color-danger);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  min-width: 16px;
  height: 16px;
  border-radius: var(--jy-radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
}

/* Vault lock chip inside the header cluster rides the same ghost-icon
   geometry as the other header icons (vault-lock.css styles the chip's
   default/floating forms). */
.jy-header-icons .jy-vault-lock-btn {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--jy-radius-md);
  color: var(--jy-color-text);
}
.jy-header-icons .jy-vault-lock-btn:hover { background: var(--jy-color-surface); }

.jy-header-icons .jy-header-admin-link {
  display: inline-flex;
  align-items: center;
  padding: var(--jy-space-2) var(--jy-space-3);
  border-radius: var(--jy-radius-md);
  font-size: var(--jy-text-sm);
  font-weight: 500;
  color: var(--jy-color-text);
  transition: background 0.15s;
  text-decoration: none;
  white-space: nowrap;
}
.jy-header-icons .jy-header-admin-link:hover { background: var(--jy-color-surface); text-decoration: none; }

/* User dropdown uses <details>/<summary> */
.jy-user-dropdown { position: relative; }
.jy-user-dropdown-toggle {
  display: flex;
  align-items: center;
  gap: var(--jy-space-2);
  padding: var(--jy-space-2) var(--jy-space-3);
  border-radius: var(--jy-radius-md);
  cursor: pointer;
  list-style: none;
  font-size: var(--jy-text-sm);
  font-weight: 500;
  color: var(--jy-color-text);
  transition: background 0.15s;
}
.jy-user-dropdown-toggle::-webkit-details-marker { display: none; }
.jy-user-dropdown-toggle:hover { background: var(--jy-color-surface); }
.jy-user-name { white-space: nowrap; }

.jy-user-dropdown-menu {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 180px;
  background: var(--jy-color-bg);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-md);
  box-shadow: var(--jy-shadow-md);
  padding: var(--jy-space-2) 0;
  z-index: 200;
}
.jy-user-dropdown[open] .jy-user-dropdown-menu { display: block; }
.jy-user-dropdown-menu a {
  display: block;
  padding: var(--jy-space-2) var(--jy-space-4);
  font-size: var(--jy-text-sm);
  color: var(--jy-color-text);
  white-space: nowrap;
}
.jy-user-dropdown-menu a:hover {
  background: var(--jy-color-surface);
  color: var(--jy-color-primary);
  text-decoration: none;
}

/* Actions dropdown — generic <details>/<summary> menu for row or panel
   actions. Anything inside the menu is a menu item, a .btn included: a
   single-button FormWriter form is how a menu item that mutates something is
   written, and its submit button arrives carrying the button classes.
   Markup:
     <details class="jy-actions-dropdown">
       <summary class="btn btn-secondary">Actions</summary>
       <div class="jy-actions-menu">
         <button type="button">…</button>   an action on this page
         <a href="…">…</a>                  an action that lives elsewhere
       </div>
     </details>
   base.js closes any open one on an outside click or after a menu click. */
.jy-actions-dropdown { position: relative; display: inline-block; }
.jy-actions-dropdown > summary { list-style: none; }
.jy-actions-dropdown > summary::-webkit-details-marker { display: none; }
.jy-actions-dropdown > summary::after { content: ' \25BE'; }
.jy-actions-dropdown.jy-actions-left .jy-actions-menu { left: 0; right: auto; }
.jy-actions-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 220px;
  background: var(--jy-color-bg);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-md);
  box-shadow: var(--jy-shadow-md);
  padding: var(--jy-space-2) 0;
  z-index: 200;
  text-align: left;
}
/* An item is a <button> when it acts on this page and an <a> when it goes
   somewhere else. They look identical, so the choice is about what the item
   does, not how it should appear. */
.jy-actions-menu button,
.jy-actions-menu a,
.jy-actions-menu button.btn,
.jy-actions-menu a.btn {
  display: block;
  width: 100%;
  padding: var(--jy-space-2) var(--jy-space-4);
  border: 0;
  background: none;
  font-family: var(--jy-font-sans);
  font-size: var(--jy-text-sm);
  font-weight: 400;
  color: var(--jy-color-text);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
}
.jy-actions-menu button:hover,
.jy-actions-menu a:hover,
.jy-actions-menu button.btn:hover,
.jy-actions-menu a.btn:hover {
  background: var(--jy-color-surface);
  color: var(--jy-color-primary);
}
.jy-actions-menu button.jy-action-danger,
.jy-actions-menu a.jy-action-danger { color: var(--jy-color-danger, #b42318); }
.jy-actions-menu button.jy-action-danger:hover,
.jy-actions-menu a.jy-action-danger:hover { background: var(--jy-color-surface); }

.jy-menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 36px;
  height: 36px;
  padding: 6px;
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-md);
  background: none;
  cursor: pointer;
  flex-shrink: 0;
}
.jy-menu-toggle span {
  display: block;
  height: 2px;
  background: var(--jy-color-text);
  border-radius: 2px;
}

@media (max-width: 768px) {
  .jy-menu-toggle { display: flex; }
  /* The header fits the phone instead of pushing the page wide. The controls
     on the right keep their size (a clipped button is a control lost); the
     account name goes, so the avatar alone opens the dropdown; padding and
     gaps tighten; and the logo is the one thing that yields, clipping its
     text at the edge if the site name is long. */
  .jy-header-inner { padding: 0 var(--jy-space-4); gap: var(--jy-space-3); }
  .jy-logo { flex: 0 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; font-size: var(--jy-text-lg); }
  /* The site name trims with an ellipsis rather than a cut letter. */
  .jy-logo-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .jy-header-right { gap: var(--jy-space-2); flex: 0 0 auto; }
  .jy-header-icons { gap: var(--jy-space-1); }
  .jy-header-icons .jy-user-name { display: none; }
  .jy-user-dropdown-toggle { padding: var(--jy-space-2); }
  .jy-header-icons .jy-header-admin-link { padding-left: var(--jy-space-1); padding-right: var(--jy-space-1); }
  /* A phone has no room for a footer under an app surface; the page ends
     where its content does. */
  .jy-site-footer { display: none; }
  .jy-nav-links {
    display: none;
    position: absolute;
    top: 60px;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    background: var(--jy-color-bg);
    border-bottom: 1px solid var(--jy-color-border);
    padding: var(--jy-space-3) var(--jy-space-5);
    gap: var(--jy-space-1);
    box-shadow: var(--jy-shadow-md);
    z-index: 99;
  }
  .jy-nav-links.open { display: flex; }
  .jy-site-header { position: relative; }
}

.jy-main-content {
  min-height: calc(100vh - 60px - 80px);
}

.jy-site-footer {
  background: var(--jy-color-surface);
  border-top: 1px solid var(--jy-color-border);
  margin-top: var(--jy-space-8);
}
.jy-site-footer .jy-container { max-width: 1200px; margin: 0 auto; padding: 0 var(--jy-space-5); }
.jy-footer-bottom {
  padding: var(--jy-space-5) 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.jy-copyright { font-size: var(--jy-text-sm); color: var(--jy-color-text-muted); margin: 0; }

/* Page structure helpers */
.jy-container { max-width: 1200px; margin: 0 auto; padding: 0 var(--jy-space-5); }
.page-content { max-width: 1200px; margin: 0 auto; padding: var(--jy-space-8) var(--jy-space-5); }

/* App pages (BeginPage 'app' option): full-bleed surfaces that fill the
   viewport below the header — mailbox, calendar, drive. The body becomes a
   flex column so the app page can grow, and the app's main component
   (a flex child of .page-content--app) stretches to the fold. */
body.jy-default:has(.page-content--app) { display: flex; flex-direction: column; min-height: 100vh; }
/* dvh tracks the visible screen on a phone as the browser toolbar comes and
   goes; 100vh above is the fallback for browsers without it. */
body.jy-default:has(.page-content--app) { min-height: 100dvh; }
/* Grow-only fill: min-height stays auto at every level, so a page taller than
   the viewport (e.g. the calendar with its edit form open) scrolls normally
   instead of collapsing. Self-scrolling components (the mailbox reader) opt
   into shrinking with flex-basis 0 + an explicit min-height. */
body.jy-default:has(.page-content--app) .jy-main-content { flex: 1; display: flex; flex-direction: column; min-height: auto; }
body.jy-default:has(.page-content--app) .jy-site-footer { margin-top: 0; }
.page-content--app {
  max-width: none;
  width: 100%;
  margin: 0;
  padding: var(--jy-space-3) var(--jy-space-5) var(--jy-space-4);
  flex: 1;
  display: flex;
  flex-direction: column;
}
.jy-app-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--jy-space-3);
  flex-wrap: wrap;
  margin-bottom: var(--jy-space-3);
}
body.jy-default .jy-app-bar h1 { font-size: var(--jy-text-xl); font-weight: 600; margin: 0; }
.jy-app-bar-action { flex-shrink: 0; }
/* An app-bar action may carry both an icon and a label (.jy-btn-icon /
   .jy-btn-label): the label shows on a desktop, the icon alone on a phone. */
.jy-btn-icon { display: none; }
.jy-btn-icon svg { width: 20px; height: 20px; display: block; }
@media (max-width: 768px) {
  .jy-btn-icon { display: inline-flex; }
  .jy-btn-icon + .jy-btn-label { display: none; }
  .jy-actions-dropdown > summary:has(.jy-btn-icon)::after { content: none; }
  /* An app surface takes the whole screen: no reading-column padding. */
  .page-content--app { padding: 0; }
}
.jy-page-header { margin-bottom: var(--jy-space-6); }
.jy-page-header h1 { margin-bottom: var(--jy-space-2); }
.page-subtitle { color: var(--jy-color-text-muted); font-size: var(--jy-text-lg); margin-top: var(--jy-space-2); }
.jy-page-header-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--jy-space-4);
  flex-wrap: wrap;
  margin-bottom: var(--jy-space-5);
}
.jy-page-header-bar h2 { margin-bottom: 0; }
.jy-page-header-action { flex-shrink: 0; }
.jy-panel {
  background: var(--jy-color-bg);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-lg);
  padding: var(--jy-space-5);
  box-shadow: var(--jy-shadow-sm);
  margin-bottom: var(--jy-space-5);
}

/* ─── Callouts ──────────────────────────────────────────────────
   A block that has to be noticed before the page's ordinary content
   is read: something is waiting on the person, or something is wrong.
   The accent bar carries the meaning, so the tone survives a theme
   that has overridden the background tokens.
   Use --action when the page CANNOT proceed without an answer; it is
   the loudest and should stay rare enough to keep meaning something. */
.jy-callout {
  border: 1px solid var(--jy-color-border);
  border-left: 4px solid var(--jy-color-border-strong);
  border-radius: var(--jy-radius-md);
  background: var(--jy-color-surface);
  padding: var(--jy-space-4);
  margin-bottom: var(--jy-space-4);
}
.jy-callout > :first-child { margin-top: 0; }
.jy-callout > :last-child  { margin-bottom: 0; }
.jy-callout-title {
  font-weight: 600;
  font-size: var(--jy-text-lg);
  margin: 0 0 var(--jy-space-2);
}
.jy-callout-info    { border-left-color: var(--jy-color-info);    background: var(--jy-color-info-bg); }
.jy-callout-success { border-left-color: var(--jy-color-success); background: var(--jy-color-success-bg); }
.jy-callout-warning { border-left-color: var(--jy-color-warning); background: var(--jy-color-warning-bg); }
.jy-callout-danger  { border-left-color: var(--jy-color-danger);  background: var(--jy-color-danger-bg); }
.jy-callout-action  {
  border-left-color: var(--jy-color-primary);
  background: var(--jy-color-info-bg);
  box-shadow: var(--jy-shadow-sm);
}

/* ─── Tickable lists ────────────────────────────────────────────
   A checkbox or radio and its label as ONE row. The default inline
   flow runs several together into an unreadable line, which matters
   most where the ticks are the decision being asked for. */
.jy-fieldset {
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-md);
  padding: var(--jy-space-3) var(--jy-space-4);
  margin: 0 0 var(--jy-space-3);
}
.jy-fieldset > legend {
  padding: 0 var(--jy-space-2);
  font-size: var(--jy-text-sm);
  font-weight: 600;
  color: var(--jy-color-text-muted);
}
.jy-check {
  display: flex;
  align-items: center;
  gap: var(--jy-space-2);
  padding: var(--jy-space-1) 0;
  cursor: pointer;
}
.jy-check input { flex-shrink: 0; margin: 0; }
.jy-check-count { margin-left: auto; font-variant-numeric: tabular-nums; }

/* Section layout helpers (used by base views like views/index.php) */
.jy-content-section { padding: 64px 0; }
.section-muted   { background: var(--jy-color-surface); }
.jy-section-dark    {
  background: var(--jy-color-text);
  color: rgba(255,255,255,0.9);
}
.jy-section-dark h1, .jy-section-dark h2, .jy-section-dark h3,
.jy-section-dark h4, .jy-section-dark h5 { color: #fff; }

/* Breadcrumbs from BeginPageNoCard */
.jy-breadcrumbs { font-size: var(--jy-text-sm); color: var(--jy-color-text-muted); }
.jy-breadcrumbs ol {
  display: flex;
  align-items: center;
  gap: var(--jy-space-2);
  list-style: none;
  flex-wrap: wrap;
  margin-bottom: var(--jy-space-3);
}
.jy-breadcrumbs li { display: flex; align-items: center; gap: var(--jy-space-2); }
.jy-breadcrumbs li::before { content: '›'; color: var(--jy-color-text-subtle); }
.jy-breadcrumbs li:first-child::before { display: none; }
.jy-breadcrumbs a { color: var(--jy-color-text-muted); }
.jy-breadcrumbs a:hover { color: var(--jy-color-primary); }
.jy-breadcrumbs li.active { color: var(--jy-color-text); font-weight: 500; }


/* ═══════════════════════════════════════════════════════════════
   JY-UI SCOPED COMPONENT KIT
   All rules below require .jy-ui as ancestor.
   Safe to load in any theme context — no class-name collisions.
   ═══════════════════════════════════════════════════════════════ */

/* ─── Typography inside scope ────────────────────────────────── */
.jy-ui {
  color: var(--jy-color-text);
  font-family: var(--jy-font-sans);
  font-size: var(--jy-text-base);
  line-height: var(--jy-leading-base);
}
.jy-ui h1, .jy-ui h2, .jy-ui h3,
.jy-ui h4, .jy-ui h5, .jy-ui h6 {
  font-family: var(--jy-font-display);
  font-weight: 600;
  line-height: var(--jy-leading-tight);
  letter-spacing: var(--jy-tracking-tight);
  color: var(--jy-color-text);
}
.jy-ui p { margin-bottom: var(--jy-space-4); }
.jy-ui p:last-child { margin-bottom: 0; }
.jy-ui a { color: var(--jy-color-link); }
.jy-ui small { font-size: var(--jy-text-sm); color: var(--jy-color-text-muted); }
.jy-ui code {
  font-family: var(--jy-font-mono);
  font-size: 0.9em;
  background: var(--jy-color-surface-alt);
  padding: 0.1em 0.35em;
  border-radius: var(--jy-radius-sm);
}

.jy-ui .text-muted  { color: var(--jy-color-text-muted) !important; }
.jy-ui .text-subtle { color: var(--jy-color-text-subtle) !important; }
.jy-ui .text-center { text-align: center; }
.jy-ui .text-sm     { font-size: var(--jy-text-sm); }
.jy-ui .muted       { color: var(--jy-color-text-muted); }

/* ─── Buttons ─────────────────────────────────────────────────── */
.jy-ui .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--jy-space-2);
  height: var(--jy-control-h-md);
  padding: 0 var(--jy-space-4);
  border-radius: var(--jy-radius-md);
  font-family: var(--jy-font-sans);
  font-size: var(--jy-text-sm);
  font-weight: 600;
  line-height: 1;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s;
  text-decoration: none;
  white-space: nowrap;
}
.jy-ui .btn:hover { text-decoration: none; }
.jy-ui .btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--jy-color-primary) 25%, transparent);
}
.jy-ui .btn svg { width: 16px; height: 16px; flex-shrink: 0; }

.jy-ui .btn-primary {
  background: var(--jy-color-primary);
  color: var(--jy-color-primary-text);
  border-color: var(--jy-color-primary);
}
.jy-ui .btn-primary:hover {
  background: var(--jy-color-primary-hover);
  border-color: var(--jy-color-primary-hover);
  color: var(--jy-color-primary-text);
}
.jy-ui .btn-primary:disabled,
.jy-ui .btn-primary.disabled {
  background: var(--jy-color-border-strong);
  border-color: var(--jy-color-border-strong);
  color: var(--jy-color-bg);
  cursor: not-allowed;
}

.jy-ui .btn-secondary {
  background: var(--jy-color-surface);
  color: var(--jy-color-text);
  border-color: var(--jy-color-border);
}
.jy-ui .btn-secondary:hover {
  background: var(--jy-color-surface-alt);
  border-color: var(--jy-color-border-strong);
}

.jy-ui .btn-outline {
  background: transparent;
  color: var(--jy-color-primary);
  border-color: var(--jy-color-primary);
}
.jy-ui .btn-outline:hover {
  background: var(--jy-color-primary);
  color: var(--jy-color-primary-text);
}

.jy-ui .btn-ghost {
  background: transparent;
  color: var(--jy-color-text);
  border-color: transparent;
}
.jy-ui .btn-ghost:hover { background: var(--jy-color-surface-alt); }

.jy-ui .btn-destructive,
.jy-ui .btn-danger {
  background: var(--jy-color-danger);
  color: #ffffff;
  border-color: var(--jy-color-danger);
}
.jy-ui .btn-destructive:hover,
.jy-ui .btn-danger:hover {
  background: color-mix(in srgb, var(--jy-color-danger) 85%, black);
}

.jy-ui .btn-sm {
  height: var(--jy-control-h-sm);
  padding: 0 var(--jy-space-3);
  font-size: var(--jy-text-xs);
}
.jy-ui .btn-lg {
  height: var(--jy-control-h-lg);
  padding: 0 var(--jy-space-5);
  font-size: var(--jy-text-base);
}
.jy-ui .btn-block { width: 100%; }

/* ─── Forms (FormWriterV2HTML5 class names) ───────────────────── */
.jy-ui .form-group { margin-bottom: var(--jy-space-4); }

.jy-ui .form-label {
  display: block;
  font-size: var(--jy-text-sm);
  font-weight: 600;
  color: var(--jy-color-text);
  margin-bottom: var(--jy-space-2);
}
.jy-ui .form-label span[aria-label="required"] {
  color: var(--jy-color-danger);
  margin-left: 2px;
}

.jy-ui .form-control {
  display: block;
  width: 100%;
  height: var(--jy-control-h-md);
  padding: 0 var(--jy-space-3);
  font-family: var(--jy-font-sans);
  font-size: var(--jy-text-sm);
  color: var(--jy-color-text);
  background: var(--jy-color-bg);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-md);
  transition: border-color 0.15s, box-shadow 0.15s;
  appearance: none;
}
.jy-ui textarea.form-control {
  height: auto;
  min-height: calc(var(--jy-control-h-md) * 2.5);
  padding: var(--jy-space-3);
  line-height: var(--jy-leading-base);
  resize: vertical;
}
.jy-ui select.form-control {
  background-image:
    linear-gradient(45deg, transparent 50%, var(--jy-color-text-muted) 50%),
    linear-gradient(135deg, var(--jy-color-text-muted) 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: var(--jy-space-8);
  cursor: pointer;
}
.jy-ui .form-control::placeholder { color: var(--jy-color-text-subtle); }
.jy-ui .form-control:focus {
  outline: none;
  border-color: var(--jy-color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--jy-color-primary) 18%, transparent);
}
.jy-ui .form-control.is-invalid { border-color: var(--jy-color-danger); }
.jy-ui .form-control.is-invalid:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--jy-color-danger) 20%, transparent);
}

.jy-ui .form-error {
  margin-top: var(--jy-space-1);
  font-size: var(--jy-text-xs);
  color: var(--jy-color-danger);
}
.jy-ui .error-list { list-style: none; padding: 0; margin: 0; }

/* Validation error summary — the .jy-error-summary container FormWriter emits
   before a form's first submit button, filled by JoineryValidator on a failed
   submit attempt (or by PHP when the form re-renders carrying server errors).
   Unscoped because forms exist on every theme, inside .jy-ui or not; token
   fallbacks keep it legible where a branded theme redefines nothing. */
.jy-error-summary {
  margin: var(--jy-space-4, 1rem) 0;
  padding: var(--jy-space-3, .75rem) var(--jy-space-4, 1rem);
  border: 1px solid var(--jy-color-danger, #b3261e);
  border-left-width: 4px;
  border-radius: var(--jy-radius, 6px);
  background: var(--jy-color-danger-bg, #fbeae9);
  color: var(--jy-color-text, #1a1d23);
}
.jy-error-summary:focus {
  outline: 2px solid var(--jy-color-danger, #b3261e);
  outline-offset: 2px;
}
.jy-error-summary-title {
  margin: 0 0 var(--jy-space-1, .25rem);
  font-weight: 600;
  color: var(--jy-color-danger, #b3261e);
}
.jy-error-summary-list { margin: 0; padding-left: 1.25rem; }
.jy-error-summary-list li { margin: .15rem 0; }
.jy-error-summary-list a {
  color: var(--jy-color-danger, #b3261e);
  text-decoration: underline;
}
.jy-error-summary-list a:hover { text-decoration: none; }

.jy-ui .form-help {
  display: block;
  margin-top: var(--jy-space-1);
  font-size: var(--jy-text-xs);
  color: var(--jy-color-text-muted);
}

/* "How do I get this?" — FormWriter's help_modal trigger. A link-weight button
   under the field, not a heavy one: it is an offer, not the field's action. */
.jy-ui .jy-help-trigger {
  display: inline-block;
  margin-top: var(--jy-space-1);
  padding: 0;
  border: 0;
  background: none;
  font-size: var(--jy-text-xs);
  color: var(--jy-color-primary);
  text-decoration: underline;
  cursor: pointer;
}
.jy-ui .jy-help-trigger:hover { text-decoration: none; }

.jy-ui .form-check {
  display: flex;
  align-items: center;
  gap: var(--jy-space-2);
  padding-left: 0;
  margin-bottom: var(--jy-space-2);
}
.jy-ui .form-check-input {
  position: relative;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  accent-color: var(--jy-color-primary);
  cursor: pointer;
  margin: 0;
}
.jy-ui .form-check-label {
  font-size: var(--jy-text-sm);
  color: var(--jy-color-text);
  cursor: pointer;
  line-height: 1.4;
  margin-bottom: 0;
}

/* Radio cards — the shape a choice takes when each option carries a promise
   rather than a label (protection levels, plan tiers). FormWriter emits this
   markup for radioinput(..., ['card' => true]); the admin theme styles the same
   markup on its own chrome, and this is the kit's copy for every other surface. */
.jy-ui .jy-radio-cards {
  display: flex;
  flex-direction: column;
  gap: var(--jy-space-3);
  margin-bottom: var(--jy-space-2);
}
.jy-ui .form-check.jy-radio-card {
  align-items: flex-start;
  gap: var(--jy-space-3);
  margin-bottom: 0;
  padding: var(--jy-space-3) var(--jy-space-4);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-lg);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.jy-ui .form-check.jy-radio-card input[type="radio"] { margin-top: 0.2rem; }
.jy-ui .form-check.jy-radio-card:has(input[type="radio"]:checked) {
  border-color: var(--jy-color-primary);
  background: var(--jy-color-info-bg);
}
/* A disabled card is an option this member cannot take right now — say so by
   fading it, never by hiding it: the reason is written above the list. */
.jy-ui .form-check.jy-radio-card:has(input[type="radio"]:disabled) {
  opacity: 0.55;
}
.jy-ui .form-check.jy-radio-card .form-check-label {
  display: flex;
  flex-direction: column;
  gap: var(--jy-space-1);
  font-weight: 600;
}
.jy-ui .jy-radio-card-desc {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-weight: 400;
  font-size: var(--jy-text-xs);
  color: var(--jy-color-text-muted);
}

/* ─── Cards ───────────────────────────────────────────────────── */
.jy-ui .card {
  background: var(--jy-color-bg);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-lg);
  box-shadow: var(--jy-shadow-sm);
  overflow: hidden;
  margin-bottom: var(--jy-space-4);
}
.jy-ui .card:last-child { margin-bottom: 0; }
.jy-ui .mb-3 { margin-bottom: var(--jy-space-4) !important; }

.jy-ui .card-header {
  padding: var(--jy-space-4) var(--jy-space-5);
  background: var(--jy-color-surface);
  border-bottom: 1px solid var(--jy-color-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--jy-space-3);
}
.jy-ui .card-header.bg-body-tertiary { background: var(--jy-color-surface); }
.jy-ui .card-header h6,
.jy-ui .card-header .h6 {
  margin-bottom: 0;
  font-size: var(--jy-text-sm);
  font-weight: 600;
}
.jy-ui .card-body { padding: var(--jy-space-5); }
.jy-ui .card-footer {
  padding: var(--jy-space-4) var(--jy-space-5);
  background: var(--jy-color-surface);
  border-top: 1px solid var(--jy-color-border);
}

/* ─── Auth Card ───────────────────────────────────────────────── */
.jy-ui .auth-page,
.jy-ui .auth-wrap {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  min-height: calc(100vh - 60px);
  padding: var(--jy-space-8) var(--jy-space-5);
  background: var(--jy-color-surface);
}
.jy-ui .auth-card {
  width: 420px;
  max-width: 100%;
  background: var(--jy-color-bg);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-lg);
  padding: var(--jy-space-6);
  box-shadow: var(--jy-shadow-md);
}
.jy-ui .auth-logo {
  display: flex;
  justify-content: center;
  margin-bottom: var(--jy-space-5);
}
.jy-ui .auth-logo a {
  display: flex;
  align-items: center;
  gap: var(--jy-space-2);
  font-family: var(--jy-font-display);
  font-size: var(--jy-text-xl);
  font-weight: 700;
  color: var(--jy-color-text);
  text-decoration: none;
}
.jy-ui .auth-logo img { height: 40px; width: auto; }
.jy-ui .auth-card h3 {
  font-size: var(--jy-text-2xl);
  text-align: center;
  margin-bottom: var(--jy-space-5);
}
.jy-ui .auth-card .btn-primary { width: 100%; margin-top: var(--jy-space-4); }
.jy-ui .auth-footer-text {
  margin-top: var(--jy-space-5);
  text-align: center;
  font-size: var(--jy-text-sm);
  color: var(--jy-color-text-muted);
}
.jy-ui .auth-links {
  display: flex;
  justify-content: space-between;
  margin-top: var(--jy-space-4);
  font-size: var(--jy-text-sm);
}

/* ─── Alerts ──────────────────────────────────────────────────── */
/* renderAlert() outputs .alert .alert-{type}
   types used: success, warning (mapped from 'warn'), error, info */
.jy-ui .alert {
  display: flex;
  align-items: flex-start;
  gap: var(--jy-space-3);
  padding: var(--jy-space-3) var(--jy-space-4);
  border-radius: var(--jy-radius-md);
  border: 1px solid transparent;
  font-size: var(--jy-text-sm);
  margin-bottom: var(--jy-space-4);
}
.jy-ui .alert:last-child { margin-bottom: 0; }
.jy-ui .alert[role="alert"] h4 {
  font-size: var(--jy-text-sm);
  font-weight: 700;
  margin-bottom: var(--jy-space-1);
}
.jy-ui .alert[role="alert"] p { margin-bottom: 0; }
.jy-ui .alert svg { width: 18px; height: 18px; flex-shrink: 0; margin-top: 1px; }

.jy-ui .alert-success {
  background: var(--jy-color-success-bg);
  color: var(--jy-color-success);
  border-color: color-mix(in srgb, var(--jy-color-success) 25%, transparent);
}
.jy-ui .alert-info {
  background: var(--jy-color-info-bg);
  color: var(--jy-color-info);
  border-color: color-mix(in srgb, var(--jy-color-info) 25%, transparent);
}
.jy-ui .alert-warning,
.jy-ui .alert-warn {
  background: var(--jy-color-warning-bg);
  color: var(--jy-color-warning);
  border-color: color-mix(in srgb, var(--jy-color-warning) 25%, transparent);
}
.jy-ui .alert-error,
.jy-ui .alert-danger {
  background: var(--jy-color-danger-bg);
  color: var(--jy-color-danger);
  border-color: color-mix(in srgb, var(--jy-color-danger) 25%, transparent);
}

/* ─── Badges ──────────────────────────────────────────────────── */
.jy-ui .badge {
  display: inline-flex;
  align-items: center;
  gap: var(--jy-space-1);
  padding: 2px var(--jy-space-2);
  font-size: var(--jy-text-xs);
  font-weight: 600;
  border-radius: var(--jy-radius-full);
  line-height: 1.5;
  background: var(--jy-color-surface-alt);
  color: var(--jy-color-text-muted);
  border: 1px solid var(--jy-color-border);
  white-space: nowrap;
}
.jy-ui .badge-success { background: var(--jy-color-success-bg); color: var(--jy-color-success); border-color: transparent; }
.jy-ui .badge-warning { background: var(--jy-color-warning-bg); color: var(--jy-color-warning); border-color: transparent; }
.jy-ui .badge-danger,
.jy-ui .badge-error   { background: var(--jy-color-danger-bg);  color: var(--jy-color-danger);  border-color: transparent; }
.jy-ui .badge-info    { background: var(--jy-color-info-bg);    color: var(--jy-color-info);    border-color: transparent; }
.jy-ui .badge-primary {
  background: color-mix(in srgb, var(--jy-color-primary) 12%, var(--jy-color-bg));
  color: var(--jy-color-primary);
  border-color: transparent;
}
.jy-ui .badge-muted { background: var(--jy-color-surface-alt); color: var(--jy-color-text-subtle); border-color: transparent; }
.jy-ui .tag {
  display: inline-block;
  padding: var(--jy-space-1) var(--jy-space-3);
  font-size: var(--jy-text-xs);
  font-weight: 500;
  background: var(--jy-color-surface);
  color: var(--jy-color-text-muted);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-sm);
}

/* ─── Tables ──────────────────────────────────────────────────── */
.jy-ui .table-wrap,
.jy-ui .table-wrapper {
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-md);
  overflow: hidden;
  background: var(--jy-color-bg);
  margin-bottom: var(--jy-space-5);
}
.jy-ui table,
.jy-ui table.data,
.jy-ui .styled-table { width: 100%; border-collapse: collapse; font-size: var(--jy-text-sm); }
.jy-ui table th {
  text-align: left;
  padding: var(--jy-space-3) var(--jy-space-4);
  background: var(--jy-color-surface);
  font-weight: 600;
  color: var(--jy-color-text-muted);
  font-size: var(--jy-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom: 1px solid var(--jy-color-border);
}
.jy-ui table td {
  text-align: left;
  padding: var(--jy-space-3) var(--jy-space-4);
  border-bottom: 1px solid var(--jy-color-border);
  color: var(--jy-color-text);
  vertical-align: middle;
}
.jy-ui table tbody tr:nth-child(even) td { background: var(--jy-color-surface); }
.jy-ui table tbody tr:hover td { background: var(--jy-color-surface-alt); }
.jy-ui table tbody tr:last-child td { border-bottom: none; }
.jy-ui td.num { text-align: right; font-variant-numeric: tabular-nums; }

/* ─── Profile Tabs ────────────────────────────────────────────── */
.jy-ui .tabs {
  display: flex;
  border-bottom: 1px solid var(--jy-color-border);
  margin-bottom: var(--jy-space-5);
  gap: var(--jy-space-1);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.jy-ui .tab {
  padding: var(--jy-space-3) var(--jy-space-4);
  font-size: var(--jy-text-sm);
  font-weight: 500;
  color: var(--jy-color-text-muted);
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
  cursor: pointer;
  background: none;
  font-family: var(--jy-font-sans);
  transition: color 0.15s;
}
.jy-ui .tab:hover { color: var(--jy-color-text); }
.jy-ui .tab.active {
  color: var(--jy-color-primary);
  border-bottom-color: var(--jy-color-primary);
  font-weight: 600;
}

/* ─── Item Grids ──────────────────────────────────────────────── */
.jy-ui .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--jy-space-5); }
.jy-ui .grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--jy-space-5); }

.jy-ui .event-card,
.jy-ui .product-card {
  background: var(--jy-color-bg);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--jy-shadow-sm);
  transition: transform 0.15s, box-shadow 0.15s;
  text-decoration: none;
  color: inherit;
}
.jy-ui .event-card:hover,
.jy-ui .product-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--jy-shadow-md);
  text-decoration: none;
}
.jy-ui .thumb {
  aspect-ratio: 16 / 10;
  background: var(--jy-color-surface-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.jy-ui .product-card .thumb { aspect-ratio: 4 / 3; }
.jy-ui .thumb img { width: 100%; height: 100%; object-fit: cover; }
.jy-ui .thumb svg { width: 48px; height: 48px; color: var(--jy-color-text-subtle); }

/* ─── Empty State ─────────────────────────────────────────────── */
.jy-ui .empty {
  text-align: center;
  padding: var(--jy-space-10) var(--jy-space-5);
  background: var(--jy-color-surface);
  border: 1px dashed var(--jy-color-border-strong);
  border-radius: var(--jy-radius-lg);
}
.jy-ui .empty svg { width: 48px; height: 48px; color: var(--jy-color-text-subtle); margin: 0 auto var(--jy-space-4); }
.jy-ui .empty h4 { margin-bottom: var(--jy-space-2); }
.jy-ui .empty p { color: var(--jy-color-text-muted); margin-bottom: var(--jy-space-4); }

/* ─── Cart Summary ────────────────────────────────────────────── */
.jy-ui .cart {
  background: var(--jy-color-bg);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-lg);
  overflow: hidden;
}
.jy-ui .cart-line {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: var(--jy-space-4);
  align-items: center;
  padding: var(--jy-space-4) var(--jy-space-5);
  border-bottom: 1px solid var(--jy-color-border);
  font-size: var(--jy-text-sm);
}
.jy-ui .cart-totals { background: var(--jy-color-surface); padding: var(--jy-space-3) var(--jy-space-5); }
.jy-ui .cart-totals .row {
  display: flex;
  justify-content: space-between;
  padding: var(--jy-space-1) 0;
  font-size: var(--jy-text-sm);
  color: var(--jy-color-text-muted);
}
.jy-ui .cart-totals .row.total {
  font-size: var(--jy-text-lg);
  font-weight: 700;
  color: var(--jy-color-text);
  border-top: 1px solid var(--jy-color-border);
  padding-top: var(--jy-space-3);
  margin-top: var(--jy-space-2);
}
.jy-ui .cart-cta { padding: var(--jy-space-5); }
.jy-ui .cart-cta .btn { width: 100%; }

/* ─── Pagination ──────────────────────────────────────────────── */
.jy-ui .pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--jy-space-2);
  flex-wrap: wrap;
  margin: var(--jy-space-6) 0;
}
.jy-ui .pagination a,
.jy-ui .pagination span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--jy-control-h-sm);
  height: var(--jy-control-h-sm);
  padding: 0 var(--jy-space-3);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-sm);
  font-size: var(--jy-text-sm);
  color: var(--jy-color-text);
  background: var(--jy-color-bg);
  text-decoration: none;
  transition: background 0.15s;
}
.jy-ui .pagination a:hover { background: var(--jy-color-surface-alt); text-decoration: none; }
.jy-ui .pagination .active,
.jy-ui .pagination .current {
  background: var(--jy-color-primary);
  border-color: var(--jy-color-primary);
  color: var(--jy-color-primary-text);
}
.jy-ui .pagination .ellipsis { border: none; background: none; color: var(--jy-color-text-subtle); }
.jy-ui .pagination .disabled { opacity: 0.4; pointer-events: none; }

/* ─── Scoped Breadcrumbs ──────────────────────────────────────── */
.jy-ui nav.jy-breadcrumbs { font-size: var(--jy-text-sm); color: var(--jy-color-text-muted); }
.jy-ui nav.jy-breadcrumbs ol { display: flex; align-items: center; gap: var(--jy-space-2); list-style: none; flex-wrap: wrap; }
.jy-ui nav.jy-breadcrumbs li { display: flex; align-items: center; gap: var(--jy-space-2); }
.jy-ui nav.jy-breadcrumbs li::before { content: '›'; color: var(--jy-color-text-subtle); }
.jy-ui nav.jy-breadcrumbs li:first-child::before { display: none; }
.jy-ui nav.jy-breadcrumbs a { color: var(--jy-color-text-muted); }
.jy-ui nav.jy-breadcrumbs a:hover { color: var(--jy-color-primary); text-decoration: none; }
.jy-ui nav.jy-breadcrumbs li.active { color: var(--jy-color-text); font-weight: 500; }

/* ─── Content Helpers ─────────────────────────────────────────── */
.jy-ui .action-row { display: flex; gap: var(--jy-space-3); margin-top: var(--jy-space-5); flex-wrap: wrap; }
.jy-ui .pill-row   { display: flex; gap: var(--jy-space-2); flex-wrap: wrap; }
.jy-ui .stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--jy-space-4);
}

/* ─── Responsive ──────────────────────────────────────────────── */
@media (max-width: 900px) {
  .jy-ui .grid-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .jy-ui .grid-3,
  .jy-ui .grid-2 { grid-template-columns: 1fr; }
  .jy-ui .auth-page,
  .jy-ui .auth-wrap { padding: var(--jy-space-4) var(--jy-space-3); }
  .jy-ui .auth-card { padding: var(--jy-space-5); }
}

/* ─── Modal dialog (JoineryModal) ───────────────────────────────
   The native <dialog> is created by JoineryModal in base.js and tagged
   with the `jy-ui` class, so these scoped rules reach it even though it
   renders in the top layer outside any page-level .jy-ui wrapper. */
dialog.jy-ui {
  position: fixed;
  inset: 0;
  margin: auto;
  padding: var(--jy-space-5);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-md);
  background: var(--jy-color-bg);
  color: var(--jy-color-text);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
  max-width: 480px;
  width: calc(100% - 2rem);
  max-height: calc(100vh - 4rem);
  z-index: 2000;
}
/* Content mode can be given more than fits: a column layout scrolls the content
   area and keeps the action row on screen, so a long dialog never hides its own
   buttons. Scoped to [open] so the closed dialog stays display:none. */
dialog.jy-ui[open] { display: flex; flex-direction: column; }
dialog.jy-ui::backdrop { background: rgba(0, 0, 0, 0.45); }
.jy-ui .dialog-message { margin-bottom: var(--jy-space-5); line-height: 1.5; }
.jy-ui .dialog-content { margin-bottom: var(--jy-space-5); overflow-y: auto; }
.jy-ui .dialog-input {
  display: block;
  width: 100%;
  padding: 0.375rem 0.625rem;
  margin-bottom: var(--jy-space-4);
  border: 1px solid var(--jy-color-border);
  border-radius: var(--jy-radius-sm);
  font-size: 0.875rem;
  color: var(--jy-color-text);
  background: var(--jy-color-bg);
  box-sizing: border-box;
}
.jy-ui .dialog-input:focus {
  outline: 2px solid var(--jy-color-primary);
  outline-offset: -1px;
  border-color: var(--jy-color-primary);
}
/* Buttons are kit .btn / .btn-* (built by JoineryModal). The action row owns
   only layout. */
.jy-ui .dialog-actions { display: flex; justify-content: flex-end; gap: var(--jy-space-2); }

/* A field help guide rendered inside the modal (FormWriter help_modal). Steps
   are the content; the copy rows and the provider link are the two things the
   operator acts on, so both are given weight. */
.jy-ui .jy-help-guide-title { margin: 0 0 var(--jy-space-3); font-size: var(--jy-text-lg); }
.jy-ui .jy-help-guide-steps {
  /* Stated rather than inherited: these are numbered clicks in order, and the
     kit reset drops list markers. */
  list-style: decimal;
  margin: 0 0 var(--jy-space-4);
  padding-left: var(--jy-space-5);
  line-height: 1.6;
}
.jy-ui .jy-help-guide-steps li { margin-bottom: var(--jy-space-2); }
.jy-ui .jy-help-guide-caution {
  margin: 0 0 var(--jy-space-4);
  padding: var(--jy-space-2) var(--jy-space-3);
  border-left: 3px solid var(--jy-color-warning);
  background: var(--jy-color-warning-bg);
  font-size: var(--jy-text-sm);
}
.jy-ui .jy-help-guide-copy {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--jy-space-2);
  margin-bottom: var(--jy-space-2);
  padding: var(--jy-space-2) var(--jy-space-3);
  background: var(--jy-color-surface-alt);
  border-radius: var(--jy-radius-sm);
}
.jy-ui .jy-help-guide-copy-label { font-size: var(--jy-text-xs); color: var(--jy-color-text-muted); }
.jy-ui .jy-help-guide-copy code { word-break: break-all; }
.jy-ui .jy-help-guide-link { margin: var(--jy-space-4) 0 0; }

/* ─── Component layout wrapper (ComponentRenderer) ──────────────
   Emitted by ComponentRenderer when a component instance overrides max-width /
   max-height / vertical margin. The wrapper sets the per-instance values as
   --jy-cl-* custom properties inline (server-computed); these rules consume
   them. Layout chrome — jy-prefixed and unscoped, not under .jy-ui. */
.jy-cl[data-maxw] .container,
.jy-cl[data-maxw] .container-fluid,
.jy-cl[data-maxw] .container-lg,
.jy-cl[data-maxw] .container-xl {
  max-width: var(--jy-cl-max-width);
}
.jy-cl[data-maxw]:not(:has(.container, .container-fluid, .container-lg, .container-xl)) > :first-child {
  max-width: var(--jy-cl-max-width);
  margin-left: auto;
  margin-right: auto;
}
.jy-cl[data-maxh] > :first-child {
  max-height: var(--jy-cl-max-height);
  overflow: hidden;
}
.jy-cl[data-vmargin="none"] { margin-top: 0; margin-bottom: 0; }
.jy-cl[data-vmargin="sm"] { margin-top: 1rem; margin-bottom: 1rem; }
.jy-cl[data-vmargin="md"] { margin-top: 2rem; margin-bottom: 2rem; }
.jy-cl[data-vmargin="lg"] { margin-top: 3rem; margin-bottom: 3rem; }
.jy-cl[data-vmargin="xl"] { margin-top: 5rem; margin-bottom: 5rem; }

/* ═══════════════════════════════════════════════════════════════
   Page components (views/components/*) — each component's structure
   lives here as a .jy-{component}-* section; per-instance values
   arrive as inline --jy-* custom properties (server-computed).
   ═══════════════════════════════════════════════════════════════ */

/* ─── Accordion ─────────────────────────────────────────────── */
.jy-ui .jy-accordion { max-width: 1100px; margin: 0 auto; padding: var(--jy-space-8) var(--jy-space-4); }
.jy-ui .jy-accordion-header { text-align: center; margin-bottom: var(--jy-space-6); }
.jy-ui .jy-accordion-header h2 { margin: 0 0 var(--jy-space-2) 0; }
.jy-ui .jy-accordion-header p { margin: 0; color: var(--jy-color-text-muted); }
.jy-ui .jy-accordion details { border: 1px solid var(--jy-color-border); border-radius: var(--jy-radius-sm); margin-bottom: var(--jy-space-2); }
.jy-ui .jy-accordion.is-flush details { border: none; border-bottom: 1px solid var(--jy-color-border); border-radius: 0; margin-bottom: 0; }
.jy-ui .jy-accordion summary { padding: var(--jy-space-4); font-weight: 600; cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; }
.jy-ui .jy-accordion summary::-webkit-details-marker { display: none; }
.jy-ui .jy-accordion summary::after { content: '+'; font-size: 1.25rem; font-weight: 400; transition: transform 0.2s; }
.jy-ui .jy-accordion details[open] > summary::after { content: '\2212'; }
.jy-ui .jy-accordion .acc-content { padding: 0 var(--jy-space-4) var(--jy-space-4); }

/* ─── Tabs ──────────────────────────────────────────────────── */
.jy-ui .jy-tabs { max-width: 1100px; margin: 0 auto; padding: var(--jy-space-8) var(--jy-space-4); }
.jy-ui .jy-tabs-heading { margin: 0 0 var(--jy-space-5) 0; }
.jy-ui .jy-tabs-list { display: flex; gap: 0; justify-content: flex-start; list-style: none; margin: 0 0 var(--jy-space-5) 0; padding: 0; border-bottom: 2px solid var(--jy-color-border); }
.jy-ui .jy-tabs.is-center .jy-tabs-list { justify-content: center; }
.jy-ui .jy-tabs.is-pills .jy-tabs-list { border-bottom: none; }
.jy-ui .jy-tabs-list button { background: none; border: none; padding: var(--jy-space-3) var(--jy-space-5); cursor: pointer; font-size: 1rem; color: var(--jy-color-text-muted); position: relative; margin-bottom: -2px; }
.jy-ui .jy-tabs.is-pills .jy-tabs-list button { border-radius: 2rem; margin-right: var(--jy-space-2); margin-bottom: 0; }
.jy-ui .jy-tabs-list button:hover { color: var(--jy-color-text); }
.jy-ui .jy-tabs-list button[aria-selected="true"] { color: var(--jy-color-text); font-weight: 600; border-bottom: 2px solid var(--jy-color-text); }
.jy-ui .jy-tabs.is-pills .jy-tabs-list button[aria-selected="true"] { border-bottom: none; background-color: var(--jy-color-surface-alt); }
.jy-ui .jy-tabs-panel { display: none; }
.jy-ui .jy-tabs-panel.active { display: block; }

/* ─── Text with image ───────────────────────────────────────── */
.jy-ui .jy-twi-section { background: var(--jy-twi-bg, transparent); }
.jy-ui .jy-twi { max-width: 1100px; margin: 0 auto; padding: var(--jy-space-8) var(--jy-space-4); display: flex; flex-direction: row; gap: var(--jy-space-6); align-items: center; }
.jy-ui .jy-twi.is-reverse { flex-direction: row-reverse; }
.jy-ui .jy-twi-text { flex: 1 1 0%; min-width: 0; }
.jy-ui .jy-twi-text h2 { margin: 0 0 var(--jy-space-4) 0; }
.jy-ui .jy-twi-image { flex: 0 0 var(--jy-twi-img, 50%); min-width: 0; }
.jy-ui .jy-twi-image img { width: 100%; height: auto; display: block; object-fit: cover; border-radius: var(--jy-radius-sm); }
.jy-ui .jy-twi-cta { margin-top: var(--jy-space-4); }
@media (max-width: 768px) {
  .jy-ui .jy-twi { flex-direction: column; }
  .jy-ui .jy-twi-image { flex: 0 0 100%; }
}

/* ─── Feature grid ──────────────────────────────────────────── */
.jy-ui .jy-feature-grid { padding: var(--jy-space-8) var(--jy-space-4); background: var(--jy-fg-bg, transparent); }
.jy-ui .jy-feature-grid-inner { max-width: 1100px; margin: 0 auto; }
.jy-ui .jy-feature-grid-header { text-align: center; margin-bottom: 2.5rem; }
.jy-ui .jy-feature-grid-header h2 { margin: 0 0 var(--jy-space-2) 0; }
.jy-ui .jy-feature-grid-header p { margin: 0; color: var(--jy-color-text-muted); }
.jy-ui .jy-feature-grid-grid { display: grid; grid-template-columns: repeat(var(--jy-fg-cols, 3), 1fr); gap: var(--jy-space-6); }
.jy-ui .jy-feature-grid-item { text-align: center; position: relative; }
.jy-ui .jy-feature-grid.is-left .jy-feature-grid-item { text-align: left; }
.jy-ui .jy-feature-grid-icon { margin-bottom: var(--jy-space-3); }
.jy-ui .jy-feature-grid:not(.is-left) .jy-feature-grid-icon { display: flex; justify-content: center; }
.jy-ui .jy-feature-grid-icon i { font-size: 2rem; color: var(--jy-fg-icon, #333); }
.jy-ui .jy-feature-grid-iconwrap { display: inline-flex; width: 64px; height: 64px; align-items: center; justify-content: center; background-color: var(--jy-fg-icon-bg); }
.jy-ui .jy-feature-grid-iconwrap.is-circle { border-radius: 50%; }
.jy-ui .jy-feature-grid-iconwrap.is-square { border-radius: 8px; }
.jy-ui .jy-feature-grid-item h3 { margin: 0 0 var(--jy-space-2) 0; font-size: 1.1rem; }
.jy-ui .jy-feature-grid-item p { margin: 0; color: var(--jy-color-text-muted); font-size: 0.95rem; line-height: 1.6; }
.jy-ui .jy-feature-grid-item a.item-link { position: absolute; inset: 0; }
@media (max-width: 768px) {
  .jy-ui .jy-feature-grid-grid { grid-template-columns: repeat(var(--jy-fg-cols-mobile, 2), 1fr); gap: var(--jy-space-5); }
}
@media (max-width: 480px) {
  .jy-ui .jy-feature-grid-grid { grid-template-columns: 1fr; }
}

/* ─── Divider ───────────────────────────────────────────────── */
.jy-ui .jy-divider { max-width: 1100px; margin: 0 auto; padding: 0 var(--jy-space-4); }
.jy-ui .jy-divider hr {
  border: 0;
  border-top-width: 1px;
  border-top-style: var(--jy-divider-style, solid);
  border-top-color: var(--jy-divider-color, var(--jy-color-border));
  width: var(--jy-divider-width, 100%);
}
.jy-ui .jy-divider.is-centered hr { margin-left: auto; margin-right: auto; }

/* ─── Spacer ────────────────────────────────────────────────── */
.jy-ui .jy-spacer { height: 2rem; }
.jy-ui .jy-spacer.is-sm { height: 1rem; }
.jy-ui .jy-spacer.is-lg { height: 4rem; }
.jy-ui .jy-spacer.is-xl { height: 6rem; }

/* ─── Page title ────────────────────────────────────────────── */
.jy-ui .jy-pagetitle { background: var(--jy-pt-bg, var(--jy-color-surface)); color: var(--jy-pt-text, var(--jy-color-text)); padding: var(--jy-space-5) var(--jy-space-4); }
.jy-ui .jy-pagetitle-inner { max-width: 1100px; margin: 0 auto; text-align: var(--jy-pt-align, left); }
.jy-ui .jy-pagetitle h1 { margin: 0 0 var(--jy-space-1) 0; }
.jy-ui .jy-pagetitle-subtitle { margin: 0; color: var(--jy-color-text-muted); font-size: 1.05rem; }
.jy-ui .jy-pagetitle-crumbs { margin-bottom: var(--jy-space-3); }
.jy-ui .jy-pagetitle-crumbs ol { display: flex; flex-wrap: wrap; gap: var(--jy-space-1) var(--jy-space-2); list-style: none; margin: 0; padding: 0; font-size: 0.875rem; color: var(--jy-color-text-muted); }
.jy-ui .jy-pagetitle-crumbs a { color: inherit; }
.jy-ui .jy-pagetitle-crumbs .sep { margin-left: var(--jy-space-2); }

/* ─── Text block ────────────────────────────────────────────── */
.jy-ui .jy-textblock-section { background: var(--jy-tb-bg, transparent); color: var(--jy-tb-text, inherit); }
.jy-ui .jy-textblock { max-width: 1100px; margin: 0 auto; padding: var(--jy-space-8) var(--jy-space-4); text-align: var(--jy-tb-align, left); }
.jy-ui .jy-textblock-heading { margin: 0 0 var(--jy-space-4) 0; }

/* ─── CTA banner ────────────────────────────────────────────── */
.jy-ui .jy-cta-banner { background: var(--jy-cta-bg, var(--jy-color-primary)); color: var(--jy-cta-text, #fff); padding: var(--jy-space-10) var(--jy-space-5); text-align: center; }
.jy-ui .jy-cta-banner.has-image { background-size: cover; background-position: center; }
.jy-ui .jy-cta-banner-inner { max-width: 720px; margin: 0 auto; }
.jy-ui .jy-cta-banner h2 { margin: 0 0 var(--jy-space-4) 0; font-size: 2rem; line-height: 1.2; }
.jy-ui .jy-cta-banner-sub { margin: 0 0 var(--jy-space-6) 0; opacity: 0.9; font-size: 1.1rem; line-height: 1.6; }
.jy-ui .jy-cta-banner-actions { display: flex; gap: var(--jy-space-4); justify-content: center; flex-wrap: wrap; }
.jy-ui .jy-cta-banner-btn { display: inline-block; padding: 0.75rem 2rem; background: rgba(255, 255, 255, 0.95); color: #111; text-decoration: none; border-radius: var(--jy-radius-sm); font-weight: 600; }
.jy-ui .jy-cta-banner-btn.is-secondary { background: transparent; border: 2px solid rgba(255, 255, 255, 0.7); color: inherit; }

/* ─── Hero (static) ─────────────────────────────────────────── */
.jy-ui .jy-hero { background: var(--jy-hero-bg, var(--jy-color-surface)); color: var(--jy-hero-text, var(--jy-color-text)); padding: 5rem 1.5rem; }
.jy-ui .jy-hero.is-sm { padding: 3rem 1.5rem; }
.jy-ui .jy-hero.is-lg { padding: 8rem 1.5rem; }
.jy-ui .jy-hero.is-fullscreen { min-height: 100vh; display: flex; align-items: center; padding: 5rem 1.5rem; }
.jy-ui .jy-hero.has-image { background-size: cover; background-position: center; }
.jy-ui .jy-hero-inner { max-width: 720px; margin: 0 auto; width: 100%; text-align: var(--jy-hero-align, center); }
.jy-ui .jy-hero h1 { margin: 0 0 var(--jy-space-4) 0; font-size: 2.5rem; line-height: 1.2; }
.jy-ui .jy-hero-sub { margin: 0 0 var(--jy-space-6) 0; font-size: 1.2rem; opacity: 0.85; line-height: 1.6; }
.jy-ui .jy-hero-btn { display: inline-block; padding: 0.75rem 2rem; text-decoration: none; border-radius: var(--jy-radius-sm); font-weight: 600; background: var(--jy-hero-text); color: var(--jy-hero-btnfg, #fff); }
.jy-ui .jy-hero-btn.is-secondary { background: transparent; border: 2px solid currentColor; color: inherit; }

/* ─── Video embed ───────────────────────────────────────────── */
.jy-ui .jy-video { max-width: 1100px; margin: 0 auto; padding: var(--jy-space-8) var(--jy-space-4); }
.jy-ui .jy-video h2 { margin: 0 0 var(--jy-space-5) 0; }
.jy-ui .jy-video-frame { aspect-ratio: var(--jy-video-ratio, 16 / 9); width: 100%; }
.jy-ui .jy-video-frame iframe { width: 100%; height: 100%; border: 0; }
.jy-ui .jy-video-caption { margin: var(--jy-space-3) 0 0 0; color: var(--jy-color-text-muted); font-size: 0.9rem; }

/* ─── Image gallery ─────────────────────────────────────────── */
.jy-ui .jy-gallery-main img { width: 100%; max-height: 500px; object-fit: cover; border-radius: var(--jy-radius-md); display: block; }
.jy-ui .jy-gallery-caption { text-align: center; margin: var(--jy-space-2) 0 0; color: var(--jy-color-text-muted); font-size: 0.9em; }
.jy-ui .jy-gallery-thumbs { display: flex; gap: var(--jy-space-2); margin-top: var(--jy-space-3); overflow-x: auto; padding-bottom: var(--jy-space-1); }
.jy-ui .jy-gallery-thumb { width: 80px; height: 60px; object-fit: cover; border-radius: var(--jy-radius-sm); cursor: pointer; flex-shrink: 0; transition: opacity 0.2s, border-color 0.2s; opacity: 0.5; border: 2px solid transparent; }
.jy-ui .jy-gallery-thumb.is-active { opacity: 1; border-color: var(--jy-color-primary); }

/* ─── List signup ───────────────────────────────────────────── */
.jy-ui .jy-listsignup { padding: var(--jy-space-5) 0; background: var(--jy-ls-bg, transparent); color: var(--jy-ls-text, inherit); }
.jy-ui .jy-listsignup-inner { max-width: 600px; margin: 0 auto; padding: 0 var(--jy-space-4); text-align: var(--jy-ls-align, center); }
.jy-ui .jy-listsignup h2 { margin: 0 0 var(--jy-space-2); }
.jy-ui .jy-listsignup-sub { margin: 0 0 var(--jy-space-4); opacity: 0.85; }
.jy-ui .jy-listsignup-submit { margin-top: var(--jy-space-4); }
.jy-ui.jy-listsignup-error { border: 2px dashed var(--jy-color-danger); background: var(--jy-color-danger-bg); padding: var(--jy-space-4) var(--jy-space-5); margin: var(--jy-space-4) 0; border-radius: var(--jy-radius-md); font-size: 0.9rem; }
.jy-ui.jy-listsignup-error strong { color: var(--jy-color-danger); }
.jy-ui.jy-listsignup-error ul { margin: var(--jy-space-2) 0 0; padding-left: var(--jy-space-5); color: var(--jy-color-text-muted); }
/* Compact mode (single-row email + submit) */
.jy-ui .jy-listsignup .lsu-compact .form-group,
.jy-ui .jy-listsignup .lsu-compact .mb-3 { margin-bottom: 0 !important; }
.jy-ui .jy-listsignup .lsu-compact-row { display: flex; gap: var(--jy-space-2); justify-content: var(--jy-ls-align, center); flex-wrap: wrap; align-items: center; }
.jy-ui .jy-listsignup .lsu-compact-row .lsu-email-wrap { flex: 1; max-width: 300px; min-width: 200px; }
.jy-ui .jy-listsignup .lsu-antispam { text-align: center; margin-top: var(--jy-space-2); }
.jy-ui .jy-listsignup .lsu-antispam .form-group,
.jy-ui .jy-listsignup .lsu-antispam .mb-3 { margin: 0 !important; display: inline-block; }
.jy-ui .jy-listsignup .lsu-antispam input[type="text"] { width: 140px !important; padding: 0.25rem 0.5rem; font-size: 0.85em; }
.jy-ui .jy-listsignup .lsu-list-name { margin: 0; opacity: 0.85; font-size: 0.95em; }
.jy-ui .jy-listsignup .lsu-compact .lsu-checkbox-list { text-align: left; display: inline-block; margin-bottom: var(--jy-space-2); }
.jy-ui .jy-listsignup .lsu-compact .lsu-checkbox-list .form-group,
.jy-ui .jy-listsignup .lsu-compact .lsu-checkbox-list .mb-3,
.jy-ui .jy-listsignup .lsu-compact .lsu-checkbox-list .form-check { margin-bottom: var(--jy-space-1) !important; }

/* ─── Slot picker (booking time picker) ─────────────────────── */
.jy-ui .joinery-slotpicker { --sp-accent: var(--jy-color-primary); font-family: inherit; }
.jy-ui .slotpick-cols { display: flex; gap: var(--jy-space-5); flex-wrap: wrap; }
.jy-ui .slotpick-cal { min-width: 270px; }
.jy-ui .slotpick-calhead { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--jy-space-2); }
.jy-ui .slotpick-month { font-weight: 600; }
.jy-ui .slotpick-nav { background: var(--jy-color-surface); border: 1px solid var(--jy-color-border); border-radius: 5px; padding: .25rem .6rem; cursor: pointer; }
.jy-ui .slotpick-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.jy-ui .slotpick-dow { text-align: center; font-size: .7rem; color: var(--jy-color-text-subtle); padding: .2rem 0; }
.jy-ui .slotpick-day { aspect-ratio: 1; border: none; background: none; border-radius: 50%; cursor: default; color: var(--jy-color-border-strong); font: inherit; }
.jy-ui .slotpick-day.has-slots { background: var(--jy-color-surface-alt); color: var(--sp-accent); font-weight: 600; cursor: pointer; }
.jy-ui .slotpick-day.has-slots:hover { background: var(--jy-color-surface); }
.jy-ui .slotpick-day.is-selected { background: var(--sp-accent); color: #fff; }
.jy-ui .slotpick-times { flex: 1; min-width: 220px; }
.jy-ui .slotpick-tzrow { margin-bottom: .6rem; font-size: .85rem; color: var(--jy-color-text-muted); }
.jy-ui .slotpick-daylabel { font-weight: 600; margin-bottom: var(--jy-space-2); }
.jy-ui .slotpick-timelist { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: .4rem; }
.jy-ui .slotpick-slot { border: 1px solid var(--sp-accent); color: var(--sp-accent); background: var(--jy-color-bg); border-radius: 5px; padding: .5rem; cursor: pointer; font: inherit; }
.jy-ui .slotpick-slot:hover { background: var(--jy-color-surface-alt); }
.jy-ui .slotpick-slot.is-chosen { background: var(--sp-accent); color: #fff; }
.jy-ui .slotpick-empty { color: var(--jy-color-text-muted); font-size: .9rem; }

/* ─── Calendar grid (month/week view) ───────────────────────── */
/* High-contrast, Gmail/Proton-style surface: the grid is a rounded panel
   whose 1px lines come from a gap over a border-coloured backdrop (no double
   borders), chips are solid colour with a darker left handle, and past chips
   invert to grey with the colour kept on the handle. */
.jy-ui .joinery-calgrid { font-family: inherit; --cg-border: var(--jy-color-border-strong, #c8ccd4); --cg-accent: #2563eb; }
.jy-ui .calgrid-toolbar { display: flex; align-items: center; gap: .5rem; margin-bottom: .75rem; flex-wrap: wrap; }
.jy-ui .calgrid-toolbar button { background: var(--jy-color-bg); border: 1px solid var(--cg-border); border-radius: 6px; padding: .35rem .7rem; cursor: pointer; font: inherit; font-weight: 500; color: var(--jy-color-text); }
.jy-ui .calgrid-toolbar button:hover { background: var(--jy-color-surface-alt); }
.jy-ui .calgrid-toolbar button.is-active { background: var(--cg-accent); color: #fff; border-color: var(--cg-accent); }
.jy-ui .calgrid-title { font-weight: 600; font-size: 1.2rem; margin: 0 .5rem; }
.jy-ui .calgrid-views { margin-left: auto; }
.jy-ui .calgrid-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--cg-border); border: 1px solid var(--cg-border); border-radius: 8px; overflow: hidden; }
.jy-ui .calgrid-dow { text-align: center; font-size: .6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--jy-color-text-muted); padding: .4rem 0; background: var(--jy-color-surface); }
.jy-ui .calgrid-cell { min-height: 100px; padding: .3rem; vertical-align: top; background: var(--jy-color-bg); }
.jy-ui .calgrid-cell.is-other { background: var(--jy-color-surface); }
.jy-ui .calgrid-cell.is-other .calgrid-daynum { color: var(--jy-color-text-subtle); }
.jy-ui .calgrid-daynum { font-size: .8125rem; font-weight: 500; display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; margin-bottom: .2rem; border-radius: 50%; }
.jy-ui .calgrid-cell.is-today .calgrid-daynum { background: var(--cg-accent); color: #fff; font-weight: 600; }
.jy-ui .calgrid-chip { --chip-color: #2563eb; display: block; width: 100%; box-sizing: border-box; text-align: left; font-family: inherit; font-size: .78rem; font-weight: 500; line-height: 1.35; padding: .15rem .4rem .15rem .45rem; margin-bottom: .2rem; border: 0; border-left: 3px solid rgba(0, 0, 0, .28); border-left-color: color-mix(in srgb, var(--chip-color) 60%, #000); border-radius: 4px; background: var(--chip-color); color: #fff; cursor: pointer; text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jy-ui .calgrid-chip:hover { filter: brightness(.92); }
.jy-ui .calgrid-chip .calgrid-chip-time { font-weight: 400; opacity: .85; margin-right: .3em; }
/* A past item goes quiet — grey chip, muted text — but keeps its colour as
   the left handle, so the calendar reads past/future at a glance. */
.jy-ui .calgrid-chip.is-past { background: var(--jy-color-surface-alt); color: var(--jy-color-text-muted); border-left-color: var(--chip-color); }
.jy-ui .calgrid-chip.is-past:hover { filter: none; background: var(--jy-color-surface); }
.jy-ui .calgrid-chip.is-past .calgrid-chip-time { opacity: .7; }
.jy-ui .calgrid-week-day { border: 1px solid var(--cg-border); border-bottom: none; padding: .5rem .6rem; display: flex; gap: .8rem; background: var(--jy-color-bg); }
.jy-ui .calgrid-week-day:first-of-type { border-radius: 8px 8px 0 0; }
.jy-ui .calgrid-week-day:last-of-type { border-bottom: 1px solid var(--cg-border); border-radius: 0 0 8px 8px; }
.jy-ui .calgrid-week-date { min-width: 6rem; font-size: .9375rem; font-weight: 500; color: var(--jy-color-text-muted); }
.jy-ui .calgrid-week-events { flex: 1; }
.jy-ui .calgrid-empty { color: var(--jy-color-text-subtle); font-size: .875rem; }

/* ─── Personal calendar page (/profile/calendar) ────────────── */
.jy-ui.cal-wrap { max-width: 980px; margin: 1rem auto; }
/* Inside an app page the calendar goes full width and the month grid
   stretches its week rows to fill the viewport (dow header row stays auto). */
.page-content--app .jy-ui.cal-wrap { max-width: none; margin: 0; flex: 1; display: flex; flex-direction: column; }
.page-content--app .jy-ui .joinery-calgrid { flex: 1; display: flex; flex-direction: column; }
/* calgrid-body must join the flex chain or the grid's flex: 1 is inert and
   the calendar stops short of the fold. */
.page-content--app .jy-ui .calgrid-body { flex: 1; display: flex; flex-direction: column; }
.page-content--app .jy-ui .calgrid-grid { flex: 1; grid-template-rows: auto; grid-auto-rows: minmax(78px, 1fr); }
.page-content--app .jy-ui .calgrid-cell { min-height: 78px; }
.page-content--app .jy-ui .calgrid-week-day { flex: 1 0 auto; }
.jy-ui .cal-note { background: var(--jy-color-success-bg, #e6f7ec); border: 1px solid var(--jy-color-success, #2d7d46); padding: .5rem .8rem; border-radius: var(--jy-radius-sm); margin-bottom: 1rem; }
.jy-ui .cal-note-detail { margin: .4rem 0 0; padding-left: 1.2rem; font-size: .9em; }
.jy-ui .cal-error { background: var(--jy-color-danger-bg); border: 1px solid var(--jy-color-danger); padding: .5rem .8rem; border-radius: var(--jy-radius-sm); margin-bottom: 1rem; }
.jy-ui .cal-full-form { border: 1px solid var(--jy-color-border); border-radius: var(--jy-radius-md); padding: 1rem 1.25rem; margin-top: 1.5rem; background: var(--jy-color-surface); }
.jy-ui .cal-full-form h2 { margin-top: 0; }
.jy-ui .cal-tz { color: var(--jy-color-text-muted); font-size: .9375rem; }
/* First-run import prompt — retires for good once the calendar has an entry. */
.jy-ui .cal-firstrun { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; border: 1px solid var(--jy-color-border); border-radius: var(--jy-radius-md); background: var(--jy-color-surface); padding: .75rem 1rem; }
.jy-ui .cal-firstrun strong { display: block; font-size: 1.05rem; }
.jy-ui .cal-firstrun span { font-size: .9375rem; color: var(--jy-color-text-muted); }
/* Import form renders through JoineryModal.open; only inner content styled here. */
.jy-ui .cal-import-form .form-group { margin-bottom: .6rem; }
.jy-ui .cal-recurrence-section { margin-top: .75rem; border-top: 1px solid var(--jy-color-border); padding-top: .75rem; }
.jy-ui .cal-rec-desc { font-size: .9375rem; color: var(--jy-color-text-muted); font-style: italic; margin-top: .25rem; min-height: 1.2em; }
.jy-ui .cal-rec-desc.is-static { font-style: normal; }
/* Scope choosers (edit/delete recurring) render through JoineryModal.open;
   only their inner content is styled here. */
.jy-ui .cal-scope-heading { margin: 0 0 1rem; font-size: 1.15rem; }
.jy-ui .cal-scope-options { display: flex; flex-direction: column; gap: .5rem; }
.jy-ui .cal-scope-options label { display: flex; align-items: center; gap: .6rem; font-size: 1.05rem; cursor: pointer; }
.jy-ui .cal-scope-options label small { color: var(--jy-color-text-muted); display: block; font-size: .875rem; }
.jy-ui.cal-popup { position: fixed; z-index: 9000; width: 340px; background: var(--jy-color-bg); border-radius: var(--jy-radius-lg); box-shadow: 0 8px 28px rgba(0, 0, 0, .18), 0 2px 8px rgba(0, 0, 0, .10); display: none; }
.jy-ui .cal-popup-header { display: flex; align-items: center; justify-content: space-between; padding: .6rem .8rem .4rem; border-bottom: 1px solid var(--jy-color-border); }
.jy-ui .cal-popup-title { font-weight: 600; font-size: 1rem; color: var(--jy-color-text-muted); }
.jy-ui .cal-popup-close { background: none; border: none; cursor: pointer; font-size: 1.3rem; color: var(--jy-color-text-subtle); padding: .1rem .3rem; border-radius: var(--jy-radius-sm); }
.jy-ui .cal-popup-close:hover { background: var(--jy-color-surface); color: var(--jy-color-text); }
.jy-ui .cal-popup-body { padding: .5rem .8rem; overflow-y: auto; max-height: calc(100vh - 190px); }
.jy-ui .cal-popup-body .form-group { margin-bottom: .6rem; }
.jy-ui .cal-popup-footer { display: flex; align-items: center; justify-content: space-between; padding: .6rem .8rem .8rem; border-top: 1px solid var(--jy-color-border); gap: .4rem; }
.jy-ui .cal-popup-more { background: none; border: none; cursor: pointer; color: var(--jy-color-text-muted); font: inherit; font-size: .9375rem; padding: .3rem .5rem; border-radius: var(--jy-radius-sm); text-decoration: none; }
.jy-ui .cal-popup-more:hover { background: var(--jy-color-surface); }
.jy-ui .cal-popup-right { display: flex; gap: .4rem; margin-left: auto; }
.jy-ui .cal-popup-delete { background: none; border: 1px solid var(--jy-color-danger); color: var(--jy-color-danger); border-radius: var(--jy-radius-sm); padding: .3rem .7rem; cursor: pointer; font: inherit; font-size: .9375rem; }
.jy-ui .cal-popup-delete:hover { background: var(--jy-color-danger-bg); }
.jy-ui .cal-popup-save { background: var(--jy-color-primary); color: var(--jy-color-primary-text); border: none; border-radius: var(--jy-radius-sm); padding: .3rem .9rem; cursor: pointer; font: inherit; font-size: .9375rem; font-weight: 600; }
.jy-ui .cal-popup-save:hover { background: var(--jy-color-primary-hover); }
.jy-ui .cal-popup-error { background: var(--jy-color-danger-bg); border: 1px solid var(--jy-color-danger); padding: .3rem .6rem; border-radius: var(--jy-radius-sm); font-size: .875rem; margin: 0 .8rem .4rem; display: none; }
.jy-ui .cal-pop-times.is-allday { display: none; }
.jy-ui .cal-pop-time-row { display: flex; gap: .6rem; }
.jy-ui .cal-pop-time-row .form-group { flex: 1; }
.jy-ui .cal-pop-time-input { width: 100%; box-sizing: border-box; }

/* ─── Pricing page (views/pricing.php) ─────────────────────────── */
.jy-ui .jy-pricing-grid { gap: 1.5rem; align-items: stretch; }
.jy-ui .jy-pricing-card { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); overflow: hidden; display: flex; flex-direction: column; position: relative; }
.jy-ui .jy-pricing-card.is-popular { border: 2px solid var(--jy-color-primary); box-shadow: 0 4px 20px rgba(0,0,0,.12); }
.jy-ui .jy-pricing-badge { background: var(--jy-color-primary); color: #fff; text-align: center; padding: .375rem; font-size: .8125rem; font-weight: 600; letter-spacing: .05em; }
.jy-ui .jy-pricing-head { padding: 2rem; text-align: center; border-bottom: 1px solid var(--jy-color-border); }
.jy-ui .jy-pricing-icon { width: 64px; height: 64px; background: rgba(26,188,156,.1); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 1.25rem; font-size: 1.75rem; }
.jy-ui .jy-pricing-name { font-size: 1.25rem; margin-bottom: 1rem; }
.jy-ui .jy-pricing-price { font-size: 1.75rem; font-weight: 700; color: var(--jy-color-primary); margin-bottom: .25rem; }
.jy-ui .jy-pricing-tier { color: var(--jy-color-text-muted); font-size: .875rem; margin: 0; }
.jy-ui .jy-pricing-body { padding: 1.5rem 2rem; flex: 1; display: flex; flex-direction: column; }
.jy-ui .jy-pricing-desc { color: var(--jy-color-text-muted); font-size: .9rem; text-align: center; margin-bottom: 1.25rem; }
.jy-ui .jy-pricing-spacer { flex: 1; margin-bottom: 1.5rem; }
.jy-ui .jy-pricing-cta { display: block; text-align: center; font-weight: 600; }
.jy-ui .jy-pricing-help { max-width: 640px; margin: 3rem auto 0; background: var(--jy-color-surface); border-radius: 8px; padding: 2.5rem; text-align: center; }
.jy-ui .jy-pricing-help-title { margin-bottom: .75rem; }
.jy-ui .jy-pricing-help-text { color: var(--jy-color-text-muted); margin-bottom: 1.5rem; }
.jy-ui .jy-pricing-help-actions { display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap; }
.jy-ui .jy-pricing-compare { margin-top: 3rem; }
.jy-ui .jy-pricing-compare-head { text-align: center; margin-bottom: 1.5rem; }
.jy-ui .jy-pricing-compare-sub { color: var(--jy-color-text-muted); }
.jy-ui .jy-pricing-table-wrap { overflow-x: auto; }
.jy-ui .jy-pricing-table { width: 100%; }
.jy-ui .jy-pricing-table th { text-align: center; }
.jy-ui .jy-pricing-table th:first-child { text-align: left; }
.jy-ui .jy-pricing-cell { text-align: center; }
.jy-ui .jy-pricing-yes { color: #198754; font-weight: 700; }
.jy-ui .jy-pricing-no { color: var(--jy-color-text-muted); }

/* ─── Auth pages (login, register, password reset, oauth_callback, totp, etc.) ─── */
.jy-ui .jy-form-actions { margin-top: var(--jy-space-4); }
.jy-ui .jy-auth-card-wide { max-width: 540px; }
.jy-ui .jy-auth-success-icon { margin-bottom: 1rem; }
.jy-ui .jy-auth-lead { margin-bottom: 1.5rem; }
.jy-ui .jy-auth-note { margin-bottom: 1.25rem; }
.jy-ui .jy-tight { margin: 0; }
.jy-ui .jy-auth-foot-spaced { margin-top: 1.25rem; }
.jy-ui .jy-auth-subhead { margin: .5rem 0 0; }
.jy-ui .jy-auth-hint { font-size: .9em; }

/* ─── Logout page (views/logout.php) ─── */
.jy-ui .jy-logout-logo { height: 100px; }
.jy-ui .jy-logout-card { max-width: 400px; }
.jy-ui .jy-logout-card-body { padding: 40px; }
.jy-ui .jy-logout-icon { font-size: 48px; color: #28a745; }

/* ─── Generic page helpers (reused across views) ─── */
.jy-ui .jy-narrow { max-width: 720px; margin: 0 auto; }
.jy-ui .jy-narrow-sm { max-width: 640px; margin: 0 auto; }

/* Settings hub: left rail of sections + content column (see
   PublicPageBase::settings_layout_start()). */
.jy-ui .jy-settings-shell { max-width: 1000px; margin: 0 auto; }
.jy-settings-layout { display: flex; gap: var(--jy-space-6); align-items: flex-start; }
.jy-settings-nav { flex: 0 0 200px; display: flex; flex-direction: column; gap: 2px; position: sticky; top: 76px; }
.jy-settings-nav-link {
  display: block;
  padding: .5rem .75rem;
  border-radius: 6px;
  color: var(--jy-color-text, #1f2937);
  text-decoration: none;
  font-size: .9375rem;
}
.jy-settings-nav-link:hover { background: var(--jy-color-bg-muted, #f3f4f6); }
.jy-settings-nav-link.active { background: var(--jy-color-bg-muted, #eef2f7); font-weight: 600; }
.jy-settings-content { flex: 1; min-width: 0; }
@media (max-width: 768px) {
  .jy-settings-layout { flex-direction: column; }
  .jy-settings-nav { position: static; flex-direction: row; flex-wrap: wrap; width: 100%; }
}
.jy-ui .jy-row-center { display: flex; gap: var(--jy-space-4); align-items: center; }

/* ─── Blog post (views/post.php) ─── */
.jy-ui .jy-post-wrap { padding: 2rem 1rem; }
.jy-ui .jy-radius-4 { border-radius: 4px; }

/* ─── Cart (views/cart.php) ─────────────────────────────────────── */
.jy-ui .jy-nowrap { white-space: nowrap; }
.jy-ui .jy-cart-section { padding: 2rem 0; }
.jy-ui .jy-cart-wrap { max-width: 820px; }
.jy-ui .jy-cart-title { font-size: 1.75rem; font-weight: 700; margin-bottom: 1.5rem; }
.jy-ui .jy-cart-empty { text-align: center; padding: 4rem 2rem; }
.jy-ui .jy-cart-empty-icon { font-size: 4rem; color: var(--jy-color-text-muted); margin-bottom: 1rem; }
.jy-ui .jy-cart-empty-title { margin-bottom: .5rem; }
.jy-ui .jy-cart-empty-text { color: var(--jy-color-text-muted); margin-bottom: 1.5rem; }
.jy-ui .jy-cart-items { display: flex; flex-direction: column; gap: 1rem; margin-bottom: 2rem; }
.jy-ui .jy-cart-card { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); padding: 1.5rem; }
.jy-ui .jy-cart-item-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; margin-bottom: 1rem; padding-bottom: .875rem; border-bottom: 1px solid var(--jy-color-border); }
.jy-ui .jy-cart-item-name { margin: 0 0 .125rem; font-size: 1.0625rem; font-weight: 700; }
.jy-ui .jy-cart-item-ver { font-size: .875rem; color: var(--jy-color-text-muted); }
.jy-ui .jy-cart-item-pricecol { text-align: right; flex-shrink: 0; }
.jy-ui .jy-cart-item-price { font-weight: 700; font-size: 1.0625rem; color: var(--jy-color-primary); }
.jy-ui .jy-cart-item-coupon { font-size: .8125rem; color: #198754; }
.jy-ui .jy-cart-meta { margin: 0 0 1rem; display: grid; grid-template-columns: max-content 1fr; gap: .375rem 1.25rem; font-size: .9375rem; }
.jy-ui .jy-cart-meta-dt { font-weight: 600; color: var(--jy-color-text-muted); white-space: nowrap; }
.jy-ui .jy-cart-item-actions { display: flex; gap: 1.25rem; font-size: .875rem; }
.jy-ui .jy-cart-action-edit { color: var(--jy-color-primary); text-decoration: none; font-weight: 600; }
.jy-ui .jy-cart-action-remove { color: var(--jy-color-danger); text-decoration: none; font-weight: 600; }
.jy-ui .jy-cart-coupon { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); padding: 1.25rem 1.5rem; margin-bottom: 1.5rem; }
.jy-ui .jy-cart-coupon-title { margin: 0 0 .875rem; font-size: 1rem; font-weight: 600; }
.jy-ui .jy-cart-coupon-tags { margin-bottom: .75rem; display: flex; flex-wrap: wrap; gap: .375rem; }
.jy-ui .jy-cart-coupon-tag { display: inline-flex; align-items: center; gap: .375rem; background: #198754; color: #fff; font-size: .875rem; font-weight: 600; padding: .3125rem .75rem; border-radius: 4px; }
.jy-ui .jy-cart-coupon-remove { color: rgba(255,255,255,.8); text-decoration: none; font-weight: 700; line-height: 1; font-size: 1rem; }
.jy-ui .jy-cart-coupon-error { color: var(--jy-color-danger); font-size: .875rem; margin-bottom: .5rem; }
.jy-ui .jy-cart-test-coupons { font-size: .8125rem; color: var(--jy-color-text-muted); margin-bottom: .625rem; }
.jy-ui .jy-cart-test-coupon-link { color: var(--jy-color-primary); margin-left: .375rem; }
.jy-ui .jy-cart-coupon-form { display: flex; gap: .5rem; align-items: flex-start; }
.jy-ui .jy-cart-coupon-input { flex: 1; padding: .5625rem .875rem; border: 1px solid var(--jy-color-border); border-radius: 6px; font-size: .9375rem; min-width: 0; }
.jy-ui .jy-cart-total { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); padding: 1.5rem; }
.jy-ui .jy-cart-totals { margin: 0 0 1.25rem; display: grid; grid-template-columns: 1fr auto; gap: .5rem 1rem; font-size: 1rem; }
.jy-ui .jy-cart-amt { margin: 0; text-align: right; }
.jy-ui .jy-cart-discount-label { color: #198754; }
.jy-ui .jy-cart-discount-amt { margin: 0; text-align: right; color: #198754; }
.jy-ui .jy-cart-total-label { font-weight: 700; font-size: 1.125rem; }
.jy-ui .jy-cart-total-amt { margin: 0; text-align: right; font-weight: 700; font-size: 1.125rem; color: var(--jy-color-primary); }
.jy-ui .jy-cart-totals .is-bordered { padding-top: .75rem; border-top: 2px solid var(--jy-color-border); }
.jy-ui .jy-cart-checkout-btn { display: block; width: 100%; text-align: center; padding: .875rem; font-size: 1.0625rem; font-weight: 700; }
.jy-ui .jy-cart-addmore { margin-top: 1rem; text-align: center; }
.jy-ui .jy-cart-addmore-link { font-size: .875rem; color: var(--jy-color-text-muted); text-decoration: none; }

/* ─── Generic reusable helpers (continued) ─── */
.jy-ui .jy-muted { color: var(--jy-color-text-muted); }
/* Inline counterpart to jy-callout-warning, for a line inside a table cell
   where a full callout block would break the row. */
.jy-ui .jy-warning { color: var(--jy-color-warning); font-size: var(--jy-text-sm); }
.jy-ui .jy-scroll-x { overflow-x: auto; }
.jy-ui .jy-w-full { width: 100%; }

/* ─── Cart confirmation (views/cart_confirm.php) ─────────────────── */
.jy-ui .jy-cc-wrap { max-width: 680px; margin: 0 auto; }
.jy-ui .jy-cc-hero { text-align: center; margin-bottom: 2.5rem; }
.jy-ui .jy-cc-icon-ok { font-size: 3.5rem; color: #198754; margin-bottom: 1rem; }
.jy-ui .jy-cc-icon-warn { font-size: 3.5rem; color: #ffc107; margin-bottom: 1rem; }
.jy-ui .jy-cc-icon-sm-ok { font-size: 2rem; color: #198754; margin-bottom: .5rem; }
.jy-ui .jy-cc-h1 { font-size: 1.75rem; margin-bottom: .5rem; }
.jy-ui .jy-cc-card { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); margin-bottom: 1.5rem; overflow: hidden; }
.jy-ui .jy-cc-head-primary { background: var(--jy-color-primary); color: #fff; padding: 1rem 1.5rem; }
.jy-ui .jy-cc-head-surface { background: var(--jy-color-surface); padding: 1rem 1.5rem; border-bottom: 1px solid var(--jy-color-border); }
.jy-ui .jy-cc-head-title { margin: 0; color: #fff; }
.jy-ui .jy-cc-table { width: 100%; margin: 0; }
.jy-ui .jy-cc-cell-l { padding: .875rem 1.5rem; text-align: left; }
.jy-ui .jy-cc-cell-r { padding: .875rem 1.5rem; text-align: right; }
.jy-ui .jy-cc-cell { padding: .875rem 1.5rem; }
.jy-ui .jy-cc-cell-price { padding: .875rem 1.5rem; text-align: right; font-weight: 600; }
.jy-ui .jy-cc-foot-row { background: var(--jy-color-surface); }
.jy-ui .jy-cc-cell-totlabel { padding: .875rem 1.5rem; font-weight: 700; }
.jy-ui .jy-cc-cell-tot { padding: .875rem 1.5rem; text-align: right; font-weight: 700; font-size: 1.125rem; color: var(--jy-color-primary); }
.jy-ui .jy-cc-after-msg { margin-top: .5rem; color: var(--jy-color-text); }
.jy-ui .jy-cc-body { padding: 1.5rem; }
.jy-ui .jy-cc-actions { margin-top: 1.25rem; }
.jy-ui .jy-cc-thanks { padding: 2rem; text-align: center; }
.jy-ui .jy-cc-panel { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); padding: 2rem; text-align: center; }
.jy-ui .jy-cc-panel-lg { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); padding: 2.5rem; text-align: center; }
.jy-ui .jy-cc-panel-title { margin-bottom: .75rem; }
.jy-ui .jy-cc-panel-text { color: var(--jy-color-text-muted); margin-bottom: 1.5rem; }
.jy-ui .jy-cc-actions-row { display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap; }
.jy-ui .jy-cc-alert { margin-bottom: 1.5rem; text-align: left; }

/* ─── 404 page (views/404.php) ─────────────────────────────────── */
.jy-ui .jy-e404-section { min-height: 75vh; display: flex; align-items: center; padding: 4rem 0; }
.jy-ui .jy-e404-grid { align-items: center; gap: 3rem; }
.jy-ui .jy-e404-visual { text-align: center; }
.jy-ui .jy-e404-num { font-size: 8rem; font-weight: 900; color: var(--jy-color-primary); opacity: .15; line-height: 1; }
.jy-ui .jy-e404-icon { margin-top: -2rem; font-size: 4rem; }
.jy-ui .jy-e404-brand { margin-bottom: 1.5rem; }
.jy-ui .jy-e404-logo { max-height: 40px; vertical-align: middle; margin-right: .75rem; }
.jy-ui .jy-e404-brandname { font-size: 1.25rem; font-weight: 700; color: var(--jy-color-primary); }
.jy-ui .jy-e404-h1 { margin-bottom: 1rem; }
.jy-ui .jy-e404-lead { font-size: 1.0625rem; color: var(--jy-color-text-muted); margin-bottom: 2rem; }
.jy-ui .jy-e404-search { margin-bottom: 2rem; }
.jy-ui .jy-e404-search-row { display: flex; gap: 0; }
.jy-ui .jy-e404-search-input { flex: 1; padding: .75rem 1rem; border: 1px solid var(--jy-color-border); border-right: none; border-radius: 4px 0 0 4px; font-size: 1rem; }
.jy-ui .jy-e404-search-btn { border-radius: 0 4px 4px 0; }
.jy-ui .jy-e404-btns { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 2rem; }
.jy-ui .jy-e404-links-title { margin-bottom: 1rem; }
.jy-ui .jy-e404-links-grid { gap: .5rem; }
.jy-ui .jy-e404-list { list-style: none; padding: 0; margin: 0; }
.jy-ui .jy-e404-li { margin-bottom: .5rem; }

/* ─── Location (views/location.php) ─────────────────────────────── */
.jy-ui .jy-loc-wrap { max-width: 860px; margin: 0 auto; }
.jy-ui .jy-loc-card { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); padding: 2rem; margin-bottom: 1.5rem; }
.jy-ui .jy-loc-desc-row { display: flex; gap: 1.5rem; align-items: flex-start; }
.jy-ui .jy-loc-desc-icon { font-size: 2.5rem; color: var(--jy-color-primary); flex-shrink: 0; }
.jy-ui .jy-loc-grow { flex: 1; }
.jy-ui .jy-loc-contact { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); overflow: hidden; }
.jy-ui .jy-loc-contact-head { background: var(--jy-color-primary); color: #fff; padding: 1rem 1.5rem; }
.jy-ui .jy-loc-contact-title { margin: 0; color: #fff; }
.jy-ui .jy-loc-contact-body { padding: 1.5rem; display: flex; flex-wrap: wrap; gap: 1.5rem; }
.jy-ui .jy-loc-item { flex: 1; min-width: 180px; display: flex; gap: .75rem; align-items: flex-start; }
.jy-ui .jy-loc-item-icon { font-size: 1.25rem; color: var(--jy-color-primary); flex-shrink: 0; margin-top: .125rem; }
.jy-ui .jy-loc-item-title { margin: 0 0 .25rem; }
.jy-ui .jy-loc-link { color: var(--jy-color-text-muted); text-decoration: none; }

/* ─── Video (views/video.php) ───────────────────────────────────── */
.jy-ui .jy-noshrink { flex-shrink: 0; }
.jy-ui .jy-video-wrap { max-width: 860px; margin: 0 auto; }
.jy-ui .jy-video-player { background: #000; border-radius: 8px; overflow: hidden; margin-bottom: 1.5rem; box-shadow: 0 2px 12px rgba(0,0,0,.2); }
.jy-ui .jy-video-ratio { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; }
.jy-ui .jy-video-frame { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
.jy-ui .jy-video-card { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); padding: 1.5rem; margin-bottom: 1.5rem; }
.jy-ui .jy-video-desc-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; }
.jy-ui .jy-video-grow { flex: 1; }
.jy-ui .jy-video-duration { display: inline-block; background: var(--jy-color-text-muted); color: #fff; font-size: .8125rem; padding: .25rem .75rem; border-radius: 4px; }
.jy-ui .jy-video-cols { display: flex; gap: 1.5rem; flex-wrap: wrap; align-items: flex-start; }
.jy-ui .jy-video-transcript { flex: 2; min-width: 240px; background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); overflow: hidden; }
.jy-ui .jy-video-tagscard { flex: 1; min-width: 180px; background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); overflow: hidden; }
.jy-ui .jy-video-cardhead { background: var(--jy-color-surface); padding: .875rem 1.25rem; border-bottom: 1px solid var(--jy-color-border); }
.jy-ui .jy-video-cardtitle { margin: 0; font-size: 1rem; }
.jy-ui .jy-video-cardtitle-sm { margin: 0; font-size: .9375rem; }
.jy-ui .jy-video-cardbody { padding: 1.25rem; }
.jy-ui .jy-video-tag { display: inline-block; background: var(--jy-color-primary); color: #fff; font-size: .8125rem; padding: .25rem .625rem; border-radius: 4px; margin: 0 .25rem .375rem 0; }

/* ─── Documentation (views/documentation.php) ─── */
.jy-ui .jy-docs-section { padding: 3rem 0; }

/* ─── Notifications (views/notifications.php) ────────────────────── */
.jy-ui .jy-narrow-lg { max-width: 860px; margin: 0 auto; }
.jy-ui .jy-notif-empty-icon { opacity: .3; }
.jy-ui .ntf-inbox-card { background: #fff; border-radius: .5rem; border: 1px solid #e3e6ed; overflow: hidden; }
.jy-ui .ntf-inbox-header { display: flex; justify-content: space-between; align-items: center; padding: .875rem 1.25rem; border-bottom: 1px solid #e3e6ed; background: #f9fafd; }
.jy-ui .ntf-inbox-title { display: flex; align-items: center; gap: .5rem; font-weight: 600; font-size: .9375rem; color: #344050; }
.jy-ui .ntf-inbox-count { background: var(--jy-color-primary); color: #fff; font-size: .75rem; font-weight: 600; padding: .125rem .5rem; border-radius: 999px; line-height: 1.4; }
.jy-ui .ntf-mark-all-btn { background: none; border: 1px solid #d8dbe0; border-radius: .25rem; padding: .3rem .75rem; font-size: .8125rem; color: #5e6e82; cursor: pointer; transition: all .15s; }
.jy-ui .ntf-mark-all-btn:hover { background: #f0f2f5; color: #344050; border-color: #c0c4cc; }
.jy-ui .ntf-inbox-empty { text-align: center; padding: 3rem 1rem; color: #9da9bb; }
.jy-ui .ntf-inbox-empty p { margin: .75rem 0 0; }
.jy-ui .ntf-row { display: flex; align-items: flex-start; padding: .75rem 1.25rem; border-bottom: 1px solid #f0f2f5; position: relative; transition: background .15s; }
.jy-ui .ntf-row:last-child { border-bottom: none; }
.jy-ui .ntf-row:hover { background: #f9fafd; }
.jy-ui .ntf-row-unread { background: #f0f7ff; }
.jy-ui .ntf-row-unread:hover { background: #e6f0fc; }
.jy-ui .ntf-row-unread .ntf-row-title { font-weight: 600; }
.jy-ui .ntf-unread-dot { position: absolute; left: .375rem; top: 50%; transform: translateY(-50%); width: 6px; height: 6px; border-radius: 50%; background: var(--jy-color-primary); }
.jy-ui .ntf-row-icon { flex-shrink: 0; width: 36px; height: 36px; border-radius: 50%; background: #edf2f9; display: flex; align-items: center; justify-content: center; margin-right: .875rem; color: #5e6e82; }
.jy-ui .ntf-row-unread .ntf-row-icon { background: #dbe8f9; color: var(--jy-color-primary); }
.jy-ui .ntf-row-content { flex: 1; min-width: 0; }
.jy-ui .ntf-row-link { text-decoration: none; color: inherit; }
.jy-ui .ntf-row-link:hover .ntf-row-title { color: var(--jy-color-primary); }
.jy-ui .ntf-row-title { display: block; font-size: .875rem; color: #344050; line-height: 1.4; }
.jy-ui .ntf-row-body { display: block; font-size: .8125rem; color: #748194; margin-top: .125rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jy-ui .ntf-row-meta { flex-shrink: 0; margin-left: 1rem; display: flex; flex-direction: column; align-items: flex-end; gap: .375rem; }
.jy-ui .ntf-row-time { font-size: .75rem; color: #9da9bb; white-space: nowrap; }
.jy-ui .ntf-row-mark-btn { background: none; border: 1px solid #d8dbe0; border-radius: 50%; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; cursor: pointer; color: #9da9bb; padding: 0; transition: all .15s; }
.jy-ui .ntf-row-mark-btn:hover { background: #e8f4e8; border-color: #6bc16b; color: #3a8a3a; }
.jy-ui .ntf-inbox-pager { display: flex; justify-content: center; align-items: center; gap: 1rem; padding: .875rem 1.25rem; border-top: 1px solid #e3e6ed; background: #f9fafd; font-size: .8125rem; color: #748194; }
.jy-ui .ntf-inbox-pager a { color: var(--jy-color-primary); text-decoration: none; font-weight: 500; }
.jy-ui .ntf-inbox-pager a:hover { text-decoration: underline; }

/* ─── Conversations inbox (views/profile/conversations.php) ──────── */
.jy-ui .jy-faded { opacity: .3; }
.jy-ui .msg-inbox-card { background: #fff; border-radius: .5rem; border: 1px solid #e3e6ed; overflow: hidden; }
.jy-ui .msg-inbox-header { display: flex; justify-content: space-between; align-items: center; padding: .875rem 1.25rem; border-bottom: 1px solid #e3e6ed; background: #f9fafd; }
.jy-ui .msg-inbox-title { display: flex; align-items: center; gap: .5rem; font-weight: 600; font-size: .9375rem; color: #344050; }
.jy-ui .msg-compose-btn { display: inline-flex; align-items: center; gap: .375rem; background: var(--jy-color-primary); color: #fff; border: none; border-radius: .25rem; padding: .3rem .75rem; font-size: .8125rem; font-weight: 500; text-decoration: none; cursor: pointer; transition: opacity .15s; }
.jy-ui .msg-compose-btn:hover { opacity: .85; color: #fff; }
.jy-ui .msg-compose-btn.is-hidden { display: none; }
.jy-ui .msg-inbox-empty { text-align: center; padding: 3rem 1rem; color: #9da9bb; }
.jy-ui .msg-inbox-empty p { margin: .75rem 0 0; }
.jy-ui .msg-row { display: flex; align-items: center; padding: .875rem 1.25rem; border-bottom: 1px solid #f0f2f5; text-decoration: none; color: inherit; position: relative; transition: background .15s; }
.jy-ui .msg-row:last-child { border-bottom: none; }
.jy-ui .msg-row:hover { background: #f9fafd; }
.jy-ui .msg-row-unread { background: #f0f7ff; }
.jy-ui .msg-row-unread:hover { background: #e6f0fc; }
.jy-ui .msg-row-unread .msg-row-name { font-weight: 700; }
.jy-ui .msg-row-unread .msg-row-preview { color: #4a5568; }
.jy-ui .msg-row-muted { opacity: .6; }
.jy-ui .msg-unread-dot { position: absolute; left: .375rem; top: 50%; transform: translateY(-50%); width: 6px; height: 6px; border-radius: 50%; background: var(--jy-color-primary); }
.jy-ui .msg-row-avatar { flex-shrink: 0; margin-right: .875rem; }
.jy-ui .msg-row-content { flex: 1; min-width: 0; }
.jy-ui .msg-row-name { display: block; font-weight: 600; font-size: .875rem; color: #344050; line-height: 1.4; }
.jy-ui .msg-row-preview { display: block; font-size: .8125rem; color: #748194; margin-top: .125rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jy-ui .msg-row-meta { flex-shrink: 0; margin-left: 1rem; display: flex; flex-direction: column; align-items: flex-end; gap: .25rem; }
.jy-ui .msg-row-time { font-size: .75rem; color: #9da9bb; white-space: nowrap; }
.jy-ui .msg-inbox-pager { display: flex; justify-content: center; align-items: center; gap: 1rem; padding: .875rem 1.25rem; border-top: 1px solid #e3e6ed; background: #f9fafd; font-size: .8125rem; color: #748194; }
.jy-ui .msg-inbox-pager a { color: var(--jy-color-primary); text-decoration: none; font-weight: 500; }
.jy-ui .msg-inbox-pager a:hover { text-decoration: underline; }

/* ─── Public booking (views/book.php) ───────────────────────────── */
.jy-ui.jy-book-wrap { max-width: 820px; margin: 1.5rem auto; }
.jy-ui .jy-book-meta { color: #555; }
.jy-ui .jy-book-errors { background: #fdecea; border: 1px solid #c0392b; padding: .6rem .9rem; border-radius: 4px; margin: 1rem 0; }
.jy-ui .jy-book-sectionhead { margin-top: 1.5rem; }

/* ─── Booking (disabled notice) (views/booking.php) ─────────────── */
.jy-ui .jy-booking-panel { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); padding: 2.5rem; text-align: center; }
.jy-ui .jy-booking-icon { font-size: 3rem; color: #f6c23e; margin-bottom: 1rem; }
.jy-ui .jy-booking-title { margin-bottom: 1rem; }
.jy-ui .jy-booking-alert { margin-bottom: 1.5rem; text-align: left; }
.jy-ui .jy-booking-text { color: var(--jy-color-text-muted); margin-bottom: 2rem; }
.jy-ui .jy-booking-actions { display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap; }

/* ─── Booking manage (views/booking_manage.php) ─────────────────── */
.jy-ui.jy-bookmgr-wrap { max-width: 760px; margin: 1.5rem auto; }
.jy-ui .jy-bookmgr-meta { color: #555; }
.jy-ui .jy-bookmgr-notice { background: #fdecea; border: 1px solid #c0392b; padding: .6rem .9rem; border-radius: 4px; }
.jy-ui .jy-bookmgr-notice.is-spaced { margin: 1rem 0; }
.jy-ui .jy-bookmgr-notice-ok { background: #e6f7ec; border: 1px solid #2d7d46; padding: .6rem .9rem; border-radius: 4px; }
.jy-ui .jy-bookmgr-policy { color: #666; font-size: .9rem; }
.jy-ui .jy-bookmgr-warn { color: #a15c00; }
.jy-ui .jy-bookmgr-h2 { margin-top: 2rem; }

/* ─── Orders history (views/profile/orders.php) ─────────────────── */
.jy-ui .jy-orders-row { padding: var(--jy-space-3) 0; display: flex; justify-content: space-between; align-items: center; gap: var(--jy-space-4); flex-wrap: wrap; }
.jy-ui .jy-orders-row.is-divided { border-top: 1px solid var(--jy-color-border); }
.jy-ui .jy-orders-num { margin: 0; font-weight: 600; }

/* ─── Events history (views/profile/events.php) ─────────────────── */
.jy-ui .jy-pevents-row { padding: var(--jy-space-3) 0; display: flex; justify-content: space-between; align-items: flex-start; gap: var(--jy-space-4); flex-wrap: wrap; }
.jy-ui .jy-pevents-row.is-divided { border-top: 1px solid var(--jy-color-border); }
.jy-ui .jy-pevents-main { flex: 1; min-width: 0; }
.jy-ui .jy-pevents-name { margin: 0 0 var(--jy-space-1); }
.jy-ui .jy-pevents-badges { flex-shrink: 0; display: flex; align-items: center; gap: var(--jy-space-2); }

/* ─── Change tier (views/profile/change-tier.php) ───────────────── */
.jy-ui .jy-tier-reactivate { margin-bottom: var(--jy-space-5); text-align: center; }
.jy-ui .jy-tier-cards { display: flex; gap: var(--jy-space-5); flex-wrap: wrap; justify-content: center; margin-bottom: var(--jy-space-6); }
.jy-ui .jy-tier-card { flex: 1; min-width: 240px; max-width: 340px; }
.jy-ui .jy-tier-card.is-current { box-shadow: 0 0 0 3px var(--jy-color-primary), var(--jy-shadow-md); }
.jy-ui .jy-tier-card.is-current .card-header { background: var(--jy-color-primary); color: #fff; }
.jy-ui .jy-tier-name { margin: 0; }
.jy-ui .jy-tier-card.is-current .jy-tier-name { color: #fff; }
.jy-ui .jy-tier-current-label { margin: var(--jy-space-1) 0 0; font-size: var(--jy-text-sm); color: rgba(255,255,255,.85); }
.jy-ui .jy-tier-sub { margin: var(--jy-space-1) 0 0; }
.jy-ui .jy-tier-section { margin-bottom: var(--jy-space-5); }
.jy-ui .jy-tier-product { border-top: 1px solid var(--jy-color-border); padding-top: var(--jy-space-3); margin-top: var(--jy-space-3); }
.jy-ui .jy-tier-product-name { margin: 0 0 var(--jy-space-1); font-weight: 600; }
.jy-ui .jy-tier-price { margin: 0; font-size: var(--jy-text-2xl); font-weight: 700; }
.jy-ui .jy-tier-period { font-weight: 400; }
.jy-ui .jy-tier-msg { margin-bottom: var(--jy-space-3); }

/* ─── Generic spacing/display helpers (continued) ─── */
.jy-ui .jy-mt-2 { margin-top: var(--jy-space-2); }
.jy-ui .jy-mt-4 { margin-top: var(--jy-space-4); }
.jy-ui .jy-inline { display: inline; }

/* ─── Security settings (views/profile/security.php) ────────────── */
.jy-ui .jy-security-codes { background: #f5f5f5; padding: 1em; border-radius: 4px; font-size: 1.1em; }
.jy-ui .jy-security-secret { background: #f5f5f5; padding: 1em; border-radius: 4px; word-break: break-all; white-space: pre-wrap; }
.jy-ui .jy-security-note { margin-top: var(--jy-space-4); font-size: .9em; color: #666; }
.jy-ui .jy-security-qr { text-align: center; margin: var(--jy-space-4) 0; }
.jy-ui .jy-security-qr-img { max-width: 240px; }

/* ─── Subscriptions (views/profile/subscriptions.php) ───────────── */
.jy-ui .jy-mt-5 { margin-top: var(--jy-space-5); }
.jy-ui .jy-subs-summary { display: flex; justify-content: space-between; align-items: center; gap: var(--jy-space-4); flex-wrap: wrap; }
.jy-ui .jy-subs-name { margin: 0 0 var(--jy-space-1); }
.jy-ui .jy-subs-cancel { color: var(--jy-color-danger); }
.jy-ui .jy-subs-row { border-bottom: 1px solid var(--jy-color-border); padding: var(--jy-space-4) 0; display: flex; justify-content: space-between; align-items: center; gap: var(--jy-space-4); }
.jy-ui .jy-subs-amt { margin: 0; font-weight: 600; }
.jy-ui .jy-subs-links { margin-top: var(--jy-space-5); padding-top: var(--jy-space-4); border-top: 1px solid var(--jy-color-border); display: flex; gap: var(--jy-space-5); flex-wrap: wrap; }
.jy-ui .jy-subs-orderrow { border-bottom: 1px solid var(--jy-color-border); padding: var(--jy-space-3) 0; display: flex; justify-content: space-between; align-items: center; gap: var(--jy-space-4); }

/* ─── Generic helpers (continued) ─── */
.jy-ui .jy-mb-2 { margin-bottom: var(--jy-space-2); }
.jy-ui .jy-mb-5 { margin-bottom: var(--jy-space-5); }
.jy-ui .jy-white { color: #fff; }
.jy-ui .jy-cardhead-primary { background: var(--jy-color-primary); color: #fff; }

/* ─── Course session viewer (views/profile/event_sessions_course.php) ─── */
.jy-ui .jy-esc-layout { display: flex; gap: var(--jy-space-6); align-items: flex-start; flex-wrap: wrap; }
.jy-ui .jy-esc-main { flex: 2; min-width: 0; }
.jy-ui .jy-esc-time { margin: 0 0 var(--jy-space-4); }
.jy-ui .jy-esc-img { max-width: 100%; border-radius: var(--jy-radius-sm); }
.jy-ui .jy-esc-materials-h { text-transform: uppercase; letter-spacing: .05em; margin-bottom: var(--jy-space-2); }
.jy-ui .jy-esc-filelist { margin: 0; padding-left: var(--jy-space-5); }
.jy-ui .jy-esc-next { margin-top: var(--jy-space-5); padding-top: var(--jy-space-5); border-top: 1px solid var(--jy-color-border); text-align: right; }
.jy-ui .jy-esc-sidebar { flex: 1; min-width: 220px; max-width: 280px; }
.jy-ui .jy-esc-navlink.is-active { font-weight: 600; color: var(--jy-color-primary); }

/* ─── Generic helper (continued) ─── */
.jy-ui .jy-mt-3 { margin-top: var(--jy-space-3); }

/* ─── Event sessions (views/profile/event_sessions.php) ─────────── */
.jy-ui .jy-esess-layout { display: flex; gap: var(--jy-space-6); align-items: flex-start; flex-wrap: wrap; }
.jy-ui .jy-esess-main { flex: 2; min-width: 0; }
.jy-ui .jy-esess-loc-title { margin: 0 0 var(--jy-space-3); }
.jy-ui .jy-esess-mb2 { margin: 0 0 var(--jy-space-2); }
.jy-ui .jy-esess-mb3 { margin: 0 0 var(--jy-space-3); }
.jy-ui .jy-esess-loc-img { max-width: 100%; border-radius: var(--jy-radius-sm); margin-bottom: var(--jy-space-3); }
.jy-ui .jy-esess-session { border-bottom: 1px solid var(--jy-color-border); padding: var(--jy-space-5); }
.jy-ui .jy-esess-session-title { margin: 0 0 var(--jy-space-1); color: var(--jy-color-primary); }
.jy-ui .jy-esess-session-time { margin: 0 0 var(--jy-space-4); }
.jy-ui .jy-esess-materials-h { text-transform: uppercase; letter-spacing: .05em; margin-bottom: var(--jy-space-2); }
.jy-ui .jy-esess-filelist { margin: 0; padding-left: var(--jy-space-5); }
.jy-ui .jy-esess-pager { padding: var(--jy-space-4) var(--jy-space-5); text-align: center; }
.jy-ui .jy-esess-sidebar { flex: 1; min-width: 240px; max-width: 300px; }

/* ─── Generic helper (continued) ─── */
.jy-ui .jy-mb-4 { margin-bottom: var(--jy-space-4); }

/* ─── Billing (views/profile/billing.php) ───────────────────────── */
.jy-ui .jy-billing-row { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--jy-space-4); }
.jy-ui .jy-billing-flex { display: flex; align-items: center; gap: var(--jy-space-3); }
.jy-ui .jy-billing-cardbrand { font-weight: 700; letter-spacing: .05em; }
.jy-ui .jy-billing-bold { font-weight: 600; }
.jy-ui .jy-billing-paypal { font-weight: 700; }
.jy-ui .jy-billing-cycle-opt { display: flex; justify-content: space-between; align-items: center; padding: var(--jy-space-3) var(--jy-space-4); background: var(--jy-color-surface); border-radius: var(--jy-radius-md); margin-bottom: var(--jy-space-2); }
.jy-ui .jy-billing-savings { color: var(--jy-color-success); font-weight: 600; margin-left: var(--jy-space-2); }
.jy-ui .jy-billing-amt { text-align: right; font-weight: 600; }
.jy-ui .jy-billing-empty { padding: var(--jy-space-8); text-align: center; }
.jy-ui .jy-billing-empty-icon { font-size: 2.5rem; color: var(--jy-color-text-muted); margin-bottom: var(--jy-space-4); }
.jy-ui .jy-billing-nav { margin-top: var(--jy-space-4); display: flex; gap: var(--jy-space-4); flex-wrap: wrap; }

/* ─── Events listing (views/events.php) ─────────────────────────── */
.jy-ui .jy-events-ics-row { text-align: right; margin-bottom: 1rem; }
.jy-ui .jy-events-ics-link { color: var(--jy-color-text-muted); font-size: .875rem; }
.jy-ui .mobile-category-select { display: none; }
.jy-ui .jy-events-mobile-select { margin-bottom: 1.5rem; }
.jy-ui .jy-events-placeholder { height: 250px; background: var(--jy-color-surface); display: flex; align-items: center; justify-content: center; font-size: 4rem; color: var(--jy-color-border); }
@media (max-width: 576px) {
  .jy-ui .mobile-category-select { display: block !important; }
  .jy-ui .grid-filter-wrap { display: none; }
}

/* ─── Product detail (views/product.php) ────────────────────────── */
.jy-ui .jy-product-layout { display: flex; gap: 3rem; align-items: flex-start; flex-wrap: wrap; }
.jy-ui .jy-product-left { flex: 1; min-width: 280px; }
.jy-ui .jy-product-right { flex: 1; min-width: 320px; }
.jy-ui .jy-product-imgwrap { margin-bottom: 1.5rem; text-align: center; }
.jy-ui .jy-product-img { width: 100%; max-width: 400px; height: 300px; background: linear-gradient(135deg, #f0f4f8 0%, #dde3ea 100%); border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 5rem; color: #b0bac4; margin: 0 auto; box-shadow: 0 2px 8px rgba(0,0,0,.08); }
.jy-ui .jy-product-sale-wrap { margin-top: .75rem; }
.jy-ui .jy-product-sale { display: inline-block; background: #dc3545; color: #fff; font-size: .8125rem; font-weight: 700; padding: .25rem .75rem; border-radius: 4px; letter-spacing: .05em; }
.jy-ui .jy-product-block { margin-bottom: 1.5rem; }
.jy-ui .jy-product-alert { margin-bottom: 1rem; }
.jy-ui .jy-product-price { font-size: 1.75rem; font-weight: 700; color: var(--jy-color-primary); margin-bottom: 1.25rem; }
.jy-ui .jy-product-desc { color: var(--jy-color-text-muted); line-height: 1.6; }
.jy-ui .jy-product-submit { margin-top: 1.5rem; }
.jy-ui .jy-product-addbtn { width: 100%; padding: .75rem; font-size: 1.0625rem; }
.jy-ui .jy-product-backwrap { padding-top: 1rem; margin-top: 1rem; border-top: 1px solid var(--jy-color-border); }
.jy-ui .jy-product-back { color: var(--jy-color-text-muted); text-decoration: none; font-size: .9375rem; }

/* ─── Generic helper (continued) ─── */
.jy-ui .jy-fs-sm { font-size: .875rem; }

/* ─── Event detail (views/event.php) ────────────────────────────── */
.jy-ui .jy-event-datetime { font-size: 1.0625rem; color: var(--jy-color-text-muted); }
.jy-ui .jy-event-img { width: 100%; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,.1); }
.jy-ui .jy-event-loc-img { width: 100%; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); }
.jy-ui .jy-event-regnote { color: var(--jy-color-text-muted); font-size: .875rem; margin-top: 1rem; margin-bottom: 0; }
.jy-ui .jy-event-past-h { margin-top: 1.5rem; margin-bottom: 1rem; }
.jy-ui .jy-event-sesslink-p { margin-top: 1rem; margin-bottom: 0; }
.jy-ui .jy-event-sesslink { color: var(--jy-color-primary); }

/* ─── Generic helper (continued) ─── */
.jy-ui .jy-grow { flex: 1; }

/* ─── Products listing (views/products.php) ─────────────────────── */
.jy-ui .jy-products-grid { gap: 1.5rem; }
.jy-ui .jy-products-card { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,.1); overflow: hidden; display: flex; flex-direction: column; transition: transform .2s, box-shadow .2s; }
.jy-ui .jy-products-imglink { display: block; overflow: hidden; text-decoration: none; }
.jy-ui .jy-products-img { width: 100%; height: 220px; background: linear-gradient(135deg, #f0f4f8 0%, #dde3ea 100%); display: flex; align-items: center; justify-content: center; font-size: 3rem; color: #b0bac4; transition: transform .3s; }
.jy-ui .jy-products-body { padding: 1.25rem; flex: 1; display: flex; flex-direction: column; }
.jy-ui .jy-products-name { font-size: 1.0625rem; margin: 0 0 .5rem; }
.jy-ui .jy-products-namelink { color: var(--jy-color-text); text-decoration: none; }
.jy-ui .jy-products-desc { color: var(--jy-color-text-muted); font-size: .875rem; margin: 0 0 1rem; flex: 1; }
.jy-ui .jy-products-pager { margin-top: 3rem; display: flex; justify-content: space-between; align-items: center; background: var(--jy-color-surface); border-radius: 8px; padding: 1.25rem 1.5rem; }
.jy-ui .jy-products-pager-info { margin: 0; color: var(--jy-color-text-muted); font-size: .9rem; }
.jy-ui .product-card:hover { transform: translateY(-4px); box-shadow: 0 8px 24px rgba(0,0,0,.12) !important; }
.jy-ui .product-card:hover img { transform: scale(1.04); }

/* ─── Single conversation (views/profile/conversation.php) ──────── */
.jy-ui .conversation-page { display: flex; flex-direction: column; min-height: 400px; }
.jy-ui .conversation-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; }
.jy-ui .jy-convo-back-wrap { display: flex; align-items: center; gap: .75rem; }
.jy-ui .jy-convo-back { text-decoration: none; color: inherit; font-size: 1.2rem; }
.jy-ui .conversation-more-menu { position: relative; }
.jy-ui .jy-convo-summary { cursor: pointer; }
.jy-ui .conversation-dropdown { position: absolute; right: 0; top: 100%; background: #fff; border: 1px solid #ddd; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,.1); z-index: 10; min-width: 160px; margin-top: 4px; }
.jy-ui .conversation-action-btn { display: block; width: 100%; text-align: left; padding: .5rem 1rem; border: none; background: none; cursor: pointer; }
.jy-ui .conversation-action-btn:hover { background: #f5f5f5; }
.jy-ui .jy-convo-delete { color: #c00; }
.jy-ui .conversation-messages { display: flex; flex-direction: column; gap: .75rem; padding: 1rem 0; flex: 1; }
.jy-ui .jy-convo-loadmore { text-align: center; padding: .5rem; }
.jy-ui .jy-convo-placeholder { text-align: center; color: #888; padding: 2rem 0; }
.jy-ui .message-bubble { max-width: 70%; padding: .75rem 1rem; border-radius: 1rem; word-wrap: break-word; }
.jy-ui .message-bubble.message-mine { align-self: flex-end; background: var(--jy-color-primary); color: #fff; border-bottom-right-radius: .25rem; }
.jy-ui .message-bubble.message-theirs { align-self: flex-start; background: #f0f0f0; color: #333; border-bottom-left-radius: .25rem; }
.jy-ui .message-sender { font-size: .8rem; font-weight: 600; margin-bottom: .25rem; }
.jy-ui .message-body { line-height: 1.4; }
.jy-ui .message-time { font-size: .75rem; opacity: .7; margin-top: .25rem; }
.jy-ui .message-bubble.message-mine .message-time { text-align: right; }
.jy-ui .conversation-compose { display: flex; gap: .5rem; padding: 1rem 0; border-top: 1px solid #eee; align-items: flex-end; }
.jy-ui .conversation-compose textarea { flex: 1; resize: none; min-height: 44px; max-height: 120px; padding: .5rem .75rem; border: 1px solid #ccc; border-radius: .5rem; font-family: inherit; font-size: .95rem; }
.jy-ui .conversation-compose textarea:focus { outline: none; border-color: var(--jy-color-primary); }

/* ─── Home / install welcome (views/index.php) ──────────────────── */
.jy-ui .jy-home-hero { padding: 5rem 0; text-align: center; }
.jy-ui .jy-home-h1 { font-size: 2.5rem; font-weight: 700; margin-bottom: 1.5rem; }
.jy-ui .jy-home-lead { font-size: 1.125rem; color: var(--jy-color-text-muted); margin-bottom: 2rem; max-width: 600px; margin-left: auto; margin-right: auto; }
.jy-ui .jy-home-cta { display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap; padding: .25rem; }
.jy-ui .jy-home-btn { font-size: 1.0625rem; padding: .75rem 2rem; }
.jy-ui .jy-home-section { padding: 4rem 0; }
.jy-ui .jy-home-sectionhead { text-align: center; margin-bottom: 3rem; }
.jy-ui .jy-home-grid { gap: 1.5rem; }
.jy-ui .jy-home-feature { background: #fff; border: 1px solid var(--jy-color-border); border-radius: 8px; padding: 2rem; text-align: center; }
.jy-ui .jy-home-feature-title { margin-top: 0; margin-bottom: .75rem; }
.jy-ui .jy-home-gs-grid { gap: 3rem; align-items: start; }
.jy-ui .jy-home-gs-lead { color: var(--jy-color-text-muted); margin-bottom: 2rem; }
.jy-ui .jy-home-step { display: flex; gap: 1rem; margin-bottom: 1.5rem; align-items: flex-start; }
.jy-ui .jy-home-step-num { flex-shrink: 0; width: 32px; height: 32px; background: var(--jy-color-primary); color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: .875rem; }
.jy-ui .jy-home-step-desc { margin: .25rem 0 0; color: var(--jy-color-text-muted); font-size: .9rem; }
.jy-ui .jy-home-admin-card { background: #fff; border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,.1); }
.jy-ui .jy-home-admin-head { background: #212529; color: #fff; padding: 1rem 1.5rem; font-weight: 600; border-radius: 8px 8px 0 0; }
.jy-ui .jy-home-admin-body { padding: 1.5rem; }
.jy-ui .jy-home-creds { background: var(--jy-color-surface); border-radius: 4px; padding: 1rem; margin-bottom: 1rem; }
.jy-ui .jy-home-cred-row { display: flex; margin-bottom: .5rem; }
.jy-ui .jy-home-cred-label { width: 90px; color: var(--jy-color-text-muted); }
.jy-ui .jy-home-alert { margin-bottom: 1rem; }
.jy-ui .jy-home-cta-section { padding: 4rem 0; text-align: center; }
.jy-ui .jy-home-cta-title { color: #fff; margin-bottom: 1rem; }
.jy-ui .jy-home-cta-text { color: rgba(255,255,255,.8); margin-bottom: 2rem; }
.jy-ui .jy-home-cta-btn { background: #fff; color: var(--jy-color-text); font-size: 1.0625rem; padding: .75rem 2.5rem; }

/* ─── Blog listing (views/blog.php) ─────────────────────────────── */
.jy-ui .jy-blog-noresult { background: #fff; border-radius: 8px; padding: 3rem; text-align: center; box-shadow: 0 1px 4px rgba(0,0,0,.1); margin-bottom: 2rem; }
.jy-ui .jy-blog-noresult-h { margin-bottom: 1rem; }
.jy-ui .jy-blog-entry { display: flex; gap: 1.5rem; padding-bottom: 2.5rem; margin-bottom: 2.5rem; border-bottom: 1px solid var(--jy-color-border); }
.jy-ui .jy-blog-thumb { flex-shrink: 0; width: 200px; }
.jy-ui .jy-blog-thumblink { text-decoration: none; }
.jy-ui .jy-blog-thumbimg { width: 200px; height: 150px; border-radius: 6px; background: linear-gradient(135deg, #f0f4f8 0%, #dde3ea 100%); display: flex; align-items: center; justify-content: center; font-size: 2.5rem; color: #b0bac4; }
.jy-ui .jy-blog-body { flex: 1; min-width: 0; }
.jy-ui .jy-blog-title { font-size: 1.375rem; margin-bottom: .5rem; }
.jy-ui .jy-blog-titlelink { color: var(--jy-color-text); text-decoration: none; }
.jy-ui .jy-blog-meta { display: flex; flex-wrap: wrap; gap: 1rem; font-size: .875rem; color: var(--jy-color-text-muted); margin-bottom: .75rem; }
.jy-ui .jy-blog-excerpt { color: var(--jy-color-text-muted); margin-bottom: .75rem; }
.jy-ui .jy-blog-memberbadge { display: inline-block; padding: .125rem .5rem; background: #f0f0f0; border-radius: 4px; font-size: .75rem; color: #888; margin-bottom: .5rem; }
.jy-ui .jy-blog-readmore { color: var(--jy-color-primary); font-weight: 600; text-decoration: none; }
.jy-ui .jy-blog-pagination { margin-top: 2rem; }
.jy-ui .jy-blog-widget { margin-bottom: 2rem; }
.jy-ui .tabs-nav { display: flex; border-bottom: 2px solid var(--jy-color-border); margin-bottom: 1rem; }
.jy-ui .tab-link { padding: .5rem 1rem; border: none; background: none; cursor: pointer; color: var(--jy-color-text-muted); }
.jy-ui .tab-link.active { font-weight: 600; color: var(--jy-color-primary); border-bottom: 2px solid var(--jy-color-primary); margin-bottom: -2px; }
.jy-ui .tab-content { display: none; }
.jy-ui .tab-content.active { display: block; }
.jy-ui .jy-blog-sidepost { display: flex; gap: .75rem; margin-bottom: 1rem; padding-bottom: 1rem; border-bottom: 1px solid var(--jy-color-border); }
.jy-ui .jy-blog-sideicon-pinned { flex-shrink: 0; width: 60px; height: 60px; border-radius: 50%; background: var(--jy-color-primary); display: flex; align-items: center; justify-content: center; font-size: 1.25rem; color: #fff; }
.jy-ui .jy-blog-sideicon-recent { flex-shrink: 0; width: 60px; height: 60px; border-radius: 50%; background: var(--jy-color-surface); display: flex; align-items: center; justify-content: center; font-size: 1.25rem; color: #adb5bd; }
.jy-ui .jy-blog-sidetitle { font-size: .9375rem; margin: 0 0 .25rem; }
.jy-ui .jy-blog-emptynote { color: var(--jy-color-text-muted); font-size: .875rem; }
.jy-ui .jy-blog-tagstitle { font-size: 1.125rem; font-weight: 600; margin-bottom: 1rem; }
.jy-ui .jy-blog-tag { display: inline-block; padding: .25rem .75rem; margin: 0 .25rem .5rem 0; background: var(--jy-color-surface); color: var(--jy-color-text); text-decoration: none; border-radius: 3px; font-size: .875rem; }

/* ─── Generic helpers (continued) ─── */
.jy-ui .jy-mt-1 { margin-top: var(--jy-space-1); }
.jy-ui .jy-fw-600 { font-weight: 600; }
.jy-ui .jy-flex1min { flex: 1; min-width: 0; }

/* ─── Member dashboard (views/profile/profile.php) ──────────────── */
.jy-ui .jy-profile-actions { display: flex; align-items: center; gap: var(--jy-space-5); flex-wrap: wrap; }
.jy-ui .jy-profile-actions-body { display: flex; align-items: center; gap: var(--jy-space-5); flex-wrap: wrap; flex: 1; }
.jy-ui .jy-profile-actionlink { text-decoration: none; color: inherit; white-space: nowrap; }
.jy-ui .jy-profile-statcard { text-decoration: none; color: inherit; }
.jy-ui .jy-profile-statbody { text-align: center; padding: var(--jy-space-4); }
.jy-ui .jy-profile-statnum { font-size: var(--jy-text-2xl); font-weight: 700; color: var(--jy-color-primary); }
.jy-ui .jy-profile-statnum.is-alert { color: var(--jy-color-danger); }
.jy-ui .jy-profile-statnum.is-warn { color: var(--jy-color-warning); }
.jy-ui .jy-profile-cols { display: flex; gap: var(--jy-space-5); flex-wrap: wrap; }
.jy-ui .jy-profile-main { flex: 2; min-width: 280px; }
.jy-ui .jy-profile-aside { flex: 1; min-width: 240px; }
.jy-ui .jy-profile-evrow { padding: 0 0 var(--jy-space-3); display: flex; justify-content: space-between; align-items: flex-start; gap: var(--jy-space-4); flex-wrap: wrap; }
.jy-ui .jy-profile-evrow.is-divided { border-top: 1px solid var(--jy-color-border); padding-top: var(--jy-space-3); }
.jy-ui .jy-profile-feedrow { padding: 0 0 var(--jy-space-3); display: flex; align-items: flex-start; gap: var(--jy-space-3); }
.jy-ui .jy-profile-feedrow.is-divided { border-top: 1px solid var(--jy-color-border); padding-top: var(--jy-space-3); }
.jy-ui .jy-profile-feedrow.is-unread { border-left: 3px solid var(--jy-color-primary); padding-left: var(--jy-space-3); margin-left: calc(-1 * var(--jy-space-3)); }
.jy-ui .jy-profile-feedicon { flex-shrink: 0; margin-top: var(--jy-space-1); }
.jy-ui .jy-profile-feedtitle { font-weight: 400; }
.jy-ui .jy-profile-feedtitle.is-unread { font-weight: 600; }
.jy-ui .jy-profile-feedpreview { margin-top: var(--jy-space-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jy-ui .jy-profile-feedtime { flex-shrink: 0; white-space: nowrap; }
.jy-ui .jy-profile-convhead { display: flex; justify-content: space-between; align-items: baseline; }
.jy-ui .jy-profile-convtime { white-space: nowrap; margin-left: var(--jy-space-2); }
.jy-ui .jy-profile-orderrow { padding: 0 0 var(--jy-space-3); display: flex; justify-content: space-between; align-items: center; gap: var(--jy-space-4); }
.jy-ui .jy-profile-orderrow.is-divided { border-top: 1px solid var(--jy-color-border); padding-top: var(--jy-space-3); }
.jy-ui .jy-profile-amt { margin: 0; font-weight: 600; }
.jy-ui .jy-profile-userbody { text-align: center; padding: var(--jy-space-5); }
.jy-ui .jy-profile-avatar { width: 72px; height: 72px; border-radius: var(--jy-radius-full); background: var(--jy-color-primary); color: #fff; display: flex; align-items: center; justify-content: center; font-size: var(--jy-text-2xl); margin: 0 auto var(--jy-space-4); overflow: hidden; }
.jy-ui .jy-profile-avatarimg { width: 100%; height: 100%; object-fit: cover; }
.jy-ui .jy-profile-username { margin: 0 0 var(--jy-space-1); }
.jy-ui .jy-profile-usermeta { margin: 0 0 var(--jy-space-1); }
.jy-ui .jy-profile-useraddr { margin: 0 0 var(--jy-space-4); }
.jy-ui .jy-profile-subrow { display: flex; justify-content: space-between; align-items: center; padding: var(--jy-space-1) 0; }
.jy-ui .jy-profile-managelink { display: block; margin-top: var(--jy-space-2); }

/* ============================================================
   checkout — full purchase flow (accordion, summary, modal)
   State-driven: section-header / section-badge / section-body
   styling keys off .checkout-section[data-state]; JS only sets
   data-state, never inline styles.
   ============================================================ */
.jy-ui .jy-checkout-testbar { background: #fff3cd; color: #856404; padding: 0.5rem 1rem; text-align: center; font-size: 0.875rem; border-bottom: 1px solid #ffc107; }
.jy-ui .jy-checkout-wrap { padding: 2rem 0; }

.jy-ui .jy-checkout-msg { padding: 1rem 1.5rem; border-radius: 8px; margin-bottom: 1.5rem; display: flex; align-items: flex-start; gap: 0.75rem; }
.jy-ui .jy-checkout-msg.is-error { background: #f8d7da; color: #721c24; }
.jy-ui .jy-checkout-msg.is-info { background: #d1ecf1; color: #0c5460; }
.jy-ui .jy-checkout-msg-icon { font-size: 1.25rem; line-height: 1; flex-shrink: 0; }
.jy-ui .jy-checkout-flash { background: #d4edda; color: #155724; padding: 0.875rem 1.25rem; border-radius: 8px; margin-bottom: 1.5rem; border: 1px solid #c3e6cb; }

.jy-ui .jy-checkout-empty { max-width: 500px; margin: 3rem auto; text-align: center; }
.jy-ui .jy-checkout-empty-icon { font-size: 4rem; color: var(--jy-color-text-muted); margin-bottom: 1rem; }
.jy-ui .jy-checkout-empty-h { margin-bottom: 0.5rem; }
.jy-ui .jy-checkout-empty-p { color: var(--jy-color-text-muted); margin-bottom: 1.5rem; }

.jy-ui .jy-checkout-progress { margin-bottom: 1.5rem; }
.jy-ui .jy-checkout-progress-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem; }
.jy-ui .jy-checkout-step-label { font-size: 0.875rem; color: var(--jy-color-text-muted); }
.jy-ui .jy-checkout-track { height: 4px; background: #e9ecef; border-radius: 2px; overflow: hidden; }
.jy-ui .jy-checkout-bar { height: 100%; background: var(--jy-color-primary); border-radius: 2px; transition: width 0.3s; width: var(--jy-checkout-progress, 0%); }

.jy-ui .jy-checkout-layout { display: flex; gap: 2rem; align-items: flex-start; flex-wrap: wrap; }
.jy-ui .jy-checkout-accordion { flex: 1; min-width: 320px; }

/* mobile order summary — hidden on desktop, shown under 768px */
.jy-ui .jy-checkout-mobilesummary { display: none; margin-bottom: 1rem; }
.jy-ui .jy-checkout-mobilecard { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,0.1); padding: 0.875rem 1.25rem; cursor: pointer; }
.jy-ui .jy-checkout-mobilerow { display: flex; justify-content: space-between; align-items: center; }
.jy-ui .jy-checkout-mobile-price { display: flex; align-items: center; gap: 0.5rem; }
.jy-ui .jy-checkout-mobile-total { color: var(--jy-color-primary); }
.jy-ui .jy-checkout-chevron { display: inline-block; transition: transform 0.2s; font-size: 0.75rem; }
.jy-ui .jy-checkout-mobiledetail { display: none; margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--jy-color-border); }
.jy-ui .jy-checkout-mobilecard.is-open .jy-checkout-mobiledetail { display: block; }
.jy-ui .jy-checkout-mobilecard.is-open .jy-checkout-chevron { transform: rotate(180deg); }
.jy-ui .jy-checkout-mobile-itemrow { display: flex; justify-content: space-between; margin-bottom: 0.5rem; font-size: 0.9375rem; }

.jy-ui .jy-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; }
.jy-ui .checkout-section:focus-within .section-header { outline: 2px solid var(--jy-color-primary); outline-offset: -2px; }

/* accordion section shell + state-driven header/badge/body */
.jy-ui .checkout-section { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,0.1); margin-bottom: 1rem; overflow: hidden; border: none; padding: 0; }
.jy-ui .checkout-section .section-header { padding: 1rem 1.5rem; display: flex; justify-content: space-between; align-items: center; cursor: pointer; }
.jy-ui .checkout-section[data-state="active"]    .section-header { background: var(--jy-color-primary); color: #fff; cursor: pointer; }
.jy-ui .checkout-section[data-state="completed"] .section-header { background: var(--jy-color-surface); border-bottom: 1px solid var(--jy-color-border); cursor: pointer; }
.jy-ui .checkout-section[data-state="pending"]   .section-header { background: #f5f5f5; color: #aaa; cursor: default; }
.jy-ui .jy-checkout-headleft { display: flex; align-items: center; gap: 0.75rem; }
.jy-ui .section-badge { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; font-weight: 700; font-size: 0.875rem; }
.jy-ui .checkout-section[data-state="active"]    .section-badge { background: rgba(255,255,255,0.2); color: #fff; }
.jy-ui .checkout-section[data-state="completed"] .section-badge { background: #198754; color: #fff; }
.jy-ui .checkout-section[data-state="pending"]   .section-badge { background: #ddd; color: #999; }
.jy-ui .jy-checkout-sectitle { font-size: 1.0625rem; }
.jy-ui .section-summary { display: flex; align-items: center; gap: 1rem; }
.jy-ui .jy-checkout-sumtext { font-size: 0.875rem; color: var(--jy-color-text-muted); }
.jy-ui .jy-checkout-sumedit { font-size: 0.8125rem; color: var(--jy-color-primary); font-weight: 600; }
.jy-ui .checkout-section .section-body { padding: 1.5rem; display: none; }
.jy-ui .checkout-section[data-state="active"] .section-body { display: block; }

/* billing section */
.jy-ui .jy-checkout-userbox { display: flex; align-items: center; justify-content: space-between; padding: 0.875rem 1rem; background: var(--jy-color-surface); border-radius: 6px; margin-bottom: 1rem; }
.jy-ui .jy-checkout-username { font-weight: 600; }
.jy-ui .jy-checkout-useremail { color: var(--jy-color-text-muted); font-size: 0.9375rem; }
.jy-ui .jy-checkout-notyou { font-size: 0.8125rem; color: var(--jy-color-text-muted); text-decoration: none; }
.jy-ui .jy-checkout-signedin { background: var(--jy-color-surface); padding: 0.875rem 1rem; border-radius: 6px; margin-bottom: 1rem; font-size: 0.9375rem; color: var(--jy-color-text-muted); }
.jy-ui .jy-checkout-namegrid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; }
.jy-ui .jy-checkout-field { margin-bottom: 1rem; }
.jy-ui .jy-checkout-label { display: block; font-weight: 600; margin-bottom: 0.25rem; font-size: 0.9375rem; }
.jy-ui .jy-checkout-req { color: var(--jy-color-danger); }
.jy-ui .jy-checkout-input { width: 100%; padding: 0.625rem 0.875rem; border: 1px solid var(--jy-color-border); border-radius: 6px; font-size: 1rem; }
.jy-ui .jy-checkout-emailexists { background: #e8f4fd; padding: 0.75rem 1rem; border-radius: 6px; margin-top: 0.75rem; font-size: 0.9375rem; }
.jy-ui .jy-checkout-errors { color: var(--jy-color-danger); font-size: 0.875rem; margin-bottom: 0.75rem; }
.jy-ui .jy-checkout-actions { margin-top: 1.25rem; }
.jy-ui .jy-checkout-consent { font-size: 0.8125rem; color: var(--jy-color-text-muted); text-align: center; margin: 0.75rem 0 0; }

/* payment section */
.jy-ui .jy-checkout-pay-stripe { margin-bottom: 1.5rem; }
.jy-ui .jy-checkout-payhead { margin-bottom: 1rem; }
.jy-ui .jy-checkout-pay-paypal.is-divided { border-top: 1px solid var(--jy-color-border); padding-top: 1.5rem; margin-top: 1.5rem; }
.jy-ui .jy-checkout-paypal-unavail { border-top: 1px solid var(--jy-color-border); padding-top: 1.5rem; margin-top: 1.5rem; color: var(--jy-color-text-muted); font-size: 0.875rem; }
.jy-ui .jy-checkout-secure { margin-top: 1.5rem; text-align: center; color: var(--jy-color-text-muted); font-size: 0.8125rem; }
.jy-ui .jy-checkout-secure-icon { vertical-align: -2px; }

/* order summary (right column) */
.jy-ui .jy-checkout-summary-col { flex: 0 0 340px; min-width: 260px; position: sticky; top: 2rem; }
.jy-ui .jy-checkout-summary-card { background: #fff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,0.1); overflow: hidden; }
.jy-ui .jy-checkout-summary-head { background: var(--jy-color-primary); color: #fff; padding: 1rem 1.5rem; }
.jy-ui .jy-checkout-summary-title { margin: 0; color: #fff; font-size: 1.0625rem; }
.jy-ui .jy-checkout-lineitem { padding: 1rem 1.5rem; border-bottom: 1px solid var(--jy-color-border); }
.jy-ui .jy-checkout-lineitem-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; }
.jy-ui .jy-checkout-lineitem-name { margin: 0 0 0.25rem; font-size: 0.9375rem; }
.jy-ui .jy-checkout-lineitem-pricewrap { text-align: right; flex-shrink: 0; }
.jy-ui .jy-checkout-price { font-weight: 700; color: var(--jy-color-primary); }
.jy-ui .jy-checkout-discount { font-size: 0.8125rem; color: #198754; }
.jy-ui .jy-checkout-itemactions { margin-top: 0.5rem; display: flex; gap: 1rem; font-size: 0.8125rem; }
.jy-ui .jy-checkout-link { color: var(--jy-color-primary); text-decoration: none; }
.jy-ui .jy-checkout-link-danger { color: var(--jy-color-danger); text-decoration: none; }
.jy-ui .jy-checkout-link-muted { color: var(--jy-color-text-muted); text-decoration: none; }
.jy-ui .jy-checkout-coupon { padding: 1rem 1.5rem; border-bottom: 1px solid var(--jy-color-border); }
.jy-ui .jy-checkout-coupon-chips { margin-bottom: 0.5rem; }
.jy-ui .jy-checkout-chip { display: inline-flex; align-items: center; gap: 0.25rem; background: #198754; color: #fff; font-size: 0.8125rem; padding: 0.25rem 0.625rem; border-radius: 4px; margin: 0 0.25rem 0.25rem 0; }
.jy-ui .jy-checkout-chip-x { color: #fff; text-decoration: none; font-weight: 700; line-height: 1; }
.jy-ui .jy-checkout-coupon-test { font-size: 0.8125rem; color: var(--jy-color-text-muted); margin-bottom: 0.5rem; }
.jy-ui .jy-checkout-coupon-testlink { color: var(--jy-color-primary); margin-left: 0.25rem; }
.jy-ui .jy-checkout-coupon-row { display: flex; gap: 0.5rem; }
.jy-ui .jy-checkout-coupon-input { flex: 1; padding: 0.5rem 0.75rem; border: 1px solid var(--jy-color-border); border-radius: 6px; font-size: 0.9375rem; }
.jy-ui .jy-checkout-coupon-apply { font-size: 0.9375rem; padding: 0.5rem 0.875rem; }
.jy-ui .jy-checkout-coupon-error { color: var(--jy-color-danger); font-size: 0.8125rem; margin-top: 0.375rem; }
.jy-ui .jy-checkout-totals { background: var(--jy-color-surface); padding: 1rem 1.5rem; }
.jy-ui .jy-checkout-totals-dl { margin: 0; display: grid; grid-template-columns: 1fr auto; gap: 0.375rem 1rem; }
.jy-ui .jy-checkout-totals-dl dd { margin: 0; text-align: right; }
.jy-ui .jy-checkout-subtotal-dt { font-weight: 400; }
.jy-ui .jy-checkout-discount-dt, .jy-ui .jy-checkout-discount-dd { color: #198754; }
.jy-ui .jy-checkout-total-dt { font-weight: 700; font-size: 1.0625rem; }
.jy-ui .jy-checkout-total-dd { font-weight: 700; font-size: 1.0625rem; color: var(--jy-color-primary); }
.jy-ui .jy-checkout-total-dt.is-bordered, .jy-ui .jy-checkout-total-dd.is-bordered { padding-top: 0.75rem; border-top: 1px solid var(--jy-color-border); }
.jy-ui .jy-checkout-addmore { padding: 1rem 1.5rem; text-align: center; }

/* login modal */
.jy-ui .jy-checkout-modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 9999; align-items: center; justify-content: center; }
.jy-ui .jy-checkout-modal-box { background: #fff; border-radius: 12px; padding: 2rem; max-width: 400px; width: 90%; position: relative; box-shadow: 0 8px 32px rgba(0,0,0,0.2); }
.jy-ui .jy-checkout-modal-close { position: absolute; top: 0.75rem; right: 1rem; background: none; border: none; font-size: 1.5rem; cursor: pointer; color: var(--jy-color-text-muted); }
.jy-ui .jy-checkout-modal-title { margin: 0 0 1.5rem; }
.jy-ui .jy-checkout-modal-error { color: var(--jy-color-danger); font-size: 0.875rem; margin-bottom: 1rem; }
.jy-ui .jy-checkout-modal-field { margin-bottom: 1rem; }
.jy-ui .jy-checkout-modal-field.is-last { margin-bottom: 1.5rem; }
.jy-ui .jy-checkout-modal-label { display: block; font-weight: 600; margin-bottom: 0.25rem; }
.jy-ui .jy-checkout-modal-foot { margin-top: 1rem; text-align: center; }
.jy-ui .jy-checkout-modal-forgot { font-size: 0.875rem; color: var(--jy-color-text-muted); }

@media (max-width: 768px) {
    .jy-ui .jy-checkout-mobilesummary { display: block; }
    .jy-ui .jy-checkout-summary-col { display: none; }
}

/* ============================================
   Copy field (PublicPageBase::copy_field)
   Unscoped: appears in admin fix tables and
   anywhere a value is carried to another system.
   ============================================ */
.jy-copyfield { display: flex; gap: 0.25rem; align-items: center; }
.jy-copyfield input[readonly] { flex: 1; min-width: 10rem; cursor: text; background: #fff; }
.jy-copyfield button { white-space: nowrap; }

/* ============================================
   Box variants (begin_box 'variant' option)
   Unscoped: boxes are chrome, not kit components,
   and these are how a page says what a panel IS.

   Left alone, every box on a page looks the same:
   one header bar, one body, edge to edge. A panel
   that belongs to the one above it and a panel
   that is the task at hand both read as just the
   next section. Two shapes fix that.

     .jy-box-nested — belongs to its container.
       Indented, tinted, and tied to the panel
       above by a spine down its left edge.

     .jy-box-focus  — the task at hand. Lifted
       onto its own surface inside a recessed
       stage: a modal that stayed in the flow of
       the page, so what surrounds it is still
       readable and reachable.

   Both header shapes are matched (.card-header
   from the admin theme, .content-box-header from
   the base one) so a variant looks the same
   wherever it is used.
   ============================================ */

/* --- nested: a child panel --- */
.jy-box-nested {
    margin: 1.25rem 0 1.5rem 1rem;
    border: 1px solid var(--jy-color-border);
    border-left: 3px solid var(--jy-color-primary);
    border-radius: 0 var(--jy-radius, 0.375rem) var(--jy-radius, 0.375rem) 0;
    background: var(--jy-color-surface);
    overflow: hidden;
}
.jy-box-nested > .card-header,
.jy-box-nested > .content-box-header {
    padding: 0.5rem 1rem;
    background: transparent;
    border-bottom: 1px solid var(--jy-color-border);
}
/* Smaller and quieter than its parent's title: a child panel that shouts as
   loud as the panel containing it is the problem this variant exists to fix. */
.jy-box-nested > .card-header h5,
.jy-box-nested > .card-header h6,
.jy-box-nested > .content-box-header h6 {
    margin: 0;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--jy-color-text-muted);
}
.jy-box-nested > .card-body,
.jy-box-nested > .content-box-body { padding: 1rem; }
.jy-box-nested > .card-body > :last-child,
.jy-box-nested > .content-box-body > :last-child { margin-bottom: 0; }

/* --- focus: the almost-modal --- */
/* The stage is the cutout. A recessed well in the page — inset shadow, no
   border — reads as a hole rather than another card, which is what stops the
   panel inside it being mistaken for one more section. */
.jy-box-stage {
    margin: 1.5rem 0;
    padding: 1.5rem;
    border-radius: 0.75rem;
    background: var(--jy-box-stage-bg, rgba(20, 32, 48, 0.09));
    box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.09);
}
.jy-box-focus {
    background: var(--jy-color-bg);
    border: 1px solid var(--jy-color-border);
    border-radius: var(--jy-radius-lg, 0.5rem);
    /* Two shadows: a broad soft one for the height off the stage, a tight one
       under the edge so the panel keeps its shape against a light background. */
    box-shadow: 0 0.75rem 2rem rgba(0, 0, 0, 0.18), 0 0.125rem 0.25rem rgba(0, 0, 0, 0.08);
    overflow: hidden;
}
/* A modal's title bar is part of the panel, not a band across it. */
.jy-box-focus > .card-header,
.jy-box-focus > .content-box-header {
    padding: 1rem 1.5rem 0.75rem;
    background: var(--jy-color-bg);
    border-bottom: 1px solid var(--jy-color-border);
}
.jy-box-focus > .card-header h5,
.jy-box-focus > .card-header h6,
.jy-box-focus > .content-box-header h6 {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--jy-color-text);
}
.jy-box-focus > .card-body,
.jy-box-focus > .content-box-body { padding: 1.25rem 1.5rem 1.5rem; }
.jy-box-focus > .card-body > :last-child,
.jy-box-focus > .content-box-body > :last-child { margin-bottom: 0; }

/* A nested panel inside a focus panel sits on the panel's own surface, so it
   tints the other way — otherwise it would be invisible against it. */
.jy-box-focus .jy-box-nested { background: var(--jy-color-surface-alt); }

@media (max-width: 600px) {
    /* Horizontal inset is the first thing to go on a narrow screen: elevation
       and the tinted stage still separate the panel, and the content needs the
       width more than the margin needs to prove containment. */
    .jy-box-stage { padding: 0.75rem; border-radius: 0.5rem; }
    .jy-box-nested { margin-left: 0; }
    .jy-box-focus > .card-header,
    .jy-box-focus > .content-box-header { padding: 0.875rem 1rem 0.625rem; }
    .jy-box-focus > .card-body,
    .jy-box-focus > .content-box-body { padding: 1rem; }
}

/* ─── Chat kit (.jy-chat-*) ──────────────────────────────────
   The shared look of a conversation: bubbles, the composer, the
   small furniture around them (system chips, reactions, typing).
   Consumed by the Messages app and by the AI chat, so the two
   read as one family. Layout — how a surface arranges a list
   beside a thread — is each surface's own business and is not
   here.
   ─────────────────────────────────────────────────────────── */

.jy-chat-log {
    display: flex;
    flex-direction: column;
    gap: var(--jy-space-1);
    padding: var(--jy-space-4);
    overflow-y: auto;
    overscroll-behavior: contain;
}
/* A short conversation sits at the bottom of the pane, where the composer is,
   rather than floating at the top of an empty column. An auto top margin on
   the first item does that without justify-content: flex-end, which makes the
   overflowing top of a long thread unreachable. */
.jy-chat-log > :first-child { margin-top: auto; }

/* One turn: the bubble plus whatever hangs off it. Mine sits right. The face
   lines up with the top of the turn, not the bottom — below the bubble sit the
   reactions and the timestamp, and an avatar level with those reads as
   belonging to them rather than to the message. */
.jy-chat-row {
    display: flex;
    align-items: flex-start;
    gap: var(--jy-space-2);
    max-width: 100%;
}
.jy-chat-row + .jy-chat-row { margin-top: var(--jy-space-2); }
.jy-chat-row--mine { flex-direction: row-reverse; }

.jy-chat-avatar {
    width: 28px;
    height: 28px;
    border-radius: var(--jy-radius-full);
    object-fit: cover;
    flex: 0 0 28px;
    background: var(--jy-color-surface-alt);
}
/* Consecutive messages from the same person indent instead of repeating a face. */
.jy-chat-avatar--spacer { visibility: hidden; }

.jy-chat-stack {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    max-width: min(72ch, 78%);
}
.jy-chat-row--mine .jy-chat-stack { align-items: flex-end; }

.jy-chat-sender {
    font-size: var(--jy-text-xs);
    font-weight: 600;
    color: var(--jy-color-text-muted);
    padding: 0 var(--jy-space-2);
}

.jy-chat-bubble {
    position: relative;
    padding: var(--jy-space-2) var(--jy-space-3);
    border-radius: var(--jy-radius-lg);
    background: var(--jy-color-surface-alt);
    color: var(--jy-color-text);
    line-height: var(--jy-leading-base);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}
.jy-chat-row--mine .jy-chat-bubble {
    background: var(--jy-color-primary);
    color: var(--jy-color-primary-text);
}
.jy-chat-bubble--deleted {
    background: transparent;
    border: 1px dashed var(--jy-color-border-strong);
    color: var(--jy-color-text-subtle);
    font-style: italic;
}
.jy-chat-row--mine .jy-chat-bubble--deleted {
    background: transparent;
    color: var(--jy-color-text-subtle);
}

/* A quoted parent, sitting inside the bubble above the reply. */
.jy-chat-quote {
    display: block;
    border-left: 3px solid currentColor;
    opacity: 0.75;
    padding: 2px var(--jy-space-2);
    margin-bottom: var(--jy-space-1);
    font-size: var(--jy-text-sm);
    cursor: pointer;
    background: none;
    border-top: 0; border-right: 0; border-bottom: 0;
    text-align: left;
    color: inherit;
    width: 100%;
}
.jy-chat-quote-sender { font-weight: 600; display: block; }
.jy-chat-quote-body { display: block; opacity: 0.85; }

.jy-chat-meta {
    display: flex;
    align-items: center;
    gap: var(--jy-space-1);
    font-size: var(--jy-text-xs);
    color: var(--jy-color-text-subtle);
    padding: 0 var(--jy-space-2);
}

/* "Alice added Bob" — a centred note, not a bubble. */
.jy-chat-system {
    align-self: center;
    max-width: 80%;
    margin: var(--jy-space-3) auto;
    padding: var(--jy-space-1) var(--jy-space-3);
    border-radius: var(--jy-radius-full);
    background: var(--jy-color-surface-alt);
    color: var(--jy-color-text-muted);
    font-size: var(--jy-text-xs);
    text-align: center;
}

.jy-chat-reactions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--jy-space-1);
    padding: 0 var(--jy-space-2);
}
.jy-chat-reaction {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px var(--jy-space-2);
    border-radius: var(--jy-radius-full);
    border: 1px solid var(--jy-color-border);
    background: var(--jy-color-bg);
    color: var(--jy-color-text-muted);
    font-size: var(--jy-text-xs);
    line-height: 1.6;
    cursor: pointer;
}
.jy-chat-reaction--mine {
    border-color: var(--jy-color-primary);
    color: var(--jy-color-primary);
    background: var(--jy-color-info-bg);
}

/* Attachments: pictures render, everything else is a chip. */
.jy-chat-media {
    display: block;
    max-width: 320px;
    max-height: 320px;
    border-radius: var(--jy-radius-md);
    margin-top: var(--jy-space-1);
}
.jy-chat-file {
    display: inline-flex;
    align-items: center;
    gap: var(--jy-space-2);
    margin-top: var(--jy-space-1);
    padding: var(--jy-space-2) var(--jy-space-3);
    border-radius: var(--jy-radius-md);
    border: 1px solid var(--jy-color-border);
    background: var(--jy-color-bg);
    color: var(--jy-color-link);
    font-size: var(--jy-text-sm);
    text-decoration: none;
}
.jy-chat-file-size { color: var(--jy-color-text-subtle); }

.jy-chat-typing {
    display: flex;
    align-items: center;
    gap: var(--jy-space-2);
    min-height: 20px;
    padding: 0 var(--jy-space-4) var(--jy-space-1);
    font-size: var(--jy-text-xs);
    color: var(--jy-color-text-muted);
}
.jy-chat-typing-dots { display: inline-flex; gap: 3px; }
.jy-chat-typing-dots i {
    width: 5px; height: 5px;
    border-radius: var(--jy-radius-full);
    background: currentColor;
    animation: jy-chat-typing-bounce 1.2s infinite ease-in-out;
}
.jy-chat-typing-dots i:nth-child(2) { animation-delay: 0.15s; }
.jy-chat-typing-dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes jy-chat-typing-bounce {
    0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
    30%           { opacity: 1;   transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
    .jy-chat-typing-dots i { animation: none; opacity: 0.6; }
}

/* The composer: a growing textarea with its controls on the same line. */
.jy-chat-composer {
    display: flex;
    align-items: flex-end;
    gap: var(--jy-space-2);
    padding: var(--jy-space-3) var(--jy-space-4);
    border-top: 1px solid var(--jy-color-border);
    background: var(--jy-color-bg);
}
.jy-chat-composer textarea {
    flex: 1 1 auto;
    resize: none;
    min-height: var(--jy-control-h-md);
    max-height: 160px;
    padding: var(--jy-space-2) var(--jy-space-3);
    border: 1px solid var(--jy-color-border-strong);
    border-radius: var(--jy-radius-lg);
    font: inherit;
    line-height: var(--jy-leading-base);
    color: var(--jy-color-text);
    background: var(--jy-color-bg);
}
.jy-chat-composer-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--jy-control-h-md);
    height: var(--jy-control-h-md);
    border-radius: var(--jy-radius-full);
    border: 1px solid var(--jy-color-border-strong);
    background: var(--jy-color-bg);
    color: var(--jy-color-text-muted);
    cursor: pointer;
}
.jy-chat-composer-btn--send {
    background: var(--jy-color-primary);
    border-color: var(--jy-color-primary);
    color: var(--jy-color-primary-text);
}
.jy-chat-composer-btn[disabled] { opacity: 0.5; cursor: default; }

/* What the composer is about to send, above the text box. */
.jy-chat-tray {
    display: flex;
    flex-wrap: wrap;
    gap: var(--jy-space-2);
    padding: var(--jy-space-2) var(--jy-space-4) 0;
}
.jy-chat-tray:empty { display: none; }
.jy-chat-tray-item {
    display: inline-flex;
    align-items: center;
    gap: var(--jy-space-2);
    padding: var(--jy-space-1) var(--jy-space-2);
    border: 1px solid var(--jy-color-border);
    border-radius: var(--jy-radius-md);
    background: var(--jy-color-surface);
    font-size: var(--jy-text-sm);
}
.jy-chat-tray-item img {
    width: 32px; height: 32px;
    object-fit: cover;
    border-radius: var(--jy-radius-sm);
}
