/* Hugin — persistent left sidebar shell.
   Mounted on app/library/account/billing for signed-in users via
   sidebar.js. Landing keeps its own lp-topbar (marketing context).
   Width: 240px desktop, slides off-screen on mobile behind hamburger. */

:root {
  --sidebar-w: 240px;
}

/* Sidebar is fixed-position; the rest of the body simply shifts
   right by the sidebar width. Avoids grid-template-areas pain
   across heterogeneous page structures (skip-link, topbar, main,
   footer, template — all sit at body level). */
body[data-sidebar="on"] {
  padding-inline-start: var(--sidebar-w);
}

/* Hide the legacy topbar — its responsibilities (brand, nav, theme
   toggle, user menu) move into the sidebar shell. Keep it in the
   DOM so topbar.js still resolves /api/me and dispatches
   `hugin:session` for sidebar.js to consume. */
body[data-sidebar="on"] > .topbar {
  display: none;
}

.sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  width: var(--sidebar-w);
  display: flex;
  flex-direction: column;
  background: var(--bg-deep);
  border-inline-end: 1px solid var(--line);
  padding: var(--s-5) var(--s-4);
  overflow-y: auto;
  z-index: 50;
}

/* Brand */
.sidebar-brand {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding-block-end: var(--s-6);
  color: var(--ink);
}
.sidebar-brand-mark {
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
}
.sidebar-brand-word {
  font-family: var(--font-display);
  font-size: var(--fs-20);
  font-weight: 500;
  letter-spacing: -0.01em;
}

