/* ================================================================
 * Shelly Hub — public site stylesheet
 *   shellyhub.com (en) and shellyhub.pl (pl)
 *   Aligned with the Shelly Brand Guidelines 2026 palette: clean
 *   white background, deep ink type, accent green for actions.
 *   Mobile-first, no JS framework, no build step.
 * ================================================================ */

/* Palette pulled from the live Shelly brand:
 *   - Logo blue       : #3899D2 (matches shelly-logo.png on every page)
 *   - Deeper brand    : #1F76B6 (used for hover / strong elements)
 *   - Ink / type      : #0E1A2B (consistent with platform docs)
 *   - Soft surfaces   : #F3F8FD / #EAF2FB
 * Green is reserved for "success" badges only; the primary action
 * color is Shelly blue, matching the corporate / shop sites. */
:root {
  --hub-bg:        #ffffff;
  --hub-bg-soft:   #f3f8fd;
  --hub-bg-soft-2: #eaf2fb;
  --hub-fg:        #0e1a2b;
  --hub-fg-soft:   #475569;
  --hub-border:    #e1ecf6;
  --hub-line:      #e1ecf6;
  --hub-accent:    #3899d2;   /* Shelly logo blue — primary brand */
  --hub-accent-d:  #1f76b6;   /* deeper Shelly blue — hover state */
  --hub-accent-2:  #0e1a2b;   /* ink — secondary actions */
  --hub-success:   #34a853;   /* used only for success / featured pills */
  --hub-tag-bg:    #e7f2fb;
  --hub-tag-fg:    #1f76b6;
  --hub-shadow:    0 1px 2px rgba(15, 23, 42, .04), 0 8px 24px rgba(15, 23, 42, .06);
  --hub-shadow-lg: 0 8px 30px rgba(15, 23, 42, .08), 0 24px 48px rgba(15, 23, 42, .08);
  --hub-radius:    14px;
  --hub-radius-lg: 22px;
  --hub-font:      "Inter", "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --hub-font-h:    "Manrope", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --hub-container: 1240px;
}

*, *::before, *::after { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

/* Guard against horizontal overflow on phones.
   Applied only to body (NOT html) to avoid breaking position:fixed
   overlays like the mobile drawer. */

body.hub-body {
  font-family: var(--hub-font);
  color: var(--hub-fg);
  background: var(--hub-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  line-height: 1.55;
  overflow-x: hidden;
  overflow-wrap: anywhere;
  word-break: break-word;
}
@supports (overflow-x: clip) { body.hub-body { overflow-x: clip; } }

img { max-width: 100%; height: auto; display: block; }

a { color: var(--hub-accent-2); text-decoration: none; transition: color .15s ease; }
a:hover { color: var(--hub-accent-d); }

.hub-container {
  width: 100%;
  max-width: var(--hub-container);
  margin: 0 auto;
  padding: 0 22px;
  box-sizing: border-box;
}

.hub-skip {
  position: absolute; left: -9999px; top: -9999px;
  background: var(--hub-fg); color: #fff; padding: 8px 14px; border-radius: 6px;
}
.hub-skip:focus { left: 14px; top: 14px; z-index: 1000; }

/* ── Operator-disclosure strip ────────────────────────────────
   A slim "Shelly Hub — operated by Shelly Group SE" band that
   sits ABOVE the main hub header on every page. Added
   2026-05-28 to address Google Safe Browsing's "no visible
   operator identification" finding (the strongest single signal
   in the impersonation flag). Kept low-emphasis (~28px tall,
   12px type, hub-fg gradient) so it reads as part of the site
   chrome, not a banner ad. The link to shelly.com is the
   actionable corroboration of the ownership claim — both human
   visitors and crawlers can verify ownership in one click. */
.hub-operator-strip {
  background: linear-gradient(180deg, #0d1d3a 0%, #0a172e 100%);
  color: rgba(255, 255, 255, .82);
  font-size: 12px; line-height: 1.4;
  letter-spacing: .01em;
  border-bottom: 1px solid rgba(255, 255, 255, .04);
}
.hub-operator-strip-inner {
  display: flex; align-items: center;
  justify-content: center;        /* center on desktop … */
  gap: 14px;
  padding: 7px 22px;
  flex-wrap: wrap;
}
@media (max-width: 640px) {
  /* … but stack vertically + left-align on phones so neither
     copy chunk gets truncated mid-word. */
  .hub-operator-strip-inner {
    justify-content: flex-start;
    gap: 2px 12px;
    padding: 6px 16px;
  }
}
.hub-operator-strip-text {
  font-weight: 500;
  color: rgba(255, 255, 255, .9);
}
.hub-operator-strip-link {
  color: #AAE1FA;
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
  transition: color .15s ease;
}
.hub-operator-strip-link:hover,
.hub-operator-strip-link:focus {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ── Header ──────────────────────────────────────────────── */
.hub-header {
  background: rgba(255, 255, 255, .92);
  backdrop-filter: saturate(160%) blur(8px);
  border-bottom: 1px solid var(--hub-border);
  position: sticky; top: 0; z-index: 50;
  padding-top: env(safe-area-inset-top, 0px);
}
.hub-header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 22px; padding: 18px 22px;
}
.hub-brand {
  display: flex; align-items: center; gap: 12px;
  color: var(--hub-fg); text-decoration: none;
  min-width: 0;
}
.hub-brand:hover { color: var(--hub-fg); }
.hub-brand-mark {
  height: 28px; width: auto; display: block;
  flex: 0 0 auto;
}
.hub-brand-divider {
  width: 1px; height: 22px; background: var(--hub-line);
  display: block; flex: 0 0 auto;
}
.hub-brand-name {
  font-family: var(--hub-font-h); font-weight: 700;
  font-size: 15px; letter-spacing: -.005em;
  color: var(--hub-fg-soft);
  white-space: nowrap;
}
.hub-nav { display: none; gap: 22px; flex: 1; justify-content: center; }
.hub-nav-link {
  color: var(--hub-fg-soft); font-weight: 500; font-size: 14px;
  padding: 6px 2px; border-bottom: 2px solid transparent;
}
.hub-nav-link:hover { color: var(--hub-fg); border-bottom-color: var(--hub-accent); }
.hub-header-actions { display: flex; align-items: center; gap: 12px; }
.hub-pill {
  display: none;
  background: var(--hub-bg-soft); color: var(--hub-fg);
  border: 1px solid var(--hub-border);
  padding: 8px 16px; border-radius: 999px; font-size: 13px; font-weight: 600;
  white-space: nowrap;
}
.hub-pill:hover { background: var(--hub-bg-soft-2); color: var(--hub-fg); }
.hub-pill-primary {
  background: var(--hub-accent-2); color: #fff; border-color: var(--hub-accent-2);
}
.hub-pill-primary:hover { background: #1858bf; color: #fff; border-color: #1858bf; }

/* Header notification bell (visible only when a submitter is signed in) */
.hub-bell {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: var(--hub-bg-soft);
  border: 1px solid var(--hub-border);
  color: var(--hub-fg);
  text-decoration: none;
  transition: background .15s ease, color .15s ease, border-color .15s ease, transform .15s ease;
}
.hub-bell:hover {
  background: var(--hub-bg-soft-2);
  color: var(--hub-accent-d);
  border-color: #c4dcef;
  transform: translateY(-1px);
}
.hub-bell:focus-visible {
  outline: 2px solid var(--hub-accent);
  outline-offset: 2px;
}
.hub-bell-active {
  color: var(--hub-accent-d);
  border-color: var(--hub-accent);
  background: #f4faff;
  animation: hub-bell-shake 1.4s ease-in-out 2;
}
.hub-bell-active svg { transform-origin: 50% 4px; }
@keyframes hub-bell-shake {
  0%, 100% { transform: rotate(0); }
  10%, 30%, 50% { transform: rotate(-12deg); }
  20%, 40%, 60% { transform: rotate(12deg); }
  70% { transform: rotate(0); }
}
.hub-bell-badge {
  position: absolute;
  top: -4px; right: -4px;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 999px;
  background: #dc2626; color: #fff;
  font-family: var(--hub-font-h);
  font-size: 10.5px; font-weight: 800;
  line-height: 18px; text-align: center;
  border: 2px solid #fff;
  box-shadow: 0 0 0 4px rgba(220, 38, 38, .18);
  animation: hub-bell-pulse 1.8s ease-in-out infinite;
}
.hub-bell-badge[hidden] { display: none !important; }
@keyframes hub-bell-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, .55); }
  50%      { box-shadow: 0 0 0 8px rgba(220, 38, 38, 0); }
}

/* Header avatar — visible only when a submitter is signed in. Acts as
   a single-tap shortcut to /submit/profile. The default chip carries
   a Shelly-blue gradient + white initial; once an actual photo is
   uploaded the `.hub-header-avatar-img` modifier strips that gradient
   away so the user's photo isn't tinted. */
.hub-header-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px; height: 38px;
  border-radius: 50%;
  border: 2px solid #fff;
  background: linear-gradient(135deg, var(--hub-accent), var(--hub-accent-d));
  color: #fff;
  font-family: var(--hub-font-h);
  font-weight: 800;
  font-size: 14px;
  text-decoration: none;
  overflow: hidden;
  box-shadow: 0 0 0 1px var(--hub-border), 0 4px 14px -6px rgba(15, 23, 42, .25);
  transition: transform .15s ease, box-shadow .15s ease;
  flex: 0 0 auto;
}
.hub-header-avatar:hover {
  transform: translateY(-1px);
  box-shadow: 0 0 0 1px var(--hub-accent), 0 6px 18px -6px rgba(31, 118, 182, .45);
  color: #fff;
}
.hub-header-avatar:focus-visible {
  outline: 2px solid var(--hub-accent);
  outline-offset: 2px;
}
/* Photo-uploaded variant: drop the gradient (it would tint the photo
   blue) and lay a clean white plate underneath. The img always covers
   the full 38×38 area so the plate is invisible in the common case;
   it only matters for transparent PNG corners. */
.hub-header-avatar-img {
  background: #fff;
}
.hub-header-avatar img {
  width: 100%; height: 100%;
  display: block;
  object-fit: cover;
}
.hub-header-avatar-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* ── Notification dropdown panel ──────────────────────────── */
.hub-notif-wrap {
  position: relative;
  display: inline-flex;
}
.hub-notif-panel {
  position: absolute;
  top: calc(100% + 10px);
  right: -12px;
  width: 340px;
  background: #fff;
  border: 1px solid var(--hub-border);
  border-radius: 16px;
  box-shadow: 0 20px 50px -12px rgba(15, 23, 42, .25), 0 0 0 1px rgba(15, 23, 42, .04);
  z-index: 100;
  overflow: hidden;
  animation: hub-notif-in .18s ease-out;
}
.hub-notif-panel[hidden] { display: none; }
@keyframes hub-notif-in {
  from { opacity: 0; transform: translateY(-6px) scale(.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.hub-notif-panel::before {
  content: "";
  position: absolute;
  top: -6px; right: 20px;
  width: 12px; height: 12px;
  background: #fff;
  border: 1px solid var(--hub-border);
  border-bottom: 0; border-right: 0;
  transform: rotate(45deg);
}
.hub-notif-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--hub-border);
}
.hub-notif-head strong {
  font-family: var(--hub-font-h);
  font-size: 14px; font-weight: 700;
  color: var(--hub-fg);
}
.hub-notif-viewall {
  font-size: 12px; font-weight: 600;
  color: var(--hub-accent);
}
.hub-notif-body {
  max-height: 340px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.hub-notif-empty {
  display: flex; flex-direction: column;
  align-items: center; gap: 8px;
  padding: 32px 20px;
  color: var(--hub-fg-soft);
  font-size: 13px;
}
.hub-notif-item {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 12px 18px;
  border-bottom: 1px solid var(--hub-line);
  text-decoration: none; color: var(--hub-fg);
  transition: background .12s ease;
}
.hub-notif-item:last-child { border-bottom: 0; }
.hub-notif-item:hover { background: var(--hub-bg-soft); }
.hub-notif-item-unread { background: #f0f7ff; }
.hub-notif-item-icon {
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--hub-bg-soft-2);
  flex: 0 0 auto;
}
.hub-notif-item-icon svg { width: 16px; height: 16px; color: var(--hub-accent); }
.hub-notif-item-body { min-width: 0; }
.hub-notif-item-title {
  font-size: 13px; font-weight: 600; line-height: 1.35;
  margin: 0 0 2px;
}
.hub-notif-item-meta {
  font-size: 11px; color: var(--hub-fg-soft);
}
.hub-notif-backdrop {
  position: fixed; inset: 0; z-index: 99;
  background: transparent;
}
.hub-notif-backdrop[hidden] { display: none; }
@media (max-width: 768px) {
  .hub-notif-panel {
    position: fixed;
    top: auto; right: 12px; left: 12px;
    width: auto;
    top: max(60px, calc(env(safe-area-inset-top, 0px) + 56px));
    border-radius: 14px;
  }
  .hub-notif-panel::before { right: 56px; }
}

/* Sign-out form on /submit/account — uses the meta card padding for
   alignment but separates itself with a hairline. */
.hub-account-logout {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px dashed var(--hub-border);
  display: flex;
  justify-content: flex-end;
}
.hub-account-logout .hub-btn { display: inline-flex; align-items: center; gap: 8px; }

.hub-menu-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px;
  background: var(--hub-bg-soft);
  border: 1px solid var(--hub-border);
  border-radius: 12px;
  padding: 0;
  cursor: pointer;
  position: relative;
  transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.hub-menu-toggle:hover {
  background: var(--hub-bg-soft-2);
  border-color: var(--hub-accent);
}
.hub-menu-toggle:focus-visible {
  outline: 2px solid var(--hub-accent);
  outline-offset: 2px;
}
.hub-menu-toggle span {
  position: absolute; left: 50%; top: 50%;
  width: 18px; height: 2px;
  background: var(--hub-fg);
  border-radius: 2px;
  transform-origin: center;
  transition: transform .25s cubic-bezier(.4, 0, .2, 1),
              opacity .2s ease,
              top .25s cubic-bezier(.4, 0, .2, 1);
  margin-left: -9px;
}
.hub-menu-toggle span:nth-child(1) { top: calc(50% - 6px); transform: translateY(0); }
.hub-menu-toggle span:nth-child(2) { top: 50%; transform: translateY(-50%); }
.hub-menu-toggle span:nth-child(3) { top: calc(50% + 6px); transform: translateY(-100%); }
.hub-menu-toggle[aria-expanded="true"] span:nth-child(1) {
  top: 50%; transform: translateY(-50%) rotate(45deg);
}
.hub-menu-toggle[aria-expanded="true"] span:nth-child(2) {
  opacity: 0; transform: translateY(-50%) scaleX(0);
}
.hub-menu-toggle[aria-expanded="true"] span:nth-child(3) {
  top: 50%; transform: translateY(-50%) rotate(-45deg);
}

/* Mobile nav redesigned as a full-height slide-in drawer + overlay.
 * The previous design was a stacked dropdown that pushed the page
 * content down and felt cramped on narrow viewports. The drawer
 * pattern matches what readers expect from modern editorial sites
 * (it's the default in Stripe Press, NYT, Atlantic, etc.) and
 * gives the category list room to breathe with proper type scale.
 *
 * Markup contract:
 *   <button .hub-menu-toggle[aria-expanded]>
 *   <nav #hub-mobile-nav .hub-mobile-nav [hidden|aria-hidden]>
 * `[hidden]` is the closed state; the JS in hub_layout.html flips
 * `aria-expanded` on the toggle and removes `[hidden]` on the
 * drawer to open it.
 */
.hub-mobile-nav {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  width: 100vw;
  height: 100vh;
  height: 100dvh;     /* dvh = dynamic viewport height; avoids the
                         "drawer cut off above the iOS Safari bar"
                         bug. Browsers that don't support dvh fall
                         back to the previous declaration. */
  /* Above the cookie banner (1500) so the drawer is never obscured
   * when a first-time visitor opens the menu before accepting cookies.
   * The skip link still wins at 9999. */
  z-index: 2000;
  background: rgba(15, 23, 42, .55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  justify-content: flex-end;
  align-items: stretch;
  flex-direction: row;
  gap: 0;
  border-top: 0;
  padding: 0;
  opacity: 1;
  pointer-events: auto;
  animation: hub-mobile-overlay-in .22s ease;
}
.hub-mobile-nav[hidden] {
  display: none !important;
}
@keyframes hub-mobile-overlay-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.hub-mobile-nav-panel {
  background: #fff;
  width: min(86vw, 360px);
  height: 100%;
  display: flex;
  flex-direction: column;
  box-shadow: -24px 0 60px -20px rgba(15, 23, 42, .35);
  animation: hub-mobile-panel-in .28s cubic-bezier(.2, .9, .2, 1);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
@keyframes hub-mobile-panel-in {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}
.hub-mobile-nav-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px;
  padding-top: calc(18px + env(safe-area-inset-top, 0px));
  border-bottom: 1px solid var(--hub-border);
  background: linear-gradient(180deg, var(--hub-bg-soft), #fff);
}
.hub-mobile-nav-head .hub-brand {
  gap: 10px;
}
.hub-mobile-nav-head .hub-brand-mark {
  height: 22px;
}
.hub-mobile-nav-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px;
  border: 0; background: transparent;
  border-radius: 10px;
  color: var(--hub-fg);
  cursor: pointer;
  transition: background .15s ease;
}
.hub-mobile-nav-close:hover { background: var(--hub-bg-soft); }
.hub-mobile-nav-close:focus-visible {
  outline: 2px solid var(--hub-accent); outline-offset: 2px;
}
.hub-mobile-nav-list {
  display: flex; flex-direction: column;
  padding: 14px 0 4px;
  gap: 2px;
  list-style: none; margin: 0;
}
.hub-mobile-link {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  padding: 13px 22px;
  margin: 0 10px;
  color: var(--hub-fg);
  border-bottom: 0;
  border-radius: 10px;
  font-family: var(--hub-font-h);
  font-weight: 600;
  font-size: 15.5px;
  letter-spacing: -.005em;
  transition: background .15s ease, color .15s ease, transform .15s ease;
  text-decoration: none;
}
.hub-mobile-link::after {
  content: "";
  width: 8px; height: 8px;
  border-right: 2px solid var(--hub-fg-soft);
  border-bottom: 2px solid var(--hub-fg-soft);
  transform: rotate(-45deg);
  opacity: .55;
  flex: 0 0 auto;
  transition: transform .18s ease, border-color .18s ease, opacity .18s ease;
}
.hub-mobile-link:hover,
.hub-mobile-link:focus-visible {
  background: var(--hub-bg-soft);
  color: var(--hub-accent-d);
  outline: 0;
}
.hub-mobile-link:hover::after,
.hub-mobile-link:focus-visible::after {
  border-color: var(--hub-accent-d);
  opacity: 1;
  transform: translateX(2px) rotate(-45deg);
}
.hub-mobile-link.is-current {
  background: rgba(31, 118, 182, .1);
  color: var(--hub-accent-d);
}
.hub-mobile-link-cta {
  margin: 18px 18px 22px;
  padding: 14px 18px;
  /* Shelly logo blue — same gradient direction as the header avatar
   * so the drawer CTA reads as the same brand-anchored "primary"
   * affordance. The previous flat ink fill made it look secondary. */
  background: linear-gradient(135deg, var(--hub-accent), var(--hub-accent-d));
  color: #fff;
  font-weight: 700;
  border-radius: 12px;
  text-align: center;
  justify-content: center;
  box-shadow: 0 8px 22px -10px rgba(31, 118, 182, .55);
}
.hub-mobile-link-cta::after { display: none; }
.hub-mobile-link-cta:hover {
  background: linear-gradient(135deg, var(--hub-accent-d), #155a93);
  color: #fff;
  transform: translateY(-1px);
}
.hub-mobile-nav-foot {
  margin-top: auto;
  padding: 18px 22px;
  padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--hub-border);
  display: flex; align-items: center; justify-content: center; gap: 0;
  font-size: 13px; color: var(--hub-fg-soft);
}

/* Desktop breakpoint: show desktop nav, hide hamburger AND make sure
 * the mobile drawer can't be shown even if its [hidden] attribute was
 * removed by an earlier toggle. */
@media (min-width: 880px) {
  .hub-nav { display: flex; }
  .hub-pill { display: inline-flex; }
  .hub-menu-toggle { display: none; }
  .hub-mobile-nav,
  .hub-mobile-nav:not([hidden]) { display: none !important; }
}

/* ── Mobile: ≤ 768px ────────────────────────────────────────
   Phones and small tablets. All mobile-specific rules live here
   instead of scattered around the file so they're easy to audit
   in one pass. The goal is not just "hide the overflow" but to
   make every section look intentionally designed for a narrow
   screen: readable type sizes, generous touch targets, properly
   stacked layouts. */
@media (max-width: 768px) {
  /* ▸ Container — tighter side gutter */
  .hub-container { padding: 0 16px; }
  /* ▸ Header — generous top breathing room on phones.
     On iPhones with notch/Dynamic Island the safe-area-inset already
     pushes the header down; on non-notch phones we still want ≥ 16px
     above the inner row so it doesn't feel glued to the status bar. */
  .hub-header {
    padding-top: max(14px, env(safe-area-inset-top, 14px));
    background: #fff;
    box-shadow: 0 1px 8px rgba(15, 23, 42, .06);
  }
  .hub-header-inner { padding: 14px 16px; gap: 10px; }
  .hub-header-actions { gap: 8px; }
  .hub-brand-divider, .hub-brand-name { display: none; }
  .hub-brand-mark { height: 26px; }
  .hub-bell, .hub-header-avatar, .hub-menu-toggle {
    width: 38px; height: 38px;
  }
  .hub-bell svg { width: 18px; height: 18px; }
  .hub-header-avatar { font-size: 13px; }
  .hub-bell-badge {
    min-width: 16px; height: 16px; font-size: 9.5px; line-height: 16px;
  }
  /* ▸ Hero */
  .hub-hero { padding: 20px 0 32px; }
  .hub-hero-card { padding: 0 16px; }
  .hub-hero-image { border-radius: 14px; margin-bottom: 18px; }
  .hub-hero-title { font-size: 26px; margin-bottom: 10px; }
  .hub-hero-excerpt { font-size: 15px; margin-bottom: 12px; }
  .hub-hero-byline { font-size: 13px; gap: 6px; }
  /* ▸ Cards & grid
     On phones the card spans the full content column, so a wider
     landscape ratio reads as a hero image rather than a thumbnail
     trapped in a small box. We also bump the image-side breathing
     room and let titles wrap two lines without truncating early. */
  .hub-grid { gap: 16px; }
  .hub-card-image { aspect-ratio: 16 / 9; }
  .hub-card-image img { object-position: 50% 40%; }
  .hub-card-body { padding: 16px 18px 18px; gap: 6px; }
  .hub-card-title { font-size: 17px; line-height: 1.28; }
  .hub-card-excerpt { font-size: 13.5px; line-height: 1.55; -webkit-line-clamp: 2; }
  .hub-card-cta { font-size: 12.5px; }
  /* ▸ Rails */
  .hub-rail { padding: 28px 0; }
  .hub-rail-head h2 { font-size: 22px; }
  .hub-rail-more { font-size: 13px; }
  /* ▸ Article page */
  .hub-article { padding: 24px 0 12px; }
  .hub-article-head { padding-top: 8px; padding-bottom: 14px; }
  .hub-article-title { font-size: 28px; margin-bottom: 14px; }
  .hub-article-lede { font-size: 16px; margin-bottom: 16px; }
  .hub-article-hero { margin: 20px auto 28px; width: calc(100% - 32px); border-radius: 14px; }
  .hub-article-body { font-size: 16px; line-height: 1.7; padding-bottom: 32px; }
  .hub-article-body > p:first-of-type::first-letter { font-size: 3em; }
  .hub-article-body img { border-radius: 10px; }
  .hub-article-body blockquote { padding: 14px 16px; font-size: 17px; }
  .hub-article-body pre { font-size: 13px; padding: 16px; border-radius: 10px; }
  .hub-article-body table { font-size: 14px; }
  .hub-article-foot { padding: 18px 0 24px; }
  /* ▸ Footer */
  .hub-footer { padding: 36px 0 18px; margin-top: 40px; }
  /* Brand col spans full width on mobile, then Explore/Shop/Company/Help = 2×2 */
  .hub-footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: 24px 16px;
  }
  .hub-footer-brand-col {
    grid-column: 1 / -1;
    align-items: center;
    text-align: center;
  }
  .hub-footer-brand-col .hub-footer-logo { margin: 0 auto; }
  .hub-footer-tagline { font-size: 12px; margin: 0 auto; text-align: center; }
  .hub-footer-social { justify-content: center; }
  .hub-footer-col h4 { font-size: 10px; margin-bottom: 14px; }
  .hub-footer-col li a { font-size: 12px; }
  .hub-footer-col ul { gap: 10px; }
  /* Legal + copyright centered */
  .hub-footer-base {
    font-size: 10px;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
  }
  .hub-footer-legal { justify-content: center; }
  .hub-footer-copy { text-align: center; }
  .hub-footer-divider { margin: 24px 0 0; }
  /* ▸ Submit flow */
  .hub-submit-page { padding: 28px 0 56px; }
  .hub-submit-hero { padding: 4px 16px 0; margin-bottom: 20px; }
  .hub-submit-hero-title { font-size: 28px; }
  .hub-submit-hero-lede { font-size: 15px; }
  .hub-submit-card { padding: 22px 18px; border-radius: 16px; }
  .hub-submit-card-form { padding-bottom: 24px; }
  .hub-submit-title { font-size: 24px; }
  .hub-form-row input,
  .hub-form-row select,
  .hub-form-row textarea { padding: 10px 12px; font-size: 15px; }
  /* ▸ Empty state */
  .hub-empty { padding: 56px 0; }
  .hub-empty h1 { font-size: 26px; }
  .hub-empty p { font-size: 15px; }
  /* ▸ Cookie banner */
  .hub-cookie-banner-actions .hub-btn { flex: 1 1 calc(50% - 4px); }
}

/* ── Main ────────────────────────────────────────────────── */
.hub-main { min-height: 60vh; padding-bottom: 60px; }

/* ── Marketing banner ────────────────────────────────────────────────
   Shown at the top of the public hub home (above the featured hero
   and the empty state). Two-column layout: pill + headline + lede on
   the left, and four orbiting feature cards around a central Shelly
   mark on the right.

   Layout strategy
   ───────────────
   • The visual is a square 1:1 grid (CSS Grid, `aspect-ratio: 1`)
     so the spokes-and-hub composition stays geometrically correct
     at any container size — cards in corners, hub at center, the
     decorative SVGs on top of each other in the same cell.
   • Spokes / rings are inline SVG (zero network, sharp at any DPR).
   • On `<880px` the layout flips to a single column so the cards
     stack neatly under the headline.

   Why a custom banner instead of `.hub-hero`
   ──────────────────────────────────────────
   `.hub-hero` is the *featured-article* showcase — image + title +
   excerpt for one specific post. This banner is brand-level and
   always rendered, even when the hub has zero published articles,
   so it never overlaps with the featured hero or fights for real
   estate with it.
*/
.hub-banner {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: 64px 0 80px;
  background: linear-gradient(180deg, #f7fbff 0%, #ecf4fc 65%, #f7fbff 100%);
  border-bottom: 1px solid rgba(31, 118, 182, .08);
}
.hub-banner-bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
/* Faint engineering-paper grid in the lower-left corner — picks up
 * on the brand 2026 deck's "designed in the open" treatment. The
 * grid fades to nothing as it approaches the banner centre so it
 * never interferes with text legibility. */
.hub-banner-bg-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, rgba(31, 118, 182, .07) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(31, 118, 182, .07) 1px, transparent 1px);
  background-size: 32px 32px;
  -webkit-mask-image: radial-gradient(circle at 18% 75%, #000 0%, transparent 55%);
          mask-image: radial-gradient(circle at 18% 75%, #000 0%, transparent 55%);
  opacity: .6;
}
/* A soft accent glow under the central hub on the right. Picks up
 * the same blue as the orbital rings so the visual hangs together. */
.hub-banner-bg-glow {
  position: absolute;
  top: 50%; right: -8%;
  width: 60%; height: 130%;
  transform: translateY(-50%);
  background: radial-gradient(circle at 50% 50%,
              rgba(56, 153, 210, .14) 0%,
              rgba(56, 153, 210, .04) 40%,
              transparent 70%);
}

.hub-banner-inner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  align-items: center;
  gap: 56px;
  padding-left: 22px;
  padding-right: 22px;
}

/* ── Banner: text column ───────────────────────────────────── */
.hub-banner-text { max-width: 560px; }
.hub-banner-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 14px 7px 11px;
  background: #fff;
  border: 1px solid rgba(31, 118, 182, .12);
  border-radius: 999px;
  box-shadow: 0 6px 20px -8px rgba(15, 23, 42, .12);
  font-family: var(--hub-font-h);
  font-size: 13px; font-weight: 600;
  letter-spacing: -.005em;
  color: var(--hub-fg);
}
.hub-banner-pill-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--hub-accent);
  box-shadow: 0 0 0 3px rgba(56, 153, 210, .18);
}
.hub-banner-title {
  font-family: var(--hub-font-h);
  font-size: clamp(36px, 5vw, 64px);
  font-weight: 800;
  letter-spacing: -.025em;
  line-height: 1.04;
  margin: 22px 0 22px;
  color: var(--hub-fg);
}
.hub-banner-title-accent,
.hub-banner-title-dark {
  display: block;
}
.hub-banner-title-accent { color: var(--hub-accent); }
.hub-banner-title-dark   { color: var(--hub-fg); }
.hub-banner-lede {
  font-size: clamp(15px, 1.3vw, 17px);
  line-height: 1.55;
  color: var(--hub-fg-soft);
  margin: 0;
  max-width: 480px;
}

/* ── Banner: visual column ─────────────────────────────────── */
.hub-banner-visual {
  position: relative;
  width: 100%;
  max-width: 580px;
  aspect-ratio: 1 / 1;
  margin-left: auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 22px;
  /* Each direct child below positions itself by grid-area when it's
   * a card, or by absolute positioning when it's a decorative layer
   * or the central hub. */
}
.hub-banner-rings,
.hub-banner-spokes {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
}
.hub-banner-rings  { z-index: 0; }
.hub-banner-spokes { z-index: 1; }

/* Central Shelly mark — the geometric center of the 2×2 card grid.
 * Sized as 22% of the visual square so it scales with the column
 * width on narrow viewports without touching the surrounding cards. */
.hub-banner-hub {
  position: absolute;
  top: 50%; left: 50%;
  width: 26%; aspect-ratio: 1 / 1;
  transform: translate(-50%, -50%);
  z-index: 3;
  background: #fff;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  box-shadow:
    0 0 0 10px rgba(255, 255, 255, .85),
    0 22px 56px -18px rgba(15, 23, 42, .28),
    0 0 0 1px rgba(31, 118, 182, .08);
}
.hub-banner-hub-ring {
  position: absolute;
  inset: -16px;
  border-radius: 50%;
  border: 1.5px solid rgba(56, 153, 210, .4);
}
.hub-banner-hub-mark {
  width: 70%; height: 70%;
  object-fit: contain;
  display: block;
}

/* Orbiting feature cards. Each anchors itself to one quadrant of
 * the visual square via `grid-area`; the icon, title, and lede are
 * all mandatory so empty fields can't collapse the card layout. */
.hub-banner-card {
  position: relative;
  z-index: 2;
  background: #fff;
  border-radius: 14px;
  padding: 16px 18px 16px;
  box-shadow:
    0 14px 36px -18px rgba(15, 23, 42, .25),
    0 0 0 1px rgba(31, 118, 182, .06);
  text-decoration: none;
  color: var(--hub-fg);
  transition: transform .18s ease, box-shadow .18s ease;
  display: flex; flex-direction: column; gap: 6px;
  min-width: 0;
}
.hub-banner-card:hover,
.hub-banner-card:focus-visible {
  outline: 0;
  transform: translateY(-2px);
  box-shadow:
    0 18px 44px -18px rgba(31, 118, 182, .35),
    0 0 0 1px rgba(56, 153, 210, .35);
  color: var(--hub-fg);
}
.hub-banner-card-icon {
  display: inline-flex;
  width: 26px; height: 26px;
  color: var(--hub-accent);
  margin-bottom: 2px;
}
.hub-banner-card-icon svg { width: 100%; height: 100%; display: block; }
.hub-banner-card h3 {
  margin: 0;
  font-family: var(--hub-font-h);
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -.005em;
  color: var(--hub-fg);
}
.hub-banner-card p {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--hub-fg-soft);
}

/* Quadrant assignments — these line up exactly with the spoke
 * endpoints in the SVG above (148/452 in a 600-unit viewBox). */
.hub-banner-card-tl { grid-area: 1 / 1 / 2 / 2; align-self: end;   justify-self: end;   margin-right: 18%; margin-bottom: 18%; max-width: 220px; }
.hub-banner-card-tr { grid-area: 1 / 2 / 2 / 3; align-self: end;   justify-self: start; margin-left: 18%;  margin-bottom: 18%; max-width: 220px; }
.hub-banner-card-bl { grid-area: 2 / 1 / 3 / 2; align-self: start; justify-self: end;   margin-right: 18%; margin-top: 18%;    max-width: 220px; }
.hub-banner-card-br { grid-area: 2 / 2 / 3 / 3; align-self: start; justify-self: start; margin-left: 18%;  margin-top: 18%;    max-width: 220px; }

/* ── Banner: tablet & narrow desktops ──────────────────────── */
@media (max-width: 1100px) {
  .hub-banner-inner { gap: 40px; }
  .hub-banner-card-tl, .hub-banner-card-tr,
  .hub-banner-card-bl, .hub-banner-card-br {
    margin-left: 6%; margin-right: 6%;
    margin-top: 10%;  margin-bottom: 10%;
  }
}

/* ── Banner: mobile ─────────────────────────────────────────
 * On <880px we drop the orbital layout and stack the cards in a
 * 2×2 grid below the headline. The central Shelly mark + spokes +
 * rings are dropped (they only make sense in the orbit metaphor)
 * and replaced with a slimmer hero illustration that doesn't
 * compete with the cards for visual weight. */