/* Primary nav */
.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sidebar-link {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  color: var(--ink-mute);
  font-size: var(--fs-14);
  transition: color 120ms ease, background 120ms ease;
  position: relative;
}
.sidebar-link:hover {
  color: var(--ink);
  background: var(--bg-elev-2);
}
.sidebar-link[aria-current="page"] {
  color: var(--accent);
  background: var(--accent-soft);
}
.sidebar-link[aria-current="page"]::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--s-4));
  inset-block: 4px;
  width: 2px;
  background: var(--accent);
  border-radius: 1px;
}
.sidebar-link-icon {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
}
.sidebar-link-count {
  margin-inline-start: auto;
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  color: var(--ink-dim);
}
.sidebar-collections {
  display: grid;
  gap: 2px;
}
.sidebar-collection-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 24px;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  color: var(--ink-mute);
  font-size: var(--fs-14);
  position: relative;
  overflow: hidden;
  transition: color 120ms ease, background 120ms ease;
}
.sidebar-collection-row:hover {
  color: var(--ink);
  background: var(--bg-elev-2);
}
.sidebar-collection-row.is-active {
  color: var(--accent);
  background: var(--accent-soft);
}
.sidebar-collection-row.is-active::before {
  content: "";
  position: absolute;
  left: 0;
  inset-block: 4px;
  width: 2px;
  background: var(--accent);
  border-radius: 1px;
}
.sidebar-collection-link {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  color: inherit;
}
.sidebar-collection-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar-collection-delete {
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--status-failed);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transform: translateX(8px);
  transform-origin: center;
  transition: opacity 150ms ease, transform 180ms ease, color 120ms ease, visibility 0s linear;
  transition-delay: 0s, 0s, 0s, 0s;
}
.sidebar-collection-delete svg {
  transform-origin: center;
  transition: transform 90ms ease;
}
.sidebar-collection-row:hover .sidebar-collection-delete,
.sidebar-collection-row:focus-within .sidebar-collection-delete {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transform: translateX(0);
  transition-delay: 420ms, 420ms, 0s, 420ms;
}
.sidebar-collection-delete:hover {
  color: color-mix(in oklab, var(--status-failed) 82%, var(--ink));
  transition-delay: 0s, 0s, 0s, 0s;
}
.sidebar-collection-delete svg:hover {
  transform: rotate(-8deg);
}
.sidebar-collection-delete:focus-visible {
  outline: 2px solid var(--status-failed);
  outline-offset: 2px;
}
.sidebar-collection-delete:disabled {
  opacity: 0.5;
  cursor: progress;
}
@media (hover: none) {
  .sidebar-collection-delete {
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
    transform: none;
    transition-delay: 0s;
  }
}
.sidebar-collections-empty {
  margin: 0;
  padding: var(--s-2) var(--s-3);
  color: var(--ink-dim);
  font-size: var(--fs-13);
}
.sidebar-collection-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 28px;
  gap: var(--s-2);
  margin-block-start: var(--s-2);
}
.sidebar-collection-form input {
  min-width: 0;
  height: 28px;
  padding: 0 var(--s-2);
  color: var(--ink);
  background: var(--bg-inset);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  font: inherit;
  font-size: var(--fs-13);
}
.sidebar-collection-form input::placeholder {
  color: var(--ink-faint);
}
.sidebar-collection-form input:focus-visible {
  outline: 1px solid var(--accent-line);
  outline-offset: 2px;
}
.sidebar-collection-form button {
  height: 28px;
  color: var(--accent);
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  cursor: pointer;
}
.sidebar-collection-form button:hover {
  color: var(--ink);
  background: var(--bg-elev-2);
}
.sidebar-collection-form button:disabled {
  opacity: 0.5;
  cursor: progress;
}
.sidebar-collection-error {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--status-failed);
  font-size: var(--fs-12);
}
.sidebar-collection-error[hidden] {
  display: none;
}
.sidebar-confirm {
  position: fixed;
  inset: 0;
  z-index: 320;
  display: grid;
  place-items: center;
  padding: var(--s-4);
}
.sidebar-confirm[hidden] {
  display: none;
}
.sidebar-confirm-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
}
.sidebar-confirm-panel {
  position: relative;
  width: min(100%, 420px);
  padding: var(--s-6);
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-3);
}
.sidebar-confirm-eyebrow {
  margin: 0 0 var(--s-2);
  color: var(--ink-dim);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.sidebar-confirm-panel h2 {
  margin: 0 0 var(--s-3);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--fs-24);
  font-weight: 500;
}
.sidebar-confirm-copy {
  margin: 0;
  color: var(--ink-mute);
  line-height: 1.55;
}
.sidebar-confirm-copy strong {
  color: var(--ink);
  font-weight: 600;
}
.sidebar-confirm-error {
  margin: var(--s-3) 0 0;
  color: var(--status-failed);
  font-size: var(--fs-13);
}
.sidebar-confirm-error[hidden] {
  display: none;
}
.sidebar-confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--s-3);
  margin-block-start: var(--s-5);
}
.sidebar-confirm-cancel,
.sidebar-confirm-delete {
  padding: 9px 16px;
  border-radius: var(--r-sm);
  font: inherit;
  font-size: var(--fs-13);
  cursor: pointer;
}
.sidebar-confirm-cancel {
  color: var(--ink);
  background: var(--bg-elev);
  border: 1px solid var(--line-strong);
}
.sidebar-confirm-cancel:hover {
  background: var(--bg-elev-2);
}
.sidebar-confirm-delete {
  color: var(--bg);
  background: var(--status-failed);
  border: 1px solid var(--status-failed);
}
.sidebar-confirm-delete:hover {
  opacity: 0.9;
}
.sidebar-confirm-delete:disabled {
  opacity: 0.5;
  cursor: progress;
}
.sidebar-confirm-cancel:focus-visible,
.sidebar-confirm-delete:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Section eyebrow */
.sidebar-section {
  margin-block-start: var(--s-5);
  padding-inline-start: var(--s-3);
  padding-block-end: var(--s-2);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* Bottom group: Account/Settings + Quill meter */
.sidebar-foot {
  margin-block-start: auto;
  padding-block-start: var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

/* ============================================================
   QUILL meter — charcoal candles, warm only at the flame tip.
   The wax body stays neutral charcoal across all states; the
   small flame sits on top of lit candles as the only warm point.
   No glow halo around the candles — that orange wash competed
   with the lantern, which is where the warm light belongs.
   ============================================================ */
.quill-meter {
  background: var(--bg-inset);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--s-4) var(--s-3) var(--s-3);
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
/* Sidebar tooltips anchor at the trigger's left edge (no centering
   transform) so they grow into the main content area instead of past
   the document's left margin, where the centered default would have
   them spawn a horizontal viewport scrollbar. */
.sidebar [data-tooltip]:hover::after,
.sidebar [data-tooltip]:focus-visible::after {
  inset-inline-start: 0;
  animation-name: sidebar-tooltip-rise;
}
@keyframes sidebar-tooltip-rise {
  from { opacity: 0; transform: translateY(2px); }
  to   { opacity: 1; transform: translateY(0); }
}
.quill-meter-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.quill-meter-value {
  color: var(--ink);
  font-weight: 600;
  letter-spacing: 0.06em;
}
.quill-candles {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 3px;
  align-items: end;
  height: 26px;
}
.quill-candle {
  position: relative;
  background: #22201D; /* charcoal wax — neutral, no warm tint */
  border-radius: 1px;
  height: 100%;
  overflow: visible;
}
.quill-candle[data-lit="true"] {
  background: #2A2724; /* one notch lifted so lit reads as "fresh wax" */
}
.quill-candle[data-lit="spent"] {
  background: #1A1916;
  opacity: 0.55;
}

/* Larger meter for the /account + /billing surfaces — the same candles lit
   bigger, never a different metaphor. Lit = remaining quota, as in the sidebar. */
.quill-candles--lg {
  height: 40px;
  gap: 5px;
  max-inline-size: 360px;
}
.quill-candles--lg .quill-candle { border-radius: 2px; }
.quill-candles--lg .quill-flame {
  width: 13px;
  height: 20px;
  margin-left: -6.5px;
}

/* Defs-only SVG that hosts the shared flame gradients. It sits inside
   the candles grid for DOM proximity but must not occupy a grid slot,
   or the first candle gets bumped a column. Pulled out of flow. */
.quill-flame-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Flame — four-layer SVG that mirrors the lantern's structure (halo,
   outer body with radial gradient, pale inner core, blue base point at
   the wick). Each candle in the row offsets its animation delays by
   --candle-phase so the dozen flames never wobble in unison. */
.quill-flame {
  position: absolute;
  bottom: 100%;
  left: 50%;
  width: 9px;
  height: 14px;
  margin-left: -4.5px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 240ms ease;
  overflow: visible;
}
.quill-candle[data-lit="true"] .quill-flame { opacity: 1; }
.quill-candle[data-lit="spent"] .quill-flame { display: none; }

.qflame-halo,
.qflame-outer,
.qflame-inner,
.qflame-base {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  will-change: transform, opacity;
}

.quill-candle[data-lit="true"] .qflame-halo {
  animation: qf-halo 3.7s ease-in-out infinite;
  animation-delay: calc(var(--candle-phase, 0) * -0.31s);
}
.quill-candle[data-lit="true"] .qflame-outer {
  animation:
    qf-outer-sway 2.3s ease-in-out infinite,
    qf-outer-breath 3.1s ease-in-out infinite;
  animation-delay:
    calc(var(--candle-phase, 0) * -0.19s),
    calc(var(--candle-phase, 0) * -0.26s);
}
.quill-candle[data-lit="true"] .qflame-inner {
  animation:
    qf-inner-sway 1.9s ease-in-out infinite,
    qf-inner-flicker 0.46s steps(1, end) infinite;
  animation-delay:
    calc(var(--candle-phase, 0) * -0.16s),
    calc(var(--candle-phase, 0) * -0.04s);
}
.quill-candle[data-lit="true"] .qflame-base {
  animation: qf-base-pulse 0.74s ease-in-out infinite;
  animation-delay: calc(var(--candle-phase, 0) * -0.07s);
}

@keyframes qf-halo {
  0%, 100% { opacity: 0.65; transform: scale(1); }
  45%      { opacity: 1;    transform: scale(1.14); }
}
@keyframes qf-outer-sway {
  0%   { transform: rotate(-1.6deg) scaleY(1); }
  35%  { transform: rotate(2deg)    scaleY(1.05); }
  62%  { transform: rotate(-0.7deg) scaleY(0.96); }
  100% { transform: rotate(-1.6deg) scaleY(1); }
}
@keyframes qf-outer-breath {
  0%, 100% { opacity: 0.95; }
  30%      { opacity: 0.74; }
  60%      { opacity: 1; }
}
@keyframes qf-inner-sway {
  0%   { transform: rotate(2.2deg)  scaleY(0.94); }
  42%  { transform: rotate(-1.8deg) scaleY(1.08); }
  100% { transform: rotate(2.2deg)  scaleY(0.94); }
}
@keyframes qf-inner-flicker {
  0%, 100% { opacity: 0.88; }
  50%      { opacity: 0.7; }
}
@keyframes qf-base-pulse {
  0%, 100% { opacity: 0.4; }
  50%      { opacity: 0.7; }
}

@media (prefers-reduced-motion: reduce) {
  .quill-candle[data-lit="true"] .qflame-halo,
  .quill-candle[data-lit="true"] .qflame-outer,
  .quill-candle[data-lit="true"] .qflame-inner,
  .quill-candle[data-lit="true"] .qflame-base { animation: none; }
}
.quill-meter-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.quill-tier {
  color: var(--ink-mute);
}

/* User chip + theme toggle row, sits above the quill meter. */
.sidebar-user {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2);
  border-radius: var(--r-sm);
  background: var(--bg-elev-2);
}
.sidebar-user-initials {
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  border-radius: var(--r-full);
  background: var(--accent);
  color: var(--accent-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
}
.sidebar-user-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fs-13);
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar-user-action {
  background: transparent;
  border: none;
  color: var(--ink-mute);
  padding: 4px;
  cursor: pointer;
  border-radius: var(--r-xs);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.sidebar-user-action:hover { color: var(--ink); background: var(--bg-elev); }

/* ============================================================
   Top mini-bar that sits next to the main pane — breadcrumb +
   user chip. Replaces the old standalone topbar on app pages.
   ============================================================ */
.app-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s-4) var(--s-6);
  border-block-end: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: var(--fs-13);
  letter-spacing: 0.04em;
  color: var(--ink-mute);
}
.app-bar-crumb { display: flex; gap: var(--s-2); align-items: center; }
.app-bar-actions { display: flex; gap: var(--s-3); align-items: center; }