@media (max-width: 879px) {
  .hub-banner { padding: 40px 0 48px; }
  .hub-banner-inner {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  .hub-banner-text { max-width: none; }
  .hub-banner-title { margin: 18px 0 14px; }
  .hub-banner-visual {
    aspect-ratio: auto;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto;
    gap: 14px;
    max-width: none;
  }
  .hub-banner-rings,
  .hub-banner-spokes,
  .hub-banner-hub {
    display: none;
  }
  .hub-banner-card-tl, .hub-banner-card-tr,
  .hub-banner-card-bl, .hub-banner-card-br {
    margin: 0;
    align-self: stretch;
    justify-self: stretch;
    max-width: none;
    grid-area: auto;
  }
}
@media (max-width: 480px) {
  .hub-banner { padding: 28px 0 36px; }
  .hub-banner-visual { grid-template-columns: 1fr; }
  .hub-banner-card { padding: 14px 16px; }
}

/* ── Empty state ─────────────────────────────────────────── */
.hub-empty {
  padding: 80px 0;
  background: linear-gradient(180deg, var(--hub-bg) 0%, var(--hub-bg-soft) 100%);
}
.hub-empty .hub-container { text-align: center; }
.hub-empty h1 {
  font-family: var(--hub-font-h); font-size: 32px; font-weight: 800;
  letter-spacing: -.02em; margin: 0 0 12px;
}
.hub-empty p { color: var(--hub-fg-soft); font-size: 17px; }
.hub-empty-msg {
  text-align: center; color: var(--hub-fg-soft);
  padding: 60px 20px; font-size: 16px;
}

/* ── Hero ────────────────────────────────────────────────── */
.hub-hero {
  background: linear-gradient(180deg, var(--hub-bg-soft) 0%, var(--hub-bg) 75%);
  padding: 28px 0 48px;
}
.hub-hero-card {
  display: block;
  width: 100%;
  max-width: var(--hub-container);
  margin: 0 auto;
  padding: 0 22px;
  color: var(--hub-fg);
}
.hub-hero-card:hover { color: var(--hub-fg); }
.hub-hero-image {
  border-radius: var(--hub-radius-lg);
  overflow: hidden;
  box-shadow: var(--hub-shadow-lg);
  margin-bottom: 24px;
  background: var(--hub-bg-soft-2);
  aspect-ratio: 16 / 9;
}
/* Letterbox (not crop) — match `.hub-article-hero` so the homepage
   feature shows wide banners in full against the `--hub-bg-soft-2`
   backdrop already set on `.hub-hero-image`. See ticket SH-BL-2BV5W. */
.hub-hero-image img { width: 100%; height: 100%; object-fit: contain; transition: transform .4s ease; }
.hub-hero-card:hover .hub-hero-image img { transform: scale(1.02); }
.hub-hero-placeholder {
  width: 100%; height: 100%;
  background: linear-gradient(135deg, #0f1d3a 0%, #1f76b6 100%);
  display: flex; align-items: center; justify-content: center;
  position: relative;
}
.hub-hero-placeholder::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(circle at 30% 30%, rgba(255,255,255,.15), transparent 60%);
  pointer-events: none;
}
.hub-hero-placeholder-mark {
  font-family: var(--hub-font-h);
  font-size: clamp(64px, 12vw, 120px);
  font-weight: 800;
  letter-spacing: -.04em;
  color: rgba(255,255,255,.85);
  line-height: 1;
  position: relative;
  z-index: 1;
}
.hub-hero-meta { display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.hub-hero-title {
  font-family: var(--hub-font-h);
  font-size: clamp(28px, 4.4vw, 48px);
  font-weight: 800;
  letter-spacing: -.02em;
  margin: 0 0 14px;
  line-height: 1.1;
}
.hub-hero-excerpt {
  font-size: clamp(16px, 1.6vw, 18px);
  color: var(--hub-fg-soft);
  margin: 0 0 16px;
  max-width: 720px;
}
.hub-hero-cta {
  display: inline-block;
  font-weight: 600;
  color: var(--hub-accent);
}
.hub-hero-byline {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 0 0 18px;
  font-size: 14px;
  color: var(--hub-fg-soft);
}
.hub-hero-byline-author { font-weight: 600; color: var(--hub-fg); }
.hub-hero-byline-sep { color: var(--hub-fg-soft); }
.hub-hero-byline-curator {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 10px; border-radius: 999px;
  background: rgba(31, 118, 182, .08);
  color: #0f1d3a; font-size: 12px; font-weight: 600;
}

/* ── Tags ────────────────────────────────────────────────── */
.hub-tag {
  display: inline-block;
  background: var(--hub-tag-bg);
  color: var(--hub-tag-fg);
  font-size: 12px; font-weight: 600;
  padding: 4px 10px; border-radius: 999px;
  letter-spacing: .02em;
}
.hub-tag-small { font-size: 11px; padding: 3px 9px; }
.hub-tag-featured { background: var(--hub-success); color: #fff; }

/* ── Rails (category sections) ───────────────────────────── */
.hub-rail { padding: 36px 0; border-top: 1px solid var(--hub-border); }
.hub-rail:first-of-type { border-top: 0; }
.hub-rail-creators { background: var(--hub-bg-soft); border-top: 0; }
.hub-rail-related { background: var(--hub-bg-soft); }
.hub-rail-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; margin-bottom: 22px;
}
.hub-rail-head h2 {
  font-family: var(--hub-font-h); font-size: 26px; font-weight: 800;
  margin: 0; letter-spacing: -.01em;
}
.hub-rail-more { font-size: 14px; font-weight: 600; color: var(--hub-accent); white-space: nowrap; }

/* ── Card grid ───────────────────────────────────────────── */
.hub-grid {
  display: grid; gap: 24px;
  grid-template-columns: 1fr;
}
@media (min-width: 720px)  { .hub-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .hub-grid { grid-template-columns: repeat(3, 1fr); } }
.hub-grid-3 { grid-template-columns: 1fr; }
@media (min-width: 720px)  { .hub-grid-3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .hub-grid-3 { grid-template-columns: repeat(3, 1fr); } }
.hub-grid-creators { grid-template-columns: 1fr; }
@media (min-width: 720px)  { .hub-grid-creators { grid-template-columns: repeat(2, 1fr); } }

.hub-card {
  background: #fff;
  border: 1px solid var(--hub-border);
  border-radius: var(--hub-radius);
  overflow: hidden;
  box-shadow: var(--hub-shadow);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
  display: flex; flex-direction: column;
}
.hub-card:hover { transform: translateY(-2px); box-shadow: var(--hub-shadow-lg); border-color: #d3e3f4; }
.hub-card-link { display: block; color: var(--hub-fg); flex: 1; }
.hub-card-link:hover { color: var(--hub-fg); }
/* Card image
   ────────────────────────────────────────────────────────────
   Editorial photos vary wildly: phone-screen mockups with text
   overlays at the edges, square product shots, cinematic 16:9
   landscapes, etc. With `object-fit: cover` _any_ source whose
   ratio doesn't match the box gets clipped — and editors had no
   way to recover the cropped pixels.

   The fix is a "blurred-backdrop" pattern (a.k.a. Apple Photos
   thumbnail trick): the wrapper paints a heavily blurred copy of
   the same source image full-bleed, and the foreground `<img>`
   uses `object-fit: contain` so the entire photo is visible. The
   blurred backdrop fills any letterboxing softly without looking
   like a hard black bar. The CSS variable `--hub-card-img` is
   set per-card via the template so the backdrop matches the
   foreground without an extra DOM node.
*/
.hub-card-image {
  --hub-card-img: none;
  aspect-ratio: 16 / 10;
  background: var(--hub-bg-soft);
  overflow: hidden;
  position: relative;
  isolation: isolate;
}
.hub-card-image::before {
  /* Blurred backdrop — same source as the foreground image.
     `inset: -12px` slightly overscans the wrapper so the blurred
     edges never reveal hard borders against the card frame. */
  content: "";
  position: absolute;
  inset: -12px;
  background-image: var(--hub-card-img);
  background-size: cover;
  background-position: center;
  filter: blur(28px) saturate(120%) brightness(0.92);
  opacity: .55;
  z-index: 0;
  pointer-events: none;
}
.hub-card-image::after {
  /* Soft white-veil over the backdrop so the foreground image's
     edges still get a clean visual separation, especially when
     the source is dark. */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255,255,255,.18), rgba(255,255,255,.02));
  z-index: 1;
  pointer-events: none;
}
.hub-card-image img {
  position: relative;
  z-index: 2;
  width: 100%; height: 100%;
  object-fit: contain;          /* full image, no crop */
  object-position: center;
  transition: transform .35s ease;
  display: block;
}
.hub-card:hover .hub-card-image img { transform: scale(1.03); }
.hub-card-placeholder {
  position: absolute; inset: 0;
  z-index: 3;
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(56,153,210,.18), transparent 60%),
    linear-gradient(135deg, var(--hub-bg-soft-2), var(--hub-bg-soft));
}
.hub-card-placeholder::after {
  content: ""; position: absolute; inset: 0;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' fill='none' stroke='%23bcd0e6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='8' y='12' width='48' height='40' rx='4'/><circle cx='22' cy='26' r='4'/><path d='M8 44l16-16 12 12 8-8 12 12'/></svg>") center / 56px 56px no-repeat;
  opacity: .7;
}
.hub-card-body { padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 8px; }
.hub-card-title {
  font-family: var(--hub-font-h);
  font-size: 18px; font-weight: 700; margin: 0;
  line-height: 1.3; letter-spacing: -.01em;
}
.hub-card-excerpt {
  font-size: 14px; color: var(--hub-fg-soft); margin: 0;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.hub-card-cta {
  margin-top: auto; padding-top: 6px;
  font-size: 13px; font-weight: 600; color: var(--hub-accent);
}

/* Influencer card variant on home rail */
.hub-card-creator { padding-bottom: 14px; }
.hub-card-creator-name {
  font-size: 12px; color: var(--hub-fg-soft); font-weight: 600;
  letter-spacing: .03em; text-transform: uppercase;
}
.hub-card-actions {
  display: flex; gap: 8px; flex-wrap: wrap;
  padding: 0 20px 4px; margin-top: -4px;
}

/* ── Buttons ─────────────────────────────────────────────── */
.hub-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 10px 18px; border-radius: 999px;
  font-weight: 600; font-size: 14px; white-space: nowrap;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
  border: 1px solid transparent; cursor: pointer;
}
.hub-btn-primary  { background: var(--hub-accent);   color: #fff; }
.hub-btn-primary:hover  { background: var(--hub-accent-d);  color: #fff; }
.hub-btn-secondary{ background: var(--hub-fg);       color: #fff; }
.hub-btn-secondary:hover{ background: #1c2a3f;       color: #fff; }
.hub-btn-ghost    { background: transparent;         color: var(--hub-fg); border-color: var(--hub-border); }
.hub-btn-ghost:hover { background: var(--hub-bg-soft); color: var(--hub-fg); }

/* ── Article ───────────────────────────────────────────────
   Column widths bumped on 2026-05-12 from 760/720/760 to
   1140/1120/1140 (three passes, user kept asking for wider).
   These are very close to the `--hub-container` (1240px) max,
   which means head/body/foot now nearly span the hero-image
   width — head/foot still keep a small 100px breathing margin
   on each side of a 1240px container so they don't look like
   they're crashing into the page edges. Body font-size was
   bumped 18 → 19 → 20px in lockstep to keep characters-per-line
   at a magazine-style ~95-100 CPL (past the 50-75 textbook
   sweet spot but typical for editorial layouts like
   The Verge / Vox / Bloomberg long-reads). Mobile widths are
   untouched (see the @media (max-width: 768px) block above). */
.hub-article { padding: 36px 0 16px; }
.hub-article-head {
  max-width: 1140px; padding-top: 12px; padding-bottom: 18px;
  text-align: left;
}
.hub-breadcrumbs { font-size: 13px; color: var(--hub-fg-soft); margin-bottom: 18px; }
.hub-breadcrumbs a { color: var(--hub-fg-soft); }
.hub-breadcrumbs a:hover { color: var(--hub-fg); }
.hub-breadcrumb-sep { margin: 0 6px; color: var(--hub-border); }
.hub-eyebrow {
  display: inline-block;
  font-family: var(--hub-font-h);
  font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--hub-accent);
  background: rgba(56, 153, 210, .10);
  padding: 6px 12px; border-radius: 999px;
  margin: 0 0 18px;
  text-decoration: none;
}
.hub-eyebrow:hover { background: rgba(56, 153, 210, .18); color: var(--hub-accent-d); }
.hub-article-title {
  font-family: var(--hub-font-h);
  font-size: clamp(32px, 5vw, 52px);
  font-weight: 800; letter-spacing: -.025em;
  margin: 0 0 18px; line-height: 1.08;
  color: var(--hub-fg);
}
.hub-article-lede {
  font-family: var(--hub-font-h);
  font-size: clamp(17px, 1.7vw, 22px);
  font-weight: 500;
  color: var(--hub-fg-soft);
  line-height: 1.45;
  margin: 0 0 22px;
}
.hub-article-byline {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 14px;
  padding-top: 16px;
  border-top: 1px solid var(--hub-line);
  font-size: 14px; color: var(--hub-fg-soft);
}
.hub-byline-author { display: inline-flex; align-items: center; gap: 10px; }
.hub-byline-avatar {
  width: 32px; height: 32px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--hub-accent), var(--hub-accent-d));
  color: #fff; font-family: var(--hub-font-h);
  font-size: 13px; font-weight: 700;
}
.hub-byline-avatar-shelly {
  background: linear-gradient(135deg, #0f1d3a, #1f76b6);
  letter-spacing: .02em;
}
.hub-byline-name { font-weight: 600; color: var(--hub-fg); }
.hub-byline-meta { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.hub-byline-dot {
  width: 3px; height: 3px; border-radius: 50%;
  background: var(--hub-fg-soft); display: inline-block;
}
.hub-byline-curator {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px 3px 4px; border-radius: 999px;
  background: rgba(31, 118, 182, .08);
  color: #0f1d3a; font-size: 12px; font-weight: 600;
  letter-spacing: .02em; line-height: 1;
}
.hub-byline-curator-mark {
  width: 18px; height: 18px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #0f1d3a, #1f76b6);
  color: #fff; font-family: var(--hub-font-h);
  font-size: 10px; font-weight: 800; letter-spacing: 0;
}
.hub-card-byline {
  margin: 4px 0 0; font-size: 12px; color: var(--hub-fg-soft);
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.hub-card-byline-author { font-weight: 600; color: var(--hub-fg); }
.hub-card-byline-sep { color: var(--hub-fg-soft); }
.hub-card-byline-curator {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px;
  background: rgba(31, 118, 182, .08);
  color: #0f1d3a; font-size: 11px; font-weight: 600;
  letter-spacing: .02em;
}
.hub-article-hero {
  margin: 32px auto 40px; padding: 0;
  max-width: var(--hub-container);
  width: calc(100% - 44px);
  border-radius: var(--hub-radius-lg);
  overflow: hidden;
  box-shadow: 0 24px 60px -28px rgba(15, 23, 42, .35),
              0 8px 18px -10px rgba(15, 23, 42, .18);
  box-shadow: var(--hub-shadow-lg);
  aspect-ratio: 16 / 9;
  /* Letterbox (not crop): panoramic banners (~2:1) are shown in full
     against a subtle hub-tinted backdrop instead of being clipped to
     16:9. Keeping the 16:9 box means zero layout shift / CLS. A true
     16:9 image still fills the box exactly. See ticket SH-BL-2BV5W. */
  background: var(--hub-bg-soft-2);
}
.hub-article-hero img { width: 100%; height: 100%; object-fit: contain; }
.hub-article-video {
  margin: 32px auto 40px; padding: 0;
  max-width: var(--hub-container);
  width: calc(100% - 44px);
}
.hub-article-video-frame {
  position: relative;
  border-radius: var(--hub-radius-lg);
  overflow: hidden;
  background: #0b1220;
  box-shadow: var(--hub-shadow-lg);
  aspect-ratio: 16 / 9;
}
@supports not (aspect-ratio: 16 / 9) {
  .hub-article-video-frame { padding-top: 56.25%; }
}
.hub-article-video-frame iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0;
}
.hub-article-video-caption {
  margin-top: 10px;
  font-size: 13px; color: #6b7785;
  letter-spacing: .02em; text-align: center;
}
.hub-article-body {
  max-width: 820px; padding-top: 12px; padding-bottom: 48px;
  font-size: 20px; line-height: 1.75;
  color: #2a3340;
}
.hub-article-body > p:first-of-type::first-letter {
  font-family: var(--hub-font-h);
  font-size: 3.6em;
  line-height: .95;
  font-weight: 800;
  float: left;
  padding: 4px 12px 0 0;
  color: var(--hub-accent);
}
.hub-article-body h2 {
  font-family: var(--hub-font-h);
  font-size: 28px; font-weight: 800; margin: 44px 0 14px;
  letter-spacing: -.015em;
  color: var(--hub-fg);
}
.hub-article-body h2::before {
  content: ""; display: block;
  width: 36px; height: 3px;
  background: var(--hub-accent);
  border-radius: 2px;
  margin-bottom: 14px;
}
/* Empty headings used to render as a floating blue accent bar with no
 * text underneath — the writer just sees stray dashes between
 * paragraphs. The server sanitiser strips most of these on submit but
 * legacy content + the live editor preview can still surface them. */
.hub-article-body h1:empty,
.hub-article-body h2:empty,
.hub-article-body h3:empty,
.hub-article-body h4:empty,
.hub-article-body h5:empty,
.hub-article-body h6:empty,
.hub-article-body h2:has(> br:only-child),
.hub-article-body h3:has(> br:only-child) {
  display: none !important;
}
.hub-article-body h3 {
  font-family: var(--hub-font-h);
  font-size: 21px; font-weight: 700; margin: 32px 0 10px;
  letter-spacing: -.005em; color: var(--hub-fg);
}
.hub-article-body p { margin: 0 0 20px; }
.hub-article-body ul, .hub-article-body ol { padding-left: 26px; margin: 0 0 20px; }
.hub-article-body li { margin-bottom: 8px; }
.hub-article-body blockquote {
  position: relative;
  border-left: 4px solid var(--hub-accent);
  padding: 18px 22px 18px 28px;
  margin: 28px 0;
  background: var(--hub-bg-soft);
  border-radius: 0 var(--hub-radius) var(--hub-radius) 0;
  font-family: var(--hub-font-h);
  font-size: 20px; font-weight: 500;
  font-style: normal; line-height: 1.5;
  color: var(--hub-fg);
}
.hub-article-body blockquote::before {
  content: "\201C";
  position: absolute; top: -8px; left: 14px;
  font-family: Georgia, serif;
  font-size: 56px; line-height: 1;
  color: var(--hub-accent); opacity: .35;
}
.hub-article-body img, .hub-article-body figure img {
  display: block;
  margin: 24px auto;
  max-width: 100%;
  width: auto;
  height: auto;
  max-height: 560px;
  object-fit: contain;
  border-radius: var(--hub-radius);
  box-shadow: 0 12px 32px -16px rgba(15, 23, 42, .25);
}
.hub-article-body figure {
  margin: 28px 0;
}
.hub-article-body figure figcaption {
  text-align: center; font-size: 13px; color: var(--hub-fg-soft);
  margin-top: 10px;
}
.hub-article-body a {
  color: var(--hub-accent);
  border-bottom: 1px solid rgba(56, 153, 210, .35);
  font-weight: 500;
  transition: border-color .15s ease, color .15s ease;
}
.hub-article-body a:hover { color: var(--hub-accent-d); border-bottom-color: currentColor; }
.hub-article-body hr {
  border: 0; height: 1px;
  background: var(--hub-line);
  margin: 36px 0;
}
.hub-article-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .92em;
  background: var(--hub-bg-soft);
  padding: 2px 6px; border-radius: 4px;
  color: var(--hub-fg);
}
.hub-article-body pre {
  background: #0f172a; color: #e2e8f0;
  padding: 18px 20px; border-radius: var(--hub-radius);
  overflow-x: auto; margin: 24px 0;
  font-size: 14px; line-height: 1.6;
}
.hub-article-body pre code { background: transparent; padding: 0; color: inherit; }
/* Callouts — emitted by the manual editor and the structured-block
   renderer alike. Keep parity with the in-app preview but a notch
   more refined for the public surface. */
.hub-article-body .callout {
  display: flex; gap: 14px;
  padding: 18px 22px; margin: 24px 0;
  border-radius: var(--hub-radius);
  border: 1px solid transparent;
  font-size: 15px; line-height: 1.6;
}
.hub-article-body .callout::before {
  font-size: 22px; line-height: 1.4; flex-shrink: 0;
}
.hub-article-body .callout-info { background: #eff6ff; border-color: #bfdbfe; color: #1e3a8a; }
.hub-article-body .callout-info::before { content: "ℹ"; }
.hub-article-body .callout-tip { background: #ecfdf5; border-color: #a7f3d0; color: #065f46; }
.hub-article-body .callout-tip::before { content: "💡"; }
.hub-article-body .callout-warning { background: #fff7ed; border-color: #fdba74; color: #9a3412; }
.hub-article-body .callout-warning::before { content: "⚠"; }
.hub-article-body .callout-danger { background: #fef2f2; border-color: #fca5a5; color: #991b1b; }
.hub-article-body .callout-danger::before { content: "⛔"; }
/* Tables in article body */
.hub-article-body table {
  border-collapse: collapse;
  width: 100%; margin: 24px 0;
  font-size: 15px; line-height: 1.55;
}
.hub-article-body table th,
.hub-article-body table td {
  border: 1px solid var(--hub-border);
  padding: 10px 12px;
  vertical-align: top;
  text-align: left;
}
.hub-article-body table th {
  background: var(--hub-bg-soft);
  font-weight: 700; color: var(--hub-fg);
}
.hub-article-body table tbody tr:nth-child(even) td { background: #fafcfe; }
/* Highlight (mark) and sub/sup */
.hub-article-body mark { background: #fef08a; color: inherit; padding: 0 3px; border-radius: 3px; }
.hub-article-body sub { font-size: .72em; vertical-align: sub; }
.hub-article-body sup { font-size: .72em; vertical-align: super; }
/* Inline / video figures */
.hub-article-body figure.blog-video {
  margin: 28px 0;
}
.hub-article-body figure.blog-video iframe {
  border-radius: var(--hub-radius);
}
.hub-article-body figure.blog-video figcaption {
  margin-top: 10px; text-align: center;
  font-size: 13px; color: var(--hub-fg-soft);
}
.hub-article-body .custom-embed { margin: 24px 0; }

/* Influencer summary card */
.hub-influencer-card {
  background: var(--hub-bg-soft);
  padding: 36px 0;
  border-top: 1px solid var(--hub-border);
  border-bottom: 1px solid var(--hub-border);
}
.hub-influencer-head { max-width: 760px; margin-bottom: 14px; }
.hub-influencer-label {
  text-transform: uppercase; letter-spacing: .08em; font-size: 11px;
  color: var(--hub-fg-soft); font-weight: 700; margin: 0 0 4px;
}
.hub-influencer-name {
  font-family: var(--hub-font-h); font-size: 22px; font-weight: 700; margin: 0;
}
.hub-influencer-handle {
  display: inline-block; margin-left: 8px; color: var(--hub-fg-soft);
  font-size: 14px; font-weight: 500;
}
.hub-influencer-body { max-width: 760px; }
.hub-influencer-cta { display: flex; gap: 10px; flex-wrap: wrap; max-width: 760px; margin-top: 14px; }

.hub-article-foot { padding: 24px 0 32px; max-width: 1140px; }

/* ── Category page ───────────────────────────────────────── */
.hub-category { padding: 36px 0 24px; }
.hub-category-title {
  font-family: var(--hub-font-h); font-size: clamp(28px, 4vw, 40px);
  font-weight: 800; letter-spacing: -.02em; margin: 0 0 6px;
}
.hub-category-count { color: var(--hub-fg-soft); margin: 0 0 28px; font-size: 14px; }

/* ── Footer ──────────────────────────────────────────────────────
 * Mirrors the corporate.shelly.com footer:
 *   – dark `#0a1628` slab with subtle radial accent
 *   – brand column (logo + tagline + 5 social pills)
 *   – three nav columns (Explore / Shop / Help)
 *   – thin gradient divider
 *   – legal nav + copyright + listing line on the bottom bar
 * Uses the canonical Shelly social handles by default; admins can
 * override individual urls via `hub_site_settings.social_links`.
 */
.hub-footer {
  background: #0a1628;
  color: #94a3b8;
  padding: 56px 0 24px;
  padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  margin-top: 64px;
  position: relative;
}
.hub-footer::before {
  content: "";
  position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(to right, transparent,
              rgba(68,149,209,.18), rgba(0,60,130,.24),
              rgba(68,149,209,.18), transparent);
}
.hub-footer a { color: #94a3b8; transition: color .15s ease; }
.hub-footer a:hover { color: #fff; }

.hub-footer-grid {
  display: grid; gap: 36px;
  grid-template-columns: 1fr 1fr;
}
@media (min-width: 900px) {
  .hub-footer-grid { grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr; gap: 36px; }
}

/* Brand + tagline + socials column */
.hub-footer-brand-col { display: flex; flex-direction: column; gap: 18px; }
.hub-footer-logo {
  display: inline-flex; align-items: center;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 12px;
  padding: 10px 14px;
  width: max-content;
  transition: background .15s ease, border-color .15s ease;
}
.hub-footer-logo:hover {
  background: rgba(255,255,255,.08);
  border-color: rgba(255,255,255,.12);
}
.hub-footer-mark { height: 26px; width: auto; display: block; }
.hub-footer-tagline {
  font-size: 13px; line-height: 1.65;
  color: #6b7d96; max-width: 320px; margin: 0;
}
.hub-footer-social {
  list-style: none; padding: 0; margin: 6px 0 0;
  display: flex; flex-wrap: wrap; gap: 8px;
}
.hub-footer-social-pill {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px;
  border-radius: 10px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
  color: #94a3b8;
  transition: background .18s ease, border-color .18s ease,
              color .18s ease, transform .18s ease;
}
.hub-footer-social-pill svg { width: 16px; height: 16px; display: block; }
.hub-footer-social-pill:hover {
  background: var(--hub-accent, #003c82);
  border-color: var(--hub-accent, #003c82);
  color: #fff;
  transform: translateY(-1px);
}

/* Link columns */
.hub-footer-col h4 {
  font-family: var(--hub-font-h);
  font-size: 11px; text-transform: uppercase; letter-spacing: .2em;
  color: #fff; font-weight: 700;
  margin: 0 0 18px; padding: 0 0 10px;
  border-bottom: 1px solid rgba(255,255,255,.06);
}
.hub-footer-col ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 12px; }
.hub-footer-col li a { font-size: 13px; line-height: 1.4; }

/* Gradient divider between the grid and the bottom bar */
.hub-footer-divider {
  height: 1px;
  background: linear-gradient(to right, transparent,
              rgba(68,149,209,.15), rgba(0,60,130,.20),
              rgba(68,149,209,.15), transparent);
  margin: 40px 0 0;
}

/* Bottom legal + copyright bar */
.hub-footer-base {
  margin-top: 0; padding-top: 22px;
  display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between;
  align-items: center;
  font-size: 11px; color: #6b7d96;
}
.hub-footer-legal {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 4px 12px;
}
.hub-footer-legal a {
  font-size: 11px; color: #6b7d96;
}
.hub-footer-legal span {
  color: rgba(255,255,255,.10);
  font-size: 10px;
}
.hub-footer-copy { text-align: right; }
.hub-footer-copy p { margin: 0; font-size: 11px; color: #6b7d96; }
.hub-footer-copy p + p { margin-top: 4px; }
.hub-footer-operator {
  font-size: 10.5px !important;
  color: #5b6c84 !important;
  max-width: 520px;
  margin-left: auto !important;
  line-height: 1.5;
}
.hub-footer-operator a {
  color: #2563eb;
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
}
.hub-footer-operator a:hover,
.hub-footer-operator a:focus { text-decoration: underline; }
@media (max-width: 720px) {
  .hub-footer-operator { max-width: none; margin-left: 0 !important; }
}
@media (max-width: 759px) {
  .hub-footer-base { flex-direction: column; align-items: center; text-align: center; }
  .hub-footer-legal { justify-content: center; flex-wrap: wrap; }
  .hub-footer-copy { text-align: center; }
}

/* ── Cookie consent banner ─────────────────────────────────────────
   Slim glass-morphism slab anchored at the bottom of the viewport.
   On first visit the banner enters with a soft slide-up; once the
   user has stored a choice it stops rendering server-side. */
.hub-cookie-banner {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 1500;
  background: rgba(10, 22, 40, 0.96);
  color: #e2eaf3;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: 0 -16px 48px rgba(0, 60, 130, 0.25);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  transform: translateY(120%);
  transition: transform 0.32s cubic-bezier(.22,.61,.36,1);
  padding: 18px 0 16px;
}
body.hub-cookie-open .hub-cookie-banner { transform: translateY(0); }
.hub-cookie-inner {
  max-width: var(--hub-max-w, 1200px);
  margin: 0 auto;
  padding: 0 24px;
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 18px;
  align-items: center;
}
.hub-cookie-icon {
  width: 44px; height: 44px;
  border-radius: 12px;
  background: linear-gradient(135deg, #003c82 0%, #0e6dd4 100%);
  color: #fff;
  display: grid; place-items: center;
  flex: none;
  box-shadow: 0 6px 18px rgba(0, 60, 130, 0.35);
}
.hub-cookie-icon svg { width: 24px; height: 24px; }
.hub-cookie-body h3 {
  margin: 0 0 4px;
  font-size: 15px;
  font-weight: 700;
  color: #fff;
  letter-spacing: -.005em;
}
.hub-cookie-body p {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: #b6c4d6;
}
.hub-cookie-body p a {
  color: #8cb6e8;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.hub-cookie-body p a:hover { color: #fff; }
.hub-cookie-actions {
  display: flex; gap: 8px; flex-wrap: wrap;
  justify-content: flex-end;
}
.hub-cookie-actions .hub-btn {
  font-size: 13px;
  padding: 10px 16px;
  white-space: nowrap;
}
.hub-cookie-actions .hub-btn-ghost {
  background: transparent;
  color: #b6c4d6;
  border: 1px solid rgba(255, 255, 255, 0.15);
}
.hub-cookie-actions .hub-btn-ghost:hover {
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
}
.hub-cookie-actions .hub-btn-secondary {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.18);
}
.hub-cookie-actions .hub-btn-secondary:hover {
  background: rgba(255, 255, 255, 0.14);
}

.hub-cookie-panel {
  border-top: 1px solid rgba(255, 255, 255, 0.10);
  margin: 16px 0 0;
  padding: 16px 24px 4px;
  display: grid; gap: 14px;
}
.hub-cookie-banner-expanded { padding-bottom: 22px; }
.hub-cookie-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: center;
  padding: 12px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.hub-cookie-row:last-of-type { border-bottom: 0; }
.hub-cookie-row h4 {
  margin: 0 0 2px;
  font-size: 13px; font-weight: 700; color: #fff;
}
.hub-cookie-row p {
  margin: 0; font-size: 12px; color: #98a8be; line-height: 1.5;
}
.hub-cookie-toggle {
  position: relative;
  display: inline-flex; align-items: center; gap: 8px;
  cursor: pointer;
}
.hub-cookie-toggle input { position: absolute; opacity: 0; pointer-events: none; }
.hub-cookie-switch {
  position: relative;
  width: 38px; height: 22px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  transition: background 0.18s ease;
}
.hub-cookie-switch::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.18s ease;
  box-shadow: 0 1px 3px rgba(0,0,0,0.35);
}
.hub-cookie-toggle input:checked + .hub-cookie-switch {
  background: var(--hub-accent, #003c82);
}
.hub-cookie-toggle input:checked + .hub-cookie-switch::after { transform: translateX(16px); }
.hub-cookie-toggle.is-locked .hub-cookie-switch { opacity: .55; cursor: not-allowed; }
.hub-cookie-pill {
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #94a3b8;
}
.hub-cookie-panel-actions {
  display: flex; justify-content: flex-end;
  margin-top: 4px;
}

@media (max-width: 759px) {
  .hub-cookie-inner {
    grid-template-columns: 1fr;
    gap: 12px;
  }
  .hub-cookie-icon { display: none; }
  .hub-cookie-actions { justify-content: stretch; }
  .hub-cookie-actions .hub-btn { flex: 1; }
}

/* ── Legal pages ───────────────────────────────────────────────── */
.hub-legal {
  background:
    radial-gradient(900px 360px at 14% -200px, rgba(56,153,210,.16) 0%, transparent 60%),
    linear-gradient(180deg, var(--hub-bg-soft, #f6f8fb) 0%, var(--hub-bg, #fff) 60%);
  padding-bottom: 80px;
}
.hub-legal-hero {
  padding: 56px 0 28px;
  border-bottom: 1px solid rgba(15, 26, 43, 0.06);
}
.hub-legal-hero .hub-container { max-width: var(--hub-max-w, 1200px); }
.hub-legal-breadcrumb {
  display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
  font-size: 13px; color: #6b7d96;
  margin: 0 0 14px;
}
.hub-legal-breadcrumb a { color: #6b7d96; }
.hub-legal-breadcrumb a:hover { color: var(--hub-accent, #003c82); }
.hub-legal-breadcrumb-leaf { color: #1e2c44; font-weight: 600; }
.hub-legal-hero h1 {
  font-family: 'Manrope', system-ui, sans-serif;
  font-size: clamp(34px, 4.6vw, 52px);
  font-weight: 800;
  letter-spacing: -.025em;
  margin: 0 0 12px;
  color: #0a1628;
}
.hub-legal-lead {
  font-size: 17px; line-height: 1.6;
  max-width: 720px;
  color: #45556d;
  margin: 0 0 18px;
}
.hub-legal-updated {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #fff;
  border: 1px solid rgba(15, 26, 43, 0.10);
  padding: 7px 14px;
  border-radius: 999px;
  font-size: 12px;
  color: #45556d;
  box-shadow: 0 1px 2px rgba(15, 26, 43, 0.04);
  margin: 0;
}
.hub-legal-updated time { font-variant-numeric: tabular-nums; font-weight: 600; color: #1e2c44; }

.hub-legal-body {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: 56px;
  padding-top: 36px;
  max-width: var(--hub-max-w, 1200px);
}

.hub-legal-toc {
  position: sticky;
  top: 96px;
  align-self: start;
  background: #fff;
  border: 1px solid rgba(15, 26, 43, 0.08);
  border-radius: 16px;
  padding: 18px 18px 14px;
  box-shadow: 0 4px 14px rgba(15, 26, 43, 0.04);
}
.hub-legal-toc h2 {
  margin: 0 0 12px;
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #6b7d96;
}
.hub-legal-toc ol {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 4px;
  counter-reset: hub-toc;
}
.hub-legal-toc ol li {
  counter-increment: hub-toc;
  padding: 0;
}
.hub-legal-toc ol li a {
  display: flex; gap: 10px;
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 13.5px;
  color: #1e2c44;
  border: 1px solid transparent;
  line-height: 1.4;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.hub-legal-toc ol li a::before {
  content: counter(hub-toc, decimal-leading-zero);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: #6b7d96;
}
.hub-legal-toc ol li a:hover {
  background: #f1f5fa;
  border-color: rgba(15, 26, 43, 0.06);
  color: var(--hub-accent, #003c82);
}
.hub-legal-toc ol li a:hover::before { color: var(--hub-accent, #003c82); }
.hub-legal-toc-foot {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed rgba(15, 26, 43, 0.10);
}
.hub-legal-other {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--hub-accent, #003c82);
  letter-spacing: -.005em;
}
.hub-legal-other:hover { text-decoration: underline; }

.hub-legal-content {
  background: #fff;
  border: 1px solid rgba(15, 26, 43, 0.08);
  border-radius: 18px;
  padding: 36px 44px 40px;
  box-shadow: 0 6px 22px rgba(15, 26, 43, 0.04);
  min-width: 0;
}
.hub-legal-section {
  scroll-margin-top: 110px;
  padding: 22px 0;
  border-bottom: 1px dashed rgba(15, 26, 43, 0.08);
}
.hub-legal-section:first-of-type { padding-top: 0; }
.hub-legal-section:last-of-type { border-bottom: 0; padding-bottom: 0; }
.hub-legal-section h2 {
  font-family: 'Manrope', system-ui, sans-serif;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -.015em;
  color: #0a1628;
  margin: 0 0 12px;
}
.hub-legal-prose {
  font-size: 15px;
  line-height: 1.72;
  color: #2f3e57;
}
.hub-legal-prose p { margin: 0 0 14px; }
.hub-legal-prose p:last-child { margin-bottom: 0; }
.hub-legal-prose a {
  color: var(--hub-accent, #003c82);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.hub-legal-prose a:hover { color: #0e6dd4; }
.hub-legal-prose strong { color: #0a1628; font-weight: 700; }
.hub-legal-prose ul, .hub-legal-prose ol {
  margin: 0 0 14px; padding-left: 24px;
}
.hub-legal-prose li { margin: 0 0 6px; }
.hub-legal-prose code {
  font-family: 'JetBrains Mono', 'Menlo', monospace;
  font-size: 12.5px;
  background: #f1f5fa;
  border: 1px solid rgba(15, 26, 43, 0.06);
  padding: 1px 6px;
  border-radius: 6px;
}
.hub-legal-address {
  font-style: normal;
  background: #f6f8fb;
  border-left: 3px solid var(--hub-accent, #003c82);
  padding: 12px 16px;
  border-radius: 0 10px 10px 0;
  margin: 0 0 14px;
  line-height: 1.65;
}

.hub-legal-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  margin: 4px 0 18px;
  border: 1px solid rgba(15, 26, 43, 0.08);
  border-radius: 10px;
  overflow: hidden;
}
.hub-legal-table th, .hub-legal-table td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid rgba(15, 26, 43, 0.06);
  vertical-align: top;
}
.hub-legal-table th {
  background: #f6f8fb;
  font-weight: 700;
  color: #1e2c44;
  letter-spacing: .005em;
}
.hub-legal-table tr:last-child td { border-bottom: 0; }

.hub-legal-pager {
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid rgba(15, 26, 43, 0.08);
  display: flex; flex-wrap: wrap; gap: 10px;
}
.hub-legal-pager-link {
  display: inline-flex; align-items: center;
  gap: 6px;
  padding: 8px 14px;
  background: #f1f5fa;
  color: #1e2c44;
  border: 1px solid rgba(15, 26, 43, 0.06);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.hub-legal-pager-link::after { content: '→'; opacity: .6; }
.hub-legal-pager-link:hover {
  background: var(--hub-accent, #003c82);
  border-color: var(--hub-accent, #003c82);
  color: #fff;
}
.hub-legal-pager-link:hover::after { opacity: 1; }

@media (max-width: 1023px) {
  .hub-legal-body {
    grid-template-columns: 1fr;
    gap: 24px;
  }
  .hub-legal-toc { position: static; }
  .hub-legal-content { padding: 28px 24px 32px; }
}

/* ── Submit flow (auth + form) ───────────────────────────── */
.hub-submit-page {
  background:
    radial-gradient(1100px 480px at 12% -120px, rgba(56,153,210,.18) 0%, transparent 65%),
    radial-gradient(900px 380px at 92% -160px, rgba(15,26,43,.12) 0%, transparent 60%),
    linear-gradient(180deg, var(--hub-bg-soft) 0%, var(--hub-bg) 55%);
  padding: 40px 0 80px;
  min-height: 60vh;
}

/* Hero block on the submit page */
.hub-submit-hero {
  max-width: 860px;
  margin: 0 auto 28px;
  padding: 8px 22px 0;
}
.hub-submit-hero-eyebrow {
  display: inline-block;
  background: rgba(56, 153, 210, .12);
  color: var(--hub-accent-d);
  font-family: var(--hub-font-h);
  font-size: 12px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 999px;
  margin: 0 0 14px;
}
.hub-submit-hero-title {
  font-family: var(--hub-font-h);
  font-size: clamp(30px, 4.4vw, 48px); font-weight: 800;
  letter-spacing: -.02em; margin: 0 0 12px;
  line-height: 1.05;
  color: var(--hub-fg);
}
.hub-submit-hero-lede {
  font-size: clamp(15px, 1.5vw, 18px);
  color: var(--hub-fg-soft);
  max-width: 640px;
  margin: 0 0 20px;
  line-height: 1.55;
}
/* Hero call-out — links the writer over to /submit/stories when they
   already have something pending. Styled as a soft amber chip so it
   reads as "heads up" without becoming the loudest thing on the page. */
.hub-submit-hero-callout {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #fff8eb;
  border: 1px solid #fbe1a8;
  color: #8c5b00;
  text-decoration: none;
  font-size: 13px;
  font-weight: 700;
  padding: 8px 14px;
  border-radius: 999px;
  margin-top: 4px;
  transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.hub-submit-hero-callout:hover {
  background: #ffefc8;
  border-color: #f6c66a;
  color: #6b4500;
  transform: translateY(-1px);
}
.hub-submit-hero-callout svg { color: #b45309; }
.hub-submit-hero-meta {
  display: inline-flex; align-items: center; gap: 12px;
  background: #fff;
  border: 1px solid var(--hub-border);
  padding: 8px 14px 8px 8px;
  border-radius: 999px;
  box-shadow: var(--hub-shadow);
  font-size: 14px;
}
.hub-submit-hero-avatar {
  width: 30px; height: 30px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--hub-accent), var(--hub-accent-d));
  color: #fff; font-family: var(--hub-font-h);
  font-size: 13px; font-weight: 800;
}

.hub-submit-shell {
  display: grid; gap: 24px;
  grid-template-columns: minmax(0, 560px);
  justify-content: center;
}
.hub-submit-shell-wide {
  grid-template-columns: minmax(0, 720px);
  align-items: start;
}
/* Solo writing canvas — used by /submit when there's no side rail.
   Wider than the login/register card but narrower than full-page so
   line-length stays readable inside the rich-text editor. */
.hub-submit-card-form-solo,
.hub-submit-shell:has(.hub-submit-card-form-solo) {
  width: 100%;
}
.hub-submit-shell:has(.hub-submit-card-form-solo) {
  grid-template-columns: minmax(0, 880px);
}
@media (min-width: 1080px) {
  .hub-submit-shell-wide {
    grid-template-columns: minmax(0, 760px) minmax(300px, 400px);
  }
}
.hub-submit-card {
  background: #fff;
  border: 1px solid var(--hub-border);
  border-radius: var(--hub-radius-lg);
  padding: 30px 32px;
  box-shadow: var(--hub-shadow);
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  overflow: hidden;
}
.hub-submit-card-form { padding-bottom: 32px; }
.hub-submit-card-side { padding: 24px 24px; position: sticky; top: 92px; }
.hub-submit-side-hint {
  font-size: 12.5px; color: var(--hub-fg-soft);
  margin: 0 0 16px;
  background: var(--hub-bg-soft);
  border: 1px dashed var(--hub-border);
  border-radius: 10px;
  padding: 10px 12px;
  line-height: 1.5;
}
.hub-submit-title {
  font-family: var(--hub-font-h);
  font-size: clamp(24px, 3.2vw, 32px); font-weight: 800;
  letter-spacing: -.02em; margin: 0 0 8px;
}
.hub-submit-subtitle {
  font-family: var(--hub-font-h);
  font-size: 18px; font-weight: 800; margin: 0 0 8px;
  letter-spacing: -.01em;
}
.hub-submit-intro { color: var(--hub-fg-soft); margin: 0 0 18px; }
.hub-submit-mute { color: var(--hub-fg-soft); }
/* Operator-disclosure banner (shown above the sign-in / register
   form). Same content as the top-of-page strip, but expanded to
   spell out the account isolation message — typing a password is
   the highest-friction moment on the site, so the banner explicitly
   reassures the visitor what account they're creating and links to
   the parent shelly.com over HTTPS for verification. Styled as a
   soft info pill — palette borrowed from the existing `hub-tag` /
   `hub-link` tokens so it doesn't compete with the form's primary
   CTA. */
.hub-submit-disclosure {
  display: flex; align-items: flex-start;
  gap: 10px;
  background: #eff8ff;
  color: #0c4a6e;
  border: 1px solid #bae6fd;
  padding: 12px 14px;
  border-radius: var(--hub-radius);
  margin: 0 0 18px;
  font-size: 13px;
  line-height: 1.5;
}
.hub-submit-disclosure svg {
  flex: 0 0 auto;
  margin-top: 1px;
  color: #0369a1;
}
.hub-submit-disclosure a {
  color: #0369a1;
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 600;
  white-space: nowrap;
}
.hub-submit-disclosure a:hover,
.hub-submit-disclosure a:focus { color: #0c4a6e; }
.hub-submit-error {
  background: #fef2f2; color: #991b1b;
  border: 1px solid #fecaca;
  padding: 10px 14px; border-radius: var(--hub-radius);
  margin-bottom: 14px; font-size: 14px;
}
.hub-submit-flash {
  background: var(--hub-tag-bg); color: var(--hub-tag-fg);
  border: 1px solid var(--hub-border);
  padding: 10px 14px; border-radius: var(--hub-radius);
  margin-bottom: 14px; font-size: 14px;
}
.hub-submit-empty {
  display: grid; gap: 8px; place-items: center;
  text-align: center;
  padding: 28px 12px;
  border: 1px dashed var(--hub-border);
  border-radius: var(--hub-radius);
  color: var(--hub-fg-soft);
  background: var(--hub-bg-soft);
}
.hub-submit-empty span { font-size: 28px; }

.hub-form { display: grid; gap: 0; min-width: 0; }
.hub-form-section {
  min-width: 0;
  max-width: 100%;
  border-top: 1px solid var(--hub-line);
  padding: 22px 0 4px;
}
.hub-form-section:first-child { border-top: 0; padding-top: 0; }
.hub-form-section-head {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 14px;
}
.hub-form-section-head h2 {
  font-family: var(--hub-font-h);
  font-size: 18px; font-weight: 700; margin: 0;
  color: var(--hub-fg); letter-spacing: -.005em;
}
.hub-form-section-step {
  width: 28px; height: 28px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--hub-bg-soft-2); color: var(--hub-accent-d);
  font-family: var(--hub-font-h);
  font-weight: 800; font-size: 13px;
}
.hub-form-row { display: grid; gap: 6px; font-size: 14px; margin-bottom: 14px; }
.hub-form-row > span {
  font-weight: 600; color: var(--hub-fg); font-size: 13px;
}
.hub-form-row input,
.hub-form-row select,
.hub-form-row textarea {
  font: inherit; color: var(--hub-fg);
  background: #fff;
  border: 1px solid var(--hub-border);
  padding: 11px 14px; border-radius: 12px;
  min-height: 44px;
  width: 100%; box-sizing: border-box;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.hub-form-row textarea { resize: vertical; min-height: 100px; line-height: 1.55; }
.hub-form-row input:hover,
.hub-form-row select:hover,
.hub-form-row textarea:hover { border-color: #c4dcef; }
.hub-form-row input:focus,
.hub-form-row select:focus,
.hub-form-row textarea:focus {
  outline: 0;
  border-color: var(--hub-accent);
  box-shadow: 0 0 0 3px rgba(56, 153, 210, .18);
}
.hub-form-helper {
  font-size: 12px; color: var(--hub-fg-soft);
  line-height: 1.45;
}
.hub-form-foot { margin: 18px 0 0; font-size: 14px; color: var(--hub-fg-soft); }
.hub-form-foot a { font-weight: 600; }
.hub-form-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  margin-top: 22px;
  padding-top: 22px;
  border-top: 1px solid var(--hub-line);
}
.hub-form-actions-hint {
  font-size: 12.5px; color: var(--hub-fg-soft);
  flex: 1; min-width: 200px;
}
.hub-btn-lg {
  padding: 14px 28px; font-size: 15px;
  box-shadow: 0 8px 24px -10px rgba(56, 153, 210, .55);
}
.hub-btn-lg:hover { box-shadow: 0 12px 30px -10px rgba(31, 118, 182, .65); }

.hub-pill-ghost {
  background: #fff !important;
  border: 1px solid var(--hub-border) !important;
  color: var(--hub-fg) !important;
}
.hub-pill-ghost:hover {
  background: var(--hub-bg-soft) !important;
  color: var(--hub-fg) !important;
  border-color: #c4dcef !important;
}

.hub-inline-form { display: inline-block; margin: 0; }
.hub-inline-form .hub-pill { border: 1px solid var(--hub-border); cursor: pointer; }

/* Cover image dropzone */
.hub-cover-zone {
  position: relative;
  display: block;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  border: 2px dashed var(--hub-border);
  border-radius: 16px;
  background: linear-gradient(180deg, #fbfdff, var(--hub-bg-soft));
  padding: 28px 22px;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
  margin-bottom: 14px;
  outline: none;
  overflow: hidden;
}
.hub-cover-zone:hover,
.hub-cover-zone:focus-visible {
  border-color: var(--hub-accent);
  background: #f4faff;
  box-shadow: 0 0 0 4px rgba(56, 153, 210, .12);
}
.hub-cover-zone-drag {
  border-color: var(--hub-accent);
  background: rgba(56, 153, 210, .12);
}
.hub-cover-zone-filled {
  border-style: solid;
  background: #fff;
  padding: 0;
}
.hub-cover-empty {
  display: grid; place-items: center; gap: 6px;
  color: var(--hub-fg-soft);
  text-align: center;
}
.hub-cover-empty svg { color: var(--hub-accent); }
.hub-cover-headline {
  font-family: var(--hub-font-h);
  font-size: 15px; font-weight: 700;
  color: var(--hub-fg);
  margin: 4px 0 0;
}
.hub-cover-headline span { color: var(--hub-accent); text-decoration: underline; }
.hub-cover-sub { font-size: 12.5px; margin: 0; }

/* Media/writing guidelines callout */
.hub-media-guidelines {
  background: #f8fbff;
  border: 1px solid #dbe7f6;
  border-radius: 10px;
  padding: 14px 18px;
  margin-top: 12px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--hub-fg-soft);
}
.hub-media-guidelines p { margin: 0 0 6px; }
.hub-media-guidelines strong { color: var(--hub-fg); font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .03em; }
.hub-media-guidelines ul {
  margin: 0; padding-left: 18px;
  list-style: disc;
}
.hub-media-guidelines li { margin-bottom: 2px; }
.hub-media-guidelines-body { margin-bottom: 14px; }
.hub-cover-preview {
  position: relative;
  display: block;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  border-radius: 14px;
  overflow: hidden;
  background: var(--hub-bg-soft-2);
  aspect-ratio: 16 / 9;
}
.hub-cover-preview[hidden] { display: none !important; }
.hub-cover-preview img {
  display: block;
  width: 100%; height: 100%;
  max-width: 100%;
  object-fit: cover;
}
.hub-cover-meta {
  position: absolute; left: 14px; bottom: 12px;
  background: rgba(15, 23, 42, .68);
  color: #fff;
  font-size: 12px; font-weight: 600;
  padding: 4px 10px; border-radius: 999px;
  backdrop-filter: blur(2px);
  max-width: calc(100% - 60px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hub-cover-remove {
  position: absolute; top: 10px; right: 10px;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: rgba(15, 23, 42, .75);
  color: #fff;
  border: 0;
  font-size: 18px; line-height: 1;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .15s ease, transform .15s ease;
  z-index: 2;
}
.hub-cover-remove:hover { background: #b91c1c; transform: scale(1.05); }

/* Submission list cards (v2) */
.hub-submission-list {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: 12px;
}
.hub-submission {
  position: relative;
  display: flex; gap: 0;
  border: 1px solid var(--hub-border);
  border-radius: 14px;
  background: #fff;
  overflow: hidden;
  transition: box-shadow .2s ease, border-color .2s ease, transform .2s ease;
}
.hub-submission:hover {
  border-color: #d3e3f4;
  box-shadow: var(--hub-shadow-lg);
  transform: translateY(-1px);
}
.hub-submission-stripe { width: 5px; flex: 0 0 5px; background: var(--hub-fg-soft); }
.hub-submission-stripe-pending   { background: linear-gradient(180deg, #f97316, #fb923c); }
.hub-submission-stripe-in-review { background: linear-gradient(180deg, #4f46e5, #818cf8); }
.hub-submission-stripe-approved  { background: linear-gradient(180deg, #16a34a, #4ade80); }
.hub-submission-stripe-rejected  { background: linear-gradient(180deg, #dc2626, #f87171); }
.hub-submission-body { flex: 1; padding: 14px 16px; min-width: 0; }
.hub-submission-head {
  display: flex; align-items: flex-start; gap: 10px; justify-content: space-between;
  margin-bottom: 4px;
  flex-wrap: wrap;
}
.hub-submission-title {
  font-family: var(--hub-font-h);
  font-weight: 700; color: var(--hub-fg); font-size: 15px;
  letter-spacing: -.005em;
  display: inline-flex; align-items: center; gap: 8px;
  flex: 1; min-width: 0; word-break: break-word;
}
.hub-submission-status {
  font-size: 10.5px; font-weight: 800; padding: 4px 10px;
  border-radius: 999px; text-transform: uppercase; letter-spacing: .06em;
  flex: 0 0 auto;
}
.hub-submission-status-pending   { background: #fff7ed; color: #9a3412; }
.hub-submission-status-in-review { background: #eef2ff; color: #3730a3; }
.hub-submission-status-approved  { background: #e7f8ec; color: #166534; }
.hub-submission-status-rejected  { background: #fef2f2; color: #991b1b; }
.hub-submission-meta {
  font-size: 12px; color: var(--hub-fg-soft); display: flex; gap: 6px; flex-wrap: wrap;
}
.hub-submission-thread {
  margin-top: 12px; padding-top: 12px;
  border-top: 1px dashed var(--hub-border);
  display: grid; gap: 10px;
}
.hub-submission-msg {
  display: flex; gap: 10px; align-items: flex-start;
  font-size: 13px;
}
.hub-submission-msg-avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
  font-family: var(--hub-font-h);
  font-size: 13px; font-weight: 800; color: #fff;
  background: linear-gradient(135deg, var(--hub-accent), var(--hub-accent-d));
  box-shadow: 0 2px 6px rgba(56, 153, 210, .25);
}
.hub-submission-msg-bubble {
  flex: 1; min-width: 0;
  background: var(--hub-bg-soft);
  border: 1px solid var(--hub-border);
  border-radius: 14px;
  padding: 8px 12px 10px;
}
.hub-submission-msg-system .hub-submission-msg-avatar { background: linear-gradient(135deg, #16a34a, #34a853); box-shadow: 0 2px 6px rgba(34, 168, 83, .25); }
.hub-submission-msg-system .hub-submission-msg-bubble { background: #f0fdf4; border-color: #bbf7d0; }
.hub-submission-msg-submitter .hub-submission-msg-avatar {
  background: linear-gradient(135deg, #94a3b8, #475569);
  box-shadow: 0 2px 6px rgba(71, 85, 105, .25);
}
.hub-submission-msg-submitter .hub-submission-msg-bubble { background: #f8fafc; border-color: #e2e8f0; }
.hub-submission-msg-head {
  display: flex; gap: 8px; align-items: baseline;
  margin-bottom: 4px; flex-wrap: wrap;
}
.hub-submission-msg-head strong { font-size: 12.5px; color: var(--hub-fg); }
.hub-submission-msg-body { color: var(--hub-fg); white-space: pre-wrap; line-height: 1.5; }

/* New-message glow + dot */
.hub-submission-glow {
  border-color: var(--hub-accent);
  box-shadow: 0 0 0 3px rgba(56, 153, 210, .18), var(--hub-shadow-lg);
  animation: hub-pulse 2.6s ease 2;
}
@keyframes hub-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(56,153,210,.55), var(--hub-shadow); }
  60%  { box-shadow: 0 0 0 14px rgba(56,153,210,0),  var(--hub-shadow-lg); }
  100% { box-shadow: 0 0 0 0 rgba(56,153,210,0),    var(--hub-shadow-lg); }
}
.hub-submission-dot {
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--hub-accent);
  box-shadow: 0 0 0 4px rgba(56, 153, 210, .18);
  flex: 0 0 9px;
}

/* ── Custom modal (replaces window.prompt) ───────────────── */
.hub-modal {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.hub-modal[hidden] { display: none; }
.hub-modal-backdrop {
  position: absolute; inset: 0;
  background: rgba(15, 23, 42, .55);
  backdrop-filter: blur(4px);
  opacity: 0; transition: opacity .22s ease;
}
.hub-modal.hub-modal-open .hub-modal-backdrop { opacity: 1; }
.hub-modal-card {
  position: relative;
  width: min(480px, 100%);
  background: #fff;
  border-radius: 18px;
  box-shadow: 0 32px 80px -16px rgba(15, 23, 42, .35),
              0 12px 24px -10px rgba(15, 23, 42, .12);
  border: 1px solid var(--hub-border);
  transform: translateY(8px) scale(.98);
  opacity: 0;
  transition: opacity .22s ease, transform .22s ease;
}
.hub-modal.hub-modal-open .hub-modal-card {
  transform: translateY(0) scale(1);
  opacity: 1;
}
.hub-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px 4px;
}
.hub-modal-head h3 {
  font-family: var(--hub-font-h);
  font-size: 18px; font-weight: 800; letter-spacing: -.01em;
  margin: 0;
}
.hub-modal-close {
  width: 32px; height: 32px;
  border-radius: 50%;
  border: 0; background: var(--hub-bg-soft);
  color: var(--hub-fg); font-size: 18px; line-height: 1;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .15s ease, color .15s ease;
}
.hub-modal-close:hover { background: var(--hub-bg-soft-2); color: var(--hub-accent-d); }
.hub-modal-body { padding: 8px 22px 4px; }
.hub-modal-help {
  font-size: 13px; color: var(--hub-fg-soft);
  margin: 0 0 12px;
}
.hub-modal-input {
  width: 100%; box-sizing: border-box;
  font: inherit;
  border: 1px solid var(--hub-border);
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 14px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.hub-modal-input:focus {
  outline: 0;
  border-color: var(--hub-accent);
  box-shadow: 0 0 0 3px rgba(56, 153, 210, .18);
}
.hub-modal-error {
  margin: 10px 0 0;
  font-size: 12.5px;
  color: #b91c1c;
  font-weight: 600;
}
.hub-modal-foot {
  display: flex; justify-content: flex-end; gap: 10px;
  padding: 14px 22px 18px;
}
/* Wide variant for modals that need both a select and a multi-line
 * textarea (e.g. the code-block insertion dialog). */
.hub-modal-wide .hub-modal-card { width: min(720px, 100%); }
.hub-modal-row {
  display: grid; gap: 6px;
  margin: 0 0 12px;
}
.hub-modal-label {
  font-size: 12px; font-weight: 700; letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--hub-fg-soft);
}
.hub-modal-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 13px; line-height: 1.55;
  background: #0b1020; color: #e2e8f0;
  border-color: #1e293b;
  border-radius: 12px;
  min-height: 220px;
  resize: vertical;
  tab-size: 2;
  white-space: pre;
  overflow: auto;
}
.hub-modal-code:focus {
  border-color: var(--hub-accent);
  box-shadow: 0 0 0 3px rgba(56, 153, 210, .25);
}

/* ── Article preview modal (full-screen rendition of the draft) ── */
.hub-modal-fullscreen { padding: 0; }
.hub-modal-fullscreen .hub-modal-card.hub-preview-shell {
  width: min(960px, 100%);
  height: min(94vh, 920px);
  max-height: 94vh;
  border-radius: 22px;
  display: grid;
  grid-template-rows: auto 1fr auto;
  /* `min-width:0` on the card itself + on its grid children below
     prevents the grid from blowing out wider than the viewport on
     mobile. Without this the body/article kept their content's
     natural min-width (the `<h1>` placeholder text could not break)
     and the modal scrolled ~90px sideways at 375px wide. */
  min-width: 0;
  overflow: hidden;
  background: linear-gradient(180deg,#fff 0%, #f7fafd 100%);
}
.hub-modal-fullscreen .hub-modal-card.hub-preview-shell > * { min-width: 0; }
.hub-preview-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px;
  padding: 22px 26px 14px;
  border-bottom: 1px solid var(--hub-border);
  background: linear-gradient(180deg, rgba(255,255,255,.96), rgba(247,250,253,.92));
  position: relative;
}
.hub-preview-head-meta { display: grid; gap: 6px; min-width: 0; }
.hub-preview-eyebrow {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--hub-accent-d);
  padding: 4px 10px;
  border: 1px solid color-mix(in srgb, var(--hub-accent) 35%, white);
  background: color-mix(in srgb, var(--hub-accent) 10%, white);
  border-radius: 999px;
  width: fit-content;
}
.hub-preview-head h3 {
  font-family: var(--hub-font-h);
  font-size: 22px; font-weight: 800; letter-spacing: -.015em;
  margin: 0;
  color: var(--hub-fg);
}
.hub-preview-body {
  padding: 0;
  overflow: auto;
  background: #fff;
}
.hub-preview-article {
  /* Mirrors the public article's reading width so the preview is a
     true visual rehearsal — readers see the same column. */
  max-width: 720px;
  margin: 0 auto;
  padding: 36px 32px 60px;
}

/* Category eyebrow — matches `.hub-eyebrow` on `hub_article.html`.
   Note: `display:inline-flex` overrides the user-agent default for
   `[hidden]`, so we explicitly opt back into `display:none` when the
   element is hidden via the HTML attribute. Without this an unselected
   category showed up as an empty blue pill above the headline. */
.hub-preview-eyebrow-cat {
  display: inline-flex; align-items: center;
  font-size: 12px; font-weight: 800;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--hub-accent-d);
  background: color-mix(in srgb, var(--hub-accent) 10%, white);
  border: 1px solid color-mix(in srgb, var(--hub-accent) 28%, white);
  border-radius: 999px;
  padding: 5px 12px;
  text-decoration: none;
  pointer-events: none; /* preview-only, never navigable */
  margin-bottom: 14px;
}
.hub-preview-eyebrow-cat[hidden] { display: none; }

/* H1 — same scale as `.hub-article-title`. The empty-state placeholder
   stays styled like a real headline (italic + soft tone) instead of a
   tiny "—" so an unfilled draft reads as "skeleton", not "broken". */
.hub-preview-h1 {
  font-family: var(--hub-font-h);
  font-size: clamp(30px, 4.4vw, 44px);
  line-height: 1.12;
  letter-spacing: -.02em;
  font-weight: 800;
  margin: 0 0 14px;
  color: var(--hub-fg);
  text-wrap: balance;
}
.hub-preview-h1[data-empty="1"] {
  color: color-mix(in srgb, var(--hub-fg) 35%, white);
  font-style: italic;
  font-weight: 700;
}

/* Lede — matches `.hub-article-lede`. */
.hub-preview-lede {
  font-size: 18px; line-height: 1.55;
  color: rgba(20,30,40,.78);
  margin: 0 0 22px;
  text-wrap: pretty;
}
.hub-preview-lede[data-empty="1"] {
  color: color-mix(in srgb, var(--hub-fg) 35%, white);
  font-style: italic;
}

/* Byline — re-uses the public article's `.hub-byline-*` classes so the
   curated-by-Shelly mark and dot separators are pixel-identical. */
.hub-preview-byline {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 8px 10px;
  margin: 0 0 28px;
  font-size: 14px;
  color: var(--hub-fg-soft);
}
.hub-preview-byline .hub-byline-avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--hub-accent), var(--hub-accent-d));
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 13px;
  margin-right: 8px;
}
.hub-preview-byline .hub-byline-author {
  display: inline-flex; align-items: center;
  font-weight: 700;
  color: var(--hub-fg);
}
.hub-preview-byline .hub-byline-meta {
  display: inline-flex; align-items: center;
  gap: 8px;
  color: var(--hub-fg-soft);
}

/* Hero / cover image — `<figure>` after the byline, exactly where the
   public article puts `.hub-article-hero`. Empty state collapses to a
   compact, friendly "add a cover" prompt rather than a half-page void.

   Visibility is driven entirely by the `data-empty` attribute on the
   <figure> so the JS only needs to toggle one thing. We can't rely on
   the [hidden] HTML attribute on the inner <img>/<div> because their
   explicit display rules below (`display:block` / `display:flex`)
   would otherwise win and both would render simultaneously. */
.hub-preview-hero {
  position: relative;
  margin: 0 0 30px;
  border-radius: 16px;
  overflow: hidden;
  background: #f4f8fb;
  border: 1px solid var(--hub-border);
}
.hub-preview-hero img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 520px;
  object-fit: cover;
}
.hub-preview-hero[data-empty="1"] {
  /* Compact dashed dropzone when no cover is staged — clearly an
     optional placeholder, not the broken empty 16:9 box from before. */
  border: 1.5px dashed color-mix(in srgb, var(--hub-accent) 35%, white);
  background:
    radial-gradient(circle at top left,  rgba(56,153,210,.07), transparent 60%),
    radial-gradient(circle at bottom right, rgba(170,225,250,.10), transparent 60%),
    #f7fafd;
  aspect-ratio: auto;
  min-height: 0;
}
.hub-preview-hero[data-empty="1"] img         { display: none; }
.hub-preview-hero:not([data-empty]) .hub-preview-hero-empty { display: none; }
.hub-preview-hero-empty {
  display: flex; align-items: center; justify-content: center;
  gap: 10px;
  padding: 20px 16px;
  color: color-mix(in srgb, var(--hub-fg) 45%, white);
  font-size: 13.5px; font-weight: 600;
}
.hub-preview-hero-empty svg { flex-shrink: 0; opacity: .55; }

/* Body content — same column rules as `.hub-article-body`. */
.hub-preview-content {
  font-size: 17px; line-height: 1.75;
  color: var(--hub-fg);
  word-wrap: break-word;
  overflow-wrap: anywhere;
}
.hub-preview-content[data-empty="1"] .hub-preview-empty {
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  margin: 0;
  padding: 36px 24px;
  border-radius: 14px;
  border: 1.5px dashed color-mix(in srgb, var(--hub-accent) 30%, white);
  background: #f7fafd;
  color: color-mix(in srgb, var(--hub-fg) 45%, white);
  font-style: italic;
  font-size: 14.5px;
}
.hub-preview-content img,
.hub-preview-content video,
.hub-preview-content iframe {
  max-width: 100%;
  height: auto;
  border-radius: 12px;
  display: block;
  margin: 14px auto;
}
.hub-preview-content pre.hub-code,
.hub-preview-content pre {
  max-width: 100%;
  overflow: auto;
  border-radius: 12px;
}
.hub-preview-empty {
  padding: 36px 22px;
  text-align: center;
  color: rgba(15,23,42,.5);
  border: 1.5px dashed var(--hub-border);
  border-radius: 14px;
  font-size: 14px;
  font-weight: 600;
}
.hub-preview-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  padding: 16px 26px;
  border-top: 1px solid var(--hub-border);
  background: linear-gradient(180deg, rgba(247,250,253,.92), rgba(255,255,255,.98));
}
.hub-preview-foot-actions {
  display: flex; gap: 10px; flex-shrink: 0;
}
@media (max-width: 720px) {
  .hub-modal-fullscreen .hub-modal-card.hub-preview-shell {
    width: 100%;
    height: 100vh;
    max-height: 100vh;
    border-radius: 0;
  }
  .hub-preview-head { padding: 14px 16px 12px; }
  .hub-preview-head h3 { font-size: 17px; }
  .hub-preview-eyebrow { font-size: 10px; }
  .hub-preview-article { padding: 18px 18px 32px; }
  /* Fix-up: the action buttons used to sit side-by-side and the long
     "Looks good — send for review" copy got truncated on narrow phones
     (we measured cut-off at 375px). Stack them vertically with the
     primary action on top so the call-to-action is always reachable
     without horizontal scroll. */
  .hub-preview-foot {
    flex-direction: column; align-items: stretch;
    padding: 12px 16px;
  }
  .hub-preview-foot > p { font-size: 12px; line-height: 1.45; }
  .hub-preview-foot-actions {
    flex-direction: column-reverse;
    align-items: stretch;
    width: 100%;
  }
  .hub-preview-foot-actions .hub-btn {
    width: 100%;
    min-width: 0;        /* allow long copy to wrap rather than overflow */
    white-space: normal;
  }
}

/* ── Branded toast stack ─────────────────────────────────── */
.hub-toast-stack {
  position: fixed; right: 18px; bottom: 18px;
  display: flex; flex-direction: column; gap: 10px;
  z-index: 220;
  pointer-events: none;
  max-width: min(380px, 92vw);
}
.hub-toast {
  background: #0f172a;
  color: #fff;
  border-radius: 14px;
  padding: 12px 16px;
  font-size: 14px; font-weight: 500;
  line-height: 1.45;
  box-shadow: 0 16px 40px -12px rgba(15, 23, 42, .35),
              0 4px 12px -4px rgba(15, 23, 42, .25);
  border-left: 4px solid var(--hub-accent);
  pointer-events: auto;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .25s ease, transform .25s ease;
}
.hub-toast-success { border-left-color: #16a34a; }
.hub-toast-error   { border-left-color: #dc2626; }
.hub-toast-info    { border-left-color: var(--hub-accent); }
.hub-toast-in {
  opacity: 1;
  transform: translateY(0);
}
.hub-toast-out {
  opacity: 0;
  transform: translateY(-6px);
}

/* ── Quill rich editor on the public submit form ─────────── */
.hub-editor-shell {
  background: #fff;
  border: 1px solid var(--hub-border);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 1px 0 rgba(15, 23, 42, .04);
  transition: border-color .15s ease, box-shadow .15s ease;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
}
.hub-editor-shell .ql-container,
.hub-editor-shell .ql-editor {
  max-width: 100% !important;
  min-width: 0;
  box-sizing: border-box;
  overflow-x: hidden;
}
.hub-editor-shell .ql-editor,
.hub-editor-shell .ql-editor * {
  word-break: break-word;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
/* Tables and pre/code can carry hard-wrapped tokens that still escape — */
/* clamp them too so a stray QQQQ… line never pushes the form sideways. */
.hub-editor-shell .ql-editor pre,
.hub-editor-shell .ql-editor table,
.hub-editor-shell .ql-editor code {
  max-width: 100%;
  overflow-x: auto;
  white-space: pre-wrap;
}
.hub-editor-shell:focus-within {
  border-color: var(--hub-accent);
  box-shadow: 0 0 0 3px rgba(0, 114, 188, .12);
}
.hub-editor-toolbar {
  position: sticky; top: 0; z-index: 5;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 4px;
  padding: 8px 10px;
  background: linear-gradient(180deg, #fbfdff, var(--hub-bg-soft));
  border-bottom: 1px solid var(--hub-border);
}
.hub-editor-toolbar.hub-editor-toolbar-error { background: #fff5f5; border-color: #f4c2c2; }
.hub-editor-toolbar .ql-formats {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 0 6px;
  border-right: 1px solid var(--hub-border);
}
.hub-editor-toolbar .ql-formats:last-child { border-right: 0; }
/* `data-group="…"` is now rendered as a (visually) hidden landmark and
   reused only for screen readers — we tried surfacing it as a printed
   caption above each group, but `flex-wrap` causes the captions to
   detach from their group when the toolbar breaks onto a second row.
   The localised `title` on every button already tells the writer what
   the icon does on hover.

   The defensive `::before/::after { content: none }` rules below kill
   any leaked picker/preview pseudo-element a future Quill upgrade
   might surface above the group — we noticed a small floating
   artefact above the heading and font-size pickers in the wild and
   want a hard guarantee that nothing prints there.                   */
.hub-editor-toolbar .ql-formats[data-group] {
  position: relative;
}
.hub-editor-toolbar .ql-formats[data-group]::before,
.hub-editor-toolbar .ql-formats[data-group]::after,
.hub-editor-toolbar .ql-formats > .ql-picker::after,
.hub-editor-toolbar .ql-formats > .ql-picker::before {
  content: none !important;
}
/* Quill's Snow theme renders the picker label's *secondary* `::before`
   when both `data-label` and `data-value` are present, which on first
   paint can show "Normal" stacked above our localised "Style" /
   "Size". Hard-anchor the `::before` to a single absolute slot so
   only the visible label paints in the toolbar.                       */
.hub-editor-toolbar.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.hub-editor-toolbar.ql-snow .ql-picker.ql-size   .ql-picker-label::before,
.hub-editor-toolbar.ql-snow .ql-picker.ql-align  .ql-picker-label::before {
  position: static;
  display: inline;
  height: auto;
  line-height: 30px;
}

/* Picker labels — Quill snow theme prints "Normal" both for the
   heading picker and the size picker, which sat side-by-side and
   read as a confusing "Normal Normal" pair. We replace both labels
   with localised placeholders ("Style" / "Size") via JS, then expose
   them through `data-shelly-label`. The two CSS rules below kill the
   stock `::before { content: "Normal" }` from quill.snow.css and
   substitute our attribute-driven label instead. The picker-options
   list (the dropdown items themselves) keeps Quill's own labels so
   each option still reads "Heading 2 / Heading 3 / Normal", etc. */
.hub-editor-toolbar.ql-snow .ql-picker.ql-header .ql-picker-label[data-shelly-label]::before,
.hub-editor-toolbar.ql-snow .ql-picker.ql-size   .ql-picker-label[data-shelly-label]::before {
  content: attr(data-shelly-label) !important;
}
.hub-editor-toolbar button {
  width: 30px; height: 30px;
  border-radius: 7px;
  border: 0; background: transparent;
  color: var(--hub-fg);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.hub-editor-toolbar button:hover,
.hub-editor-toolbar button:focus-visible,
.hub-editor-toolbar select:hover,
.hub-editor-toolbar .ql-picker-label:hover { background: rgba(0, 114, 188, .08); color: var(--hub-accent); }
.hub-editor-toolbar button.ql-active,
.hub-editor-toolbar .ql-picker-label.ql-active,
.hub-editor-toolbar .ql-picker-item.ql-selected { color: var(--hub-accent) !important; background: rgba(0, 114, 188, .12); }
.hub-editor-toolbar .ql-stroke { stroke: currentColor; }
.hub-editor-toolbar .ql-fill, .hub-editor-toolbar .ql-stroke.ql-fill { fill: currentColor; }
.hub-editor-toolbar .ql-picker-label {
  border: 0; padding: 0 24px 0 8px; height: 30px; line-height: 30px; border-radius: 7px;
}
.hub-editor-toolbar .ql-picker.ql-header,
.hub-editor-toolbar .ql-picker.ql-size,
.hub-editor-toolbar .ql-picker.ql-align { width: auto; min-width: 84px; }
.hub-editor-toolbar .ql-picker.ql-color, .hub-editor-toolbar .ql-picker.ql-background { width: 32px; }
.hub-editor-toolbar .ql-picker-options {
  border: 1px solid var(--hub-border); border-radius: 10px;
  box-shadow: 0 12px 28px -16px rgba(15, 23, 42, .25);
  padding: 6px;
}
/* Lock every button + dropdown trigger to a uniform 30 × 30 box and clamp
 * the icon at 18px so a stray svg from Quill's snow theme can never blow
 * up to its natural size and produce huge black bars in the toolbar. */
.hub-editor-toolbar .ql-formats > button,
.hub-editor-toolbar .ql-formats > .ql-picker {
  width: 30px; height: 30px; min-width: 30px; line-height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
}
.hub-editor-toolbar .ql-formats > .ql-picker.ql-header,
.hub-editor-toolbar .ql-formats > .ql-picker.ql-size,
.hub-editor-toolbar .ql-formats > .ql-picker.ql-align { width: auto; }
.hub-editor-toolbar svg {
  width: 18px !important; height: 18px !important;
  display: block;
}
/* Quill ships a tiny double-chevron SVG inside every picker label that, at
   the 14 × 14 size we used to clamp it to, rendered as a confusing little
   speck above the localised "Heading style" / "Font size" text. On those
   two pickers (which carry a custom `data-shelly-label`) we hide the
   stock SVG and draw a single clean caret with a CSS pseudo-element
   instead. The align / colour / background pickers keep their SVG
   because they actually show meaningful state (current alignment icon
   or active swatch), and the picker dropdown items still get their
   icons too. */
.hub-editor-toolbar.ql-snow .ql-picker.ql-header .ql-picker-label[data-shelly-label] > svg,
.hub-editor-toolbar.ql-snow .ql-picker.ql-size   .ql-picker-label[data-shelly-label] > svg {
  display: none !important;
}
.hub-editor-toolbar.ql-snow .ql-picker.ql-header .ql-picker-label[data-shelly-label],
.hub-editor-toolbar.ql-snow .ql-picker.ql-size   .ql-picker-label[data-shelly-label] {
  position: relative;
  padding-right: 22px;
}
.hub-editor-toolbar.ql-snow .ql-picker.ql-header .ql-picker-label[data-shelly-label]::after,
.hub-editor-toolbar.ql-snow .ql-picker.ql-size   .ql-picker-label[data-shelly-label]::after {
  content: "";
  position: absolute;
  right: 8px;
  top: 50%;
  width: 7px;
  height: 7px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-65%) rotate(45deg);
  opacity: .55;
  pointer-events: none;
}
.hub-editor-toolbar.ql-snow .ql-picker.ql-header.ql-expanded .ql-picker-label[data-shelly-label]::after,
.hub-editor-toolbar.ql-snow .ql-picker.ql-size.ql-expanded   .ql-picker-label[data-shelly-label]::after {
  transform: translateY(-25%) rotate(225deg);
  opacity: .9;
}
.hub-editor-toolbar .ql-picker-label svg {
  width: 14px !important; height: 14px !important;
  position: absolute; right: 4px; top: 50%; margin-top: -7px;
}
.hub-editor-toolbar .ql-picker-options svg {
  width: 16px !important; height: 16px !important;
}

.hub-editor {
  background: #fff;
  border: 0;
  min-height: 320px;
}
.hub-editor .ql-container.ql-snow {
  border: 0;
  font: inherit; min-height: 320px;
}
.hub-editor .ql-editor {
  font-size: 17px; line-height: 1.75; min-height: 320px;
  padding: 22px 26px;
  color: var(--hub-fg);
}
.hub-editor .ql-editor.ql-blank::before {
  color: var(--hub-fg-soft); font-style: normal; left: 26px; right: 26px;
}
.hub-editor .ql-editor h2 {
  font-family: var(--hub-font-h); font-weight: 800; font-size: 26px;
  letter-spacing: -.01em; margin: 22px 0 10px;
}
.hub-editor .ql-editor h3 {
  font-family: var(--hub-font-h); font-weight: 700; font-size: 20px;
  margin: 18px 0 8px;
}
.hub-editor .ql-editor h4 {
  font-family: var(--hub-font-h); font-weight: 600; font-size: 17px;
  text-transform: uppercase; letter-spacing: .05em;
  color: var(--hub-fg-soft);
  margin: 16px 0 6px;
}
.hub-editor .ql-editor blockquote {
  border-left: 4px solid var(--hub-accent);
  padding: 10px 18px; margin: 16px 0;
  background: var(--hub-bg-soft); color: var(--hub-fg);
  font-style: italic;
  border-radius: 0 8px 8px 0;
}
.hub-editor .ql-editor pre.ql-syntax,
.hub-editor .ql-editor pre {
  background: #0f172a; color: #e2e8f0;
  border-radius: 10px; padding: 14px 18px;
  font-size: 13.5px; line-height: 1.55;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  overflow-x: auto;
}
/* Custom Shelly code block — has a header strip with the language label
   and uses highlight.js' atom-one-dark palette inherited from the CDN
   stylesheet loaded on the submit form.

   The generous top/bottom margin (24px each) is intentional: the
   embed is a Quill BlockEmbed, so the paragraphs Quill generates
   above and below cling tightly to the <pre> by default. The extra
   margin gives the writer breathing room and prevents body copy from
   appearing to "stick" to the snippet.                                */
.hub-editor .ql-editor pre.hub-code,
.hub-code {
  position: relative;
  background: #0b1020 !important;
  color: #e2e8f0;
  border-radius: 12px;
  padding: 38px 18px 16px;
  margin: 24px 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 13.5px; line-height: 1.6;
  overflow-x: auto;
  border: 1px solid #1f2a44;
  box-shadow: 0 12px 28px -22px rgba(15, 23, 42, .55);
}
/* If a code block is the very first or very last element inside the
 * editor, Quill's BlockEmbed semantics make it impossible to type
 * "above" or "below" without also breathing room on screen. The
 * sibling-margin rules below open up a clean 24px buffer so the
 * blank paragraph the editor injected actually *looks* like a place
 * the writer can click into.                                          */
.hub-editor .ql-editor pre.hub-code + p,
.hub-editor .ql-editor pre.hub-code + h1,
.hub-editor .ql-editor pre.hub-code + h2,
.hub-editor .ql-editor pre.hub-code + h3,
.hub-editor .ql-editor pre.hub-code + h4,
.hub-editor .ql-editor pre.hub-code + ul,
.hub-editor .ql-editor pre.hub-code + ol,
.hub-editor .ql-editor pre.hub-code + blockquote { margin-top: 8px; }
.hub-editor .ql-editor p + pre.hub-code,
.hub-editor .ql-editor h1 + pre.hub-code,
.hub-editor .ql-editor h2 + pre.hub-code,
.hub-editor .ql-editor h3 + pre.hub-code,
.hub-editor .ql-editor h4 + pre.hub-code,
.hub-editor .ql-editor ul + pre.hub-code,
.hub-editor .ql-editor ol + pre.hub-code,
.hub-editor .ql-editor blockquote + pre.hub-code { margin-top: 24px; }
.hub-editor .ql-editor pre.hub-code::before,
.hub-code::before {
  content: attr(data-lang);
  position: absolute; top: 0; left: 0; right: 0;
  padding: 6px 14px;
  background: linear-gradient(180deg, #131a30, #0d1326);
  border-bottom: 1px solid #1f2a44;
  border-radius: 12px 12px 0 0;
  font-family: var(--hub-font-h);
  font-size: 11px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase;
  color: #94a3b8;
}
.hub-editor .ql-editor pre.hub-code code,
.hub-code code {
  background: transparent !important;
  padding: 0; border: 0; color: inherit;
  font: inherit;
}
.hub-editor .ql-editor img {
  display: block;
  border-radius: 10px;
  max-width: 100% !important;
  width: auto;
  height: auto;
  margin: 12px auto;
  box-shadow: 0 8px 24px -16px rgba(15, 23, 42, .25);
}
.hub-editor .ql-editor iframe {
  display: block;
  width: 100%; max-width: 100%;
  aspect-ratio: 16 / 9; min-height: 240px;
  border: 0; border-radius: 10px; margin: 12px 0;
  background: #0b1220;
}
.hub-editor .ql-editor .ql-size-small  { font-size: 13px; }
.hub-editor .ql-editor .ql-size-large  { font-size: 20px; }
.hub-editor .ql-editor .ql-size-huge   { font-size: 28px; line-height: 1.3; }
.hub-editor .ql-editor .ql-align-center  { text-align: center; }
.hub-editor .ql-editor .ql-align-right   { text-align: right; }
.hub-editor .ql-editor .ql-align-justify { text-align: justify; }

.hub-editor-foot {
  display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap; gap: 8px;
  padding: 8px 14px;
  border-top: 1px solid var(--hub-border);
  background: var(--hub-bg-soft);
  font-size: 12.5px; color: var(--hub-fg-soft);
}
.hub-editor-counter {
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}
.hub-editor-error {
  margin-top: 10px;
  padding: 10px 14px;
  border-radius: 10px;
  border: 1px solid #f4c2c2;
  background: #fff5f5;
  color: #9b1c1c;
  font-size: 14px;
}

/* Tighten the form row that contains the editor (no implicit label gap). */
.hub-form-row-editor { display: block; }
.hub-form-row-editor > span { display: block; margin-bottom: 6px; }

/* ── Hub mobile pass ────────────────────────────────────────────────
 * Polishes the public hub on phones: header collapses gracefully, the
 * submit-form 2-column layout stacks, the editor toolbar wraps, dialogs
 * become full-screen sheets, and the cookie banner doesn't dominate the
 * viewport. Inputs use 16px to keep iOS Safari from auto-zooming. */
@media (max-width: 720px) {
  .hub-header-inner { gap: 8px; padding: 0 14px; }
  .hub-header-actions { gap: 6px; }

  /* Submit page hero stacks tighter */
  .hub-submit-hero { padding: 22px 16px 18px; }
  .hub-submit-hero-title { font-size: clamp(22px, 6vw, 30px); }
  .hub-submit-hero-lede { font-size: 14px; }
  .hub-submit-shell-wide,
  .hub-submit-shell { display: block; }
  .hub-submit-card { margin-bottom: 14px; }
  .hub-submit-card-form { padding: 16px; border-radius: 14px; }
  .hub-submit-card-side { padding: 16px; border-radius: 14px; }

  /* Editor toolbar wraps onto multiple rows on tiny screens */
  .hub-editor-toolbar.ql-toolbar.ql-snow {
    flex-wrap: wrap !important;
    padding: 6px 8px !important;
    gap: 4px;
  }
  .hub-editor-toolbar .ql-formats { margin-right: 6px !important; }
  .hub-editor .ql-editor { min-height: 220px; padding: 12px 14px; }

  /* Cover image dropzone shorter on phone */
  .hub-cover-zone { min-height: 160px; padding: 18px 14px; }

  /* Form action row stacks buttons full-width */
  .hub-form-actions {
    flex-direction: column-reverse;
    align-items: stretch;
    gap: 10px;
  }
  .hub-form-actions .hub-btn { width: 100%; }
  .hub-form-actions-hint { font-size: 12px; text-align: center; }

  /* All inputs/textareas: 16px to dodge the iOS zoom-on-focus */
  .hub-form input,
  .hub-form textarea,
  .hub-form select,
  .hub-modal-input { font-size: 16px; }

  /* Pop-up modals always become full-width sheets */
  .hub-modal { padding: 0; }
  .hub-modal .hub-modal-card:not(.hub-preview-shell) {
    width: 96vw; max-width: 96vw;
    border-radius: 14px;
  }
  .hub-modal-foot { flex-direction: column-reverse; gap: 8px; }
  .hub-modal-foot .hub-btn { width: 100%; }

  /* Article view layout */
  .hub-article-shell { padding: 0 14px; }
  .hub-article-h1 { font-size: clamp(26px, 7vw, 36px); }

  /* Cookie banner: smaller font + stacked buttons */
  .hub-cookie-banner-inner { padding: 14px 16px; gap: 10px; }
  .hub-cookie-banner-actions {
    flex-wrap: wrap;
    width: 100%;
  }
  .hub-cookie-banner-actions .hub-btn { flex: 1 1 calc(50% - 4px); }
}

@media (max-width: 480px) {
  .hub-submit-hero-meta { font-size: 12px; }
  .hub-submission { padding: 12px; }
  .hub-submission-meta { font-size: 11px; gap: 4px; flex-wrap: wrap; }
  .hub-submission-msg-bubble { font-size: 12.5px; }

  /* Editor toolbar: only icon buttons, no labels (already mostly the case) */
  .hub-editor-toolbar.ql-toolbar.ql-snow .ql-picker-label::before {
    font-size: 11px;
  }
}

/* ============================================================
 * Submitter "user area" — sub-navigation, profile, account,
 * stories. Shared layout for `/submit/*` pages once a creator is
 * signed in. Visually anchored on the hub-blue accent and the
 * same card system the public submit form uses, so the user-area
 * feels like a natural extension of the rest of the hub.
 * ============================================================ */

.hub-account-shell {
  padding-top: 18px;
  padding-bottom: 56px;
  display: grid;
  gap: 26px;
  min-width: 0;
  max-width: 860px;
  margin-left: auto;
  margin-right: auto;
}
.hub-account-shell-write {
  padding-bottom: 0;
  gap: 0;
}

/* ── Sub-nav ─────────────────────────────────────────────── */
.hub-account-subnav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  background: linear-gradient(135deg, #f7fbff 0%, #eaf2fb 100%);
  border: 1px solid var(--hub-border);
  border-radius: 18px;
  padding: 12px 14px;
  box-shadow: var(--hub-shadow);
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
}
.hub-account-identity {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 4px 8px 4px 4px;
  border-radius: 999px;
  text-decoration: none;
  color: var(--hub-fg);
  min-width: 0;
}
.hub-account-identity:hover { color: var(--hub-fg); background: rgba(255, 255, 255, .55); }
.hub-account-identity-text {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
  min-width: 0;
}
.hub-account-identity-text strong {
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  max-width: 220px;
}
.hub-account-identity-text .hub-submit-mute {
  font-size: 12px;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  max-width: 220px;
}
.hub-account-avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--hub-accent), var(--hub-accent-d));
  color: #fff;
  font-family: var(--hub-font-h);
  font-weight: 800;
  font-size: 16px;
  flex: 0 0 auto;
  overflow: hidden;
}
.hub-account-avatar-img { padding: 0; background: #fff; }
.hub-account-avatar-img img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}

.hub-account-tabs {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  background: rgba(255, 255, 255, .65);
  border: 1px solid var(--hub-border);
  border-radius: 999px;
  padding: 4px;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
}
.hub-account-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border-radius: 999px;
  font-family: var(--hub-font-h);
  font-weight: 600;
  font-size: 13px;
  color: var(--hub-fg-soft);
  text-decoration: none;
  transition: background .15s ease, color .15s ease, box-shadow .15s ease;
  position: relative;
  white-space: nowrap;
}
.hub-account-tab:hover {
  color: var(--hub-fg);
  background: rgba(56, 153, 210, .07);
}
.hub-account-tab.is-active {
  background: var(--hub-fg);
  color: #fff;
  box-shadow: 0 4px 14px -4px rgba(15, 23, 42, .35);
}
.hub-account-tab.is-active:hover { color: #fff; }
.hub-account-tab svg { display: block; flex: 0 0 auto; }
.hub-account-tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px; height: 18px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--hub-accent);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}
.hub-account-tab.is-active .hub-account-tab-badge {
  background: #fff;
  color: var(--hub-fg);
}

/* ── Page header (h1 + lede) ─────────────────────────────── */
.hub-account-pageheader {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 14px;
  margin-top: 8px;
}
.hub-account-h1 {
  font-family: var(--hub-font-h);
  font-size: clamp(26px, 3.6vw, 36px);
  font-weight: 800;
  letter-spacing: -.02em;
  margin: 0 0 6px;
}
.hub-account-lede {
  margin: 0;
  font-size: 15px;
  color: var(--hub-fg-soft);
  max-width: 640px;
  line-height: 1.55;
}

/* ── Generic card used on profile / account / stories ────── */
.hub-account-card {
  background: #fff;
  border: 1px solid var(--hub-border);
  border-radius: var(--hub-radius-lg);
  padding: 26px 28px;
  box-shadow: var(--hub-shadow);
}
.hub-account-card + .hub-account-card { margin-top: 0; }
.hub-account-section-title {
  font-family: var(--hub-font-h);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--hub-fg-soft);
  margin: 0 0 14px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.hub-account-helper {
  font-size: 12.5px;
  margin: -6px 0 0;
}
.hub-form-row-readonly input[readonly] {
  background: var(--hub-bg-soft);
  color: var(--hub-fg-soft);
  cursor: default;
}

.hub-form-actions-end {
  display: flex;
  justify-content: flex-end;
  margin-top: 12px;
}

/* ── Profile page — avatar block ─────────────────────────── */
.hub-account-card-profile { padding-bottom: 22px; }
.hub-profile-avatar-row {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
  margin-bottom: 24px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--hub-line);
}
.hub-profile-avatar-preview {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--hub-accent), var(--hub-accent-d));
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--hub-font-h);
  font-weight: 800;
  font-size: 36px;
  flex: 0 0 auto;
  overflow: hidden;
  box-shadow: 0 8px 22px -10px rgba(31, 118, 182, .55);
  position: relative;
}
.hub-profile-avatar-preview img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.hub-profile-avatar-fallback {
  position: absolute; inset: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.hub-profile-avatar-actions {
  flex: 1 1 220px;
  min-width: 0;
}
.hub-profile-avatar-actions h3 {
  margin: 0 0 4px;
  font-family: var(--hub-font-h);
  font-weight: 700;
  font-size: 16px;
}
.hub-profile-avatar-actions p { margin: 0 0 12px; }
.hub-profile-avatar-buttons { display: flex; gap: 8px; flex-wrap: wrap; }

/* ── Account page — meta grid + danger zone ─────────────── */
.hub-account-card-meta { padding-bottom: 22px; }
.hub-account-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  margin: 0;
}
.hub-account-meta > div {
  background: var(--hub-bg-soft);
  border-radius: 14px;
  padding: 12px 14px;
}
.hub-account-meta dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--hub-fg-soft);
  font-weight: 700;
  margin: 0 0 4px;
}
.hub-account-meta dd {
  margin: 0;
  font-family: var(--hub-font-h);
  font-weight: 700;
  font-size: 18px;
  color: var(--hub-fg);
}

.hub-account-card-danger {
  border-color: #fecaca;
  background: linear-gradient(180deg, #fff7f7 0%, #fff 60%);
}
.hub-account-section-title-danger {
  color: #b91c1c;
}
.hub-account-section-title-danger svg { color: #b91c1c; }
.hub-account-danger-lede {
  margin: 0 0 14px;
  font-size: 14px;
  color: var(--hub-fg-soft);
  line-height: 1.55;
}
.hub-account-danger-form .hub-form-row input[name="confirm"] {
  font-family: var(--hub-font-h);
  letter-spacing: .15em;
  font-weight: 700;
}
.hub-btn.hub-btn-danger {
  background: #dc2626;
  color: #fff;
  border-color: #dc2626;
}
.hub-btn.hub-btn-danger:hover {
  background: #b91c1c;
  color: #fff;
  border-color: #b91c1c;
}

/* ── Stories page — stat cards + filters + list ─────────── */
.hub-stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}
.hub-stat-card {
  display: block;
  background: #fff;
  border: 1px solid var(--hub-border);
  border-radius: 18px;
  padding: 18px 20px;
  text-decoration: none;
  color: var(--hub-fg);
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
  position: relative;
  overflow: hidden;
}
.hub-stat-card::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 4px;
  background: var(--hub-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .2s ease;
}
.hub-stat-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--hub-shadow-lg);
  border-color: rgba(56, 153, 210, .35);
  color: var(--hub-fg);
}
.hub-stat-card:hover::after,
.hub-stat-card.is-active::after { transform: scaleX(1); }
.hub-stat-card.is-active {
  border-color: var(--hub-accent);
  box-shadow: var(--hub-shadow-lg);
}
.hub-stat-card-num {
  font-family: var(--hub-font-h);
  font-size: 32px;
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1;
}
.hub-stat-card-label {
  margin-top: 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--hub-fg-soft);
}
.hub-stat-card-approved::after { background: var(--hub-success); }
.hub-stat-card-pending::after  { background: #f59e0b; }
.hub-stat-card-rejected::after { background: #dc2626; }

.hub-stories-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: #fff;
  border: 1px solid var(--hub-border);
  border-radius: 18px;
  padding: 10px 12px;
  box-shadow: var(--hub-shadow);
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
}
.hub-stories-filters {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  background: var(--hub-bg-soft);
  border-radius: 999px;
  padding: 4px;
}
.hub-stories-filter {
  border: 0;
  background: transparent;
  padding: 7px 14px;
  border-radius: 999px;
  font-family: var(--hub-font-h);
  font-weight: 600;
  font-size: 13px;
  color: var(--hub-fg-soft);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.hub-stories-filter:hover { color: var(--hub-fg); }
.hub-stories-filter.is-active {
  background: #fff;
  color: var(--hub-fg);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .12);
}
.hub-stories-search {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex: 1 1 240px;
  max-width: 360px;
}
.hub-stories-search svg {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--hub-fg-soft);
  pointer-events: none;
}
.hub-stories-search input {
  width: 100%;
  border: 1px solid var(--hub-border);
  border-radius: 999px;
  padding: 10px 14px 10px 38px;
  font: inherit;
  background: #fff;
  color: var(--hub-fg);
}
.hub-stories-search input:focus {
  outline: none;
  border-color: var(--hub-accent);
  box-shadow: 0 0 0 4px rgba(56, 153, 210, .15);
}

.hub-stories-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}
.hub-story-card {
  display: flex;
  background: #fff;
  border: 1px solid var(--hub-border);
  border-radius: 18px;
  overflow: hidden;
  box-shadow: var(--hub-shadow);
  transition: transform .15s ease, box-shadow .15s ease;
}
.hub-story-card:hover {
  transform: translateY(-1px);
  box-shadow: var(--hub-shadow-lg);
}
.hub-story-card-stripe {
  width: 6px;
  flex: 0 0 6px;
  background: var(--hub-accent);
}
.hub-story-card-pending .hub-story-card-stripe   { background: #f59e0b; }
.hub-story-card-in-review .hub-story-card-stripe { background: #f59e0b; }
.hub-story-card-approved .hub-story-card-stripe  { background: var(--hub-success); }
.hub-story-card-rejected .hub-story-card-stripe  { background: #dc2626; }
.hub-story-card-body {
  padding: 16px 20px;
  flex: 1;
  min-width: 0;
}
.hub-story-card-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
}
.hub-story-card-status {
  display: inline-block;
  font-family: var(--hub-font-h);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--hub-bg-soft-2);
  color: var(--hub-accent-d);
  margin-bottom: 6px;
}
.hub-story-card-status-approved { background: rgba(52, 168, 83, .15); color: #15803d; }
.hub-story-card-status-rejected { background: rgba(220, 38, 38, .12); color: #b91c1c; }
.hub-story-card-status-pending,
.hub-story-card-status-in-review { background: rgba(245, 158, 11, .15); color: #b45309; }
.hub-story-card-status-editing-allowed { background: rgba(124, 58, 237, .12); color: #6d28d9; }
.hub-story-card-title {
  margin: 0;
  font-family: var(--hub-font-h);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.005em;
  line-height: 1.3;
}
.hub-story-card-meta {
  font-size: 12px;
  color: var(--hub-fg-soft);
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
}
.hub-story-card-quote {
  margin: 12px 0 0;
  padding: 10px 14px;
  border-left: 3px solid var(--hub-accent);
  background: var(--hub-bg-soft);
  border-radius: 0 10px 10px 0;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--hub-fg-soft);
}
.hub-story-card-quote strong { color: var(--hub-fg); margin-right: 4px; }

/* Reply / Request-changes controls under each story card.
   Built on <details> so they collapse to a single chip until needed. */
.hub-story-card-actions {
  display: flex; flex-wrap: wrap; gap: 10px;
  align-items: center; margin-top: 12px;
}
.hub-story-card-reply {
  flex: 1 1 220px;
}
.hub-story-card-reply summary {
  cursor: pointer; font-size: 13px; font-weight: 600;
  color: var(--hub-accent); padding: 8px 12px;
  border: 1px solid var(--hub-border); border-radius: 999px;
  background: #fff; user-select: none; list-style: none;
  display: inline-flex; align-items: center; gap: 6px;
}
.hub-story-card-reply summary::-webkit-details-marker { display:none; }
.hub-story-card-reply summary::before {
  content: ""; width: 14px; height: 14px;
  background: currentColor; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z'/></svg>") center/contain no-repeat;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z'/></svg>") center/contain no-repeat;
}
.hub-story-card-reply form {
  margin-top: 8px;
  background: var(--hub-bg-soft);
  padding: 10px;
  border-radius: 10px;
  border: 1px solid var(--hub-border);
}
.hub-story-card-reply textarea {
  width: 100%; min-height: 60px;
  padding: 8px 10px;
  border: 1px solid var(--hub-border);
  border-radius: 8px;
  font: inherit; font-size: 13px;
  resize: vertical;
}
.hub-story-card-reply form button {
  margin-top: 8px;
}
.hub-story-card-revise summary {
  border-color: #fcd34d; color: #92400e; background: #fffbeb;
}
.hub-story-card-revise-help {
  margin: 0 0 8px;
  font-size: 12px;
  color: var(--hub-fg-soft);
}
.hub-btn-sm {
  font-size: 13px;
  padding: 7px 14px;
}

.hub-stories-empty {
  display: grid;
  gap: 10px;
  place-items: center;
  text-align: center;
  padding: 36px 20px;
  border: 1px dashed var(--hub-border);
  border-radius: 18px;
  background: var(--hub-bg-soft);
  color: var(--hub-fg-soft);
}
.hub-stories-empty span { font-size: 36px; }
.hub-stories-empty p { margin: 0; max-width: 420px; }

/* ── Mobile: user-area (account shell, stories, profile) ───
   Every element is constrained with min-width:0/max-width:100%
   so nothing can push the page wider than the viewport. The tabs
   scroll horizontally inside their box; stat cards wrap 2×2;
   the toolbar stacks; and long text truncates or wraps. */
@media (max-width: 768px) {
  .hub-account-shell { gap: 16px; min-width: 0; }

  /* Sub-nav: stacks vertically, both identity and tabs stretch full width */
  .hub-account-subnav {
    flex-direction: column;
    align-items: stretch;
    padding: 12px;
    border-radius: 14px;
    min-width: 0;
  }
  .hub-account-identity { gap: 10px; min-width: 0; }
  .hub-account-identity-text { min-width: 0; }
  .hub-account-identity-text strong {
    max-width: 100%; font-size: 14px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .hub-account-identity-text .hub-submit-mute {
    max-width: 100%; font-size: 12px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .hub-account-avatar { width: 34px; height: 34px; font-size: 14px; }

  /* Tabs: horizontal scroll inside the subnav — NEVER wider than the parent */
  .hub-account-tabs {
    display: flex;
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    border-radius: 12px;
    flex-wrap: nowrap;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .hub-account-tabs::-webkit-scrollbar { display: none; }
  .hub-account-tab {
    font-size: 12px; padding: 7px 10px;
    flex: 0 0 auto; gap: 4px;
  }
  .hub-account-tab svg { width: 13px; height: 13px; }

  /* Page header: stack title above CTA */
  .hub-account-h1 { font-size: 24px; }
  .hub-account-lede { font-size: 14px; }
  .hub-account-pageheader {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    margin-top: 4px;
  }
  .hub-account-pageheader > a.hub-btn,
  .hub-account-pageheader .hub-btn-lg { align-self: flex-start; }
  .hub-account-card { padding: 20px 16px; border-radius: 14px; min-width: 0; }
  .hub-profile-avatar-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
  }

  /* Stat cards: 2×2 with min-width 0 so columns share space equally */
  .hub-stat-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    max-width: 100%;
  }
  .hub-stat-card {
    padding: 14px 12px; border-radius: 14px;
    min-width: 0;
  }
  .hub-stat-card-num { font-size: 24px; }
  .hub-stat-card-label {
    font-size: 9px; letter-spacing: .04em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  /* Stories toolbar: stack vertically */
  .hub-stories-toolbar {
    flex-direction: column;
    align-items: stretch;
    padding: 10px;
    border-radius: 14px;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
  }
  /* Filter chips: horizontal scroll — NEVER wider than the toolbar */
  .hub-stories-filters {
    display: flex;
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    flex-wrap: nowrap;
    -webkit-overflow-scrolling: touch;
    border-radius: 12px;
    scrollbar-width: none;
  }
  .hub-stories-filters::-webkit-scrollbar { display: none; }
  .hub-stories-filter {
    white-space: nowrap; font-size: 12px; padding: 6px 12px;
    flex: 0 0 auto;
  }
  .hub-stories-search { max-width: 100%; flex: 1 1 auto; min-width: 0; }
  .hub-stories-search input { font-size: 16px; padding: 10px 14px 10px 36px; width: 100%; }

  /* Story cards */
  .hub-story-card { border-radius: 14px; min-width: 0; max-width: 100%; }
  .hub-story-card-body { padding: 14px 14px; min-width: 0; }
  .hub-story-card-title { font-size: 15px; }
  .hub-story-card-meta { font-size: 11px; }
  .hub-story-card-quote { font-size: 13px; padding: 8px 12px; }
  .hub-story-card-actions { gap: 8px; margin-top: 10px; flex-wrap: wrap; }
  .hub-story-card-reply { flex: 1 1 100%; }
  .hub-story-card-reply summary { font-size: 12px; padding: 6px 10px; }
  .hub-story-card-reply textarea { font-size: 16px; }
  .hub-stories-empty { padding: 28px 16px; }
}

/* ── Extra-small phones (≤ 390px) — iPhone SE / mini ─────── */
@media (max-width: 390px) {
  .hub-container { padding: 0 12px; }
  .hub-header-inner { padding: 14px 12px; gap: 8px; }
  .hub-brand-mark { height: 22px; }
  .hub-bell, .hub-header-avatar, .hub-menu-toggle {
    width: 34px; height: 34px;
  }
  .hub-account-subnav { padding: 10px; }
  .hub-account-tab { font-size: 11px; padding: 6px 10px; }
  .hub-stat-card { padding: 12px 10px; }
  .hub-stat-card-num { font-size: 20px; }
  .hub-submit-card { padding: 18px 14px; }
  .hub-hero-title { font-size: 22px; }
  .hub-article-title { font-size: 24px; }
}