/* ============================================================
   Mobile — sidebar slides off-screen, hamburger button reveals it.
   The button is a 44×44 chip with a cave-tinted dark wash + backdrop
   blur so it stays legible over parchment, hero photography, and the
   library grid alike. Bars morph into an X when the drawer is open.
   ============================================================ */
.sidebar-hamburger {
  display: none;
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  right: calc(env(safe-area-inset-right, 0px) + 10px);
  z-index: 201;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: color-mix(in oklab, var(--bg-deep) 78%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--ink);
  cursor: pointer;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 0 rgba(255,255,255,0.04) inset, 0 4px 14px rgba(0,0,0,0.28);
  --ham-scale: 1;
  transform: scale(var(--ham-scale));
  transition:
    transform 120ms ease,
    border-color 160ms ease,
    background 160ms ease;
}
.sidebar-hamburger:hover {
  border-color: color-mix(in oklab, var(--line) 60%, var(--ink-mute));
  background: color-mix(in oklab, var(--bg-deep) 88%, transparent);
}
.sidebar-hamburger:active { --ham-scale: 0.96; }
.sidebar-hamburger:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Open state — warm ember tint signals "tap to close". The button
   stays anchored top-right; only the bars morph into an X. */
.sidebar-hamburger[aria-expanded="true"] {
  border-color: color-mix(in oklab, var(--accent) 55%, var(--line));
  background: color-mix(in oklab, var(--accent-soft) 70%, var(--bg-deep));
  color: var(--accent);
}

/* Three-bar stack that morphs into an X when [aria-expanded="true"]. */
.sidebar-hamburger-bars {
  position: relative;
  display: inline-block;
  width: 18px;
  height: 14px;
}
.sidebar-hamburger-bars > span {
  position: absolute;
  left: 0;
  right: 0;
  height: 1.8px;
  background: currentColor;
  border-radius: 1px;
  transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1),
              opacity 160ms ease,
              top 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
.sidebar-hamburger-bars > span:nth-child(1) { top: 0; }
.sidebar-hamburger-bars > span:nth-child(2) { top: 6px; }
.sidebar-hamburger-bars > span:nth-child(3) { top: 12px; }

.sidebar-hamburger[aria-expanded="true"] .sidebar-hamburger-bars > span:nth-child(1) {
  top: 6px;
  transform: rotate(45deg);
}
.sidebar-hamburger[aria-expanded="true"] .sidebar-hamburger-bars > span:nth-child(2) {
  opacity: 0;
  transform: scaleX(0.4);
}
.sidebar-hamburger[aria-expanded="true"] .sidebar-hamburger-bars > span:nth-child(3) {
  top: 6px;
  transform: rotate(-45deg);
}

@media (prefers-reduced-motion: reduce) {
  .sidebar-hamburger,
  .sidebar-hamburger-bars > span { transition: none; }
}

@media (max-width: 860px) {
  body[data-sidebar="on"] {
    padding-inline-start: 0;
  }
  .sidebar {
    transform: translateX(-100%);
    transition: transform 240ms cubic-bezier(0.32, 0.72, 0.2, 1);
    z-index: 200;
    box-shadow: 14px 0 28px rgba(0,0,0,0.45);
    will-change: transform;
  }
  body[data-sidebar-open="true"] .sidebar {
    transform: translateX(0);
  }
  .sidebar-hamburger { display: inline-flex; }

  /* Backdrop when open — soft ink wash with a faint blur so the
     reading surface behind it stays present but recedes. Fades in
     to avoid a hard flash on tap. */
  body[data-sidebar-open="true"]::before {
    content: "";
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    z-index: 199;
    animation: sidebar-backdrop-in 200ms ease both;
  }
  @keyframes sidebar-backdrop-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  /* Lock page scroll while the drawer is open. position:fixed on the
     main scroll container is the iOS-safe way to do it — overflow:hidden
     on body causes a layout shift on Chrome mobile when the implicit
     scrollbar gutter disappears, and CLS picks it up. */
  body[data-sidebar-open="true"] main,
  body[data-sidebar-open="true"] .topbar { touch-action: none; }
}
