/* Dandelion demo: styles.
 *
 * CANONICAL SOURCE: longhand-site/demo/demo.css (copy in "AutoOutreach 2/demo/")
 *
 * Self-contained on purpose. Everything is scoped under .demo-root and
 * every token has a literal fallback, because the two hosts define
 * different variables: the site's styles.css and the extension's
 * sidepanel.css share brand values but not variable names. Scoping also
 * means neither host's existing rules can leak in and shift the demo.
 */

.demo-root {
  --d-ink-900: var(--ink-900, #0e2a26);
  --d-paper: var(--paper, #fffafb);
  --d-paper-card: var(--paper-card, #fbf7f3);
  --d-paper-dim: var(--paper-dim, #f6f1ec);
  --d-hairline: var(--hairline, #e2ddd7);
  --d-ink-300: var(--ink-300, #a9b8b2);
  --d-ink-500: var(--ink-500, #5c716a);
  --d-ink-700: var(--ink-700, #33473f);
  --d-teal-strong: var(--teal-strong, #1f6b5c);
  --d-mint: var(--mint, #7de2d1);

  --d-fill-1: rgba(255, 255, 255, 0.045);
  --d-fill-2: rgba(255, 255, 255, 0.07);
  --d-fill-3: rgba(255, 255, 255, 0.10);
  --d-edge: rgba(255, 255, 255, 0.09);

  position: relative;
  isolation: isolate;
}

/* ---------- reveal ---------- */

.demo-root .demo-reveal:not(.is-revealed) { display: none; }

@keyframes demo-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.demo-root .demo-reveal.is-revealed {
  animation: demo-in 260ms ease-out both;
}

/* ---------- browser frame (wide variant) ---------- */

.demo-root .browser-frame {
  /* The two chrome rows, 38px of tab strip plus a 44px toolbar. Declared here
     because the docked panel has to start below them, and when this was a
     hardcoded 49px in two places the panel sat over the toolbar the moment the
     chrome grew a second row. */
  --d-chrome-h: 82px;
  position: relative;
  background: var(--d-paper-card);
  border: 1px solid var(--d-hairline);
  /* A macOS window corner, not a card corner. The frame is pretending to be
     a window now, and 18px read as a UI card. */
  border-radius: 11px;
  overflow: hidden;
  /* Capped against the viewport so the playback controls and caption sit
     above the fold on a laptop. A demo whose Play button you have to
     scroll to find is a video you can't start. */
  height: min(72vh, 660px);
}
/* ---------- browser chrome ----------

   Deliberately NOT themed from the demo's design tokens. Real browser chrome
   belongs to the operating system, not to the page inside it, and the visible
   seam between the two is exactly what makes a screenshot read as "a website,
   in a browser" instead of "a drawing of a website". These are Chrome's own
   dark-theme greys, hardcoded for that reason.

   Chrome's own UI font is the system stack, and it is not the demo's body
   face, so it is set here too. */
.demo-root .browser-chrome {
  --c-strip: #1c1c1e;
  --c-surface: #2b2b2e;
  --c-omnibox: #3a3a3e;
  --c-icon: #c4c7c5;
  --c-text: #e8eaed;
  --c-text-dim: #9aa0a6;
  background: var(--c-strip);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  user-select: none;
}

/* --- row 1: tab strip --- */
.demo-root .chrome-tabstrip {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 38px;
  box-sizing: border-box;
  padding: 0 8px;
}
.demo-root .chrome-traffic {
  display: flex;
  gap: 8px;
  align-items: center;
  height: 100%;
  padding: 0 10px 0 4px;
}
.demo-root .chrome-light {
  width: 12px; height: 12px;
  border-radius: 50%;
}
/* The real macOS window controls. Grey circles were the clearest single tell
   that this frame was drawn rather than screenshotted. */
.demo-root .chrome-light-close { background: #ff5f57; }
.demo-root .chrome-light-min   { background: #febc2e; }
.demo-root .chrome-light-max   { background: #28c840; }

.demo-root .demo-tabs {
  display: flex;
  align-items: flex-end;
  gap: 1px;
  height: 100%;
}

/* --- row 2: toolbar --- */
.demo-root .chrome-toolbar {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 44px;
  box-sizing: border-box;
  padding: 0 10px;
  background: var(--c-surface);
}
.demo-root .chrome-nav,
.demo-root .chrome-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}
.demo-root .chrome-btn,
.demo-root .chrome-newtab,
.demo-root .chrome-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  border-radius: 50%;
  color: var(--c-icon);
  flex: none;
}
/* Forward is greyed out on a page you arrived at directly, which is the state
   this demo is always in. */
.demo-root .chrome-btn.is-dim { color: #5f6368; }
.demo-root .chrome-newtab { color: var(--c-text-dim); margin-left: 4px; margin-bottom: 5px; }
.demo-root .chrome-avatar {
  color: var(--c-text-dim);
  background: #3c4043;
  width: 24px; height: 24px;
  margin: 0 4px;
}

/* --- the omnibox --- */
.demo-root .address-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  height: 28px;
  box-sizing: border-box;
  margin: 0 6px;
  padding: 0 10px 0 12px;
  background: var(--c-omnibox);
  border-radius: 999px;
  font-size: 0.72rem;
  color: var(--c-text);
}
.demo-root .address-lead,
.demo-root .address-star {
  display: inline-flex;
  align-items: center;
  color: var(--c-icon);
  flex: none;
}
.demo-root .address-star { margin-left: auto; }
.demo-root .address-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  letter-spacing: 0.005em;
}
.demo-root .browser-page {
  padding: 24px;
  /* Clears the docked panel. Percentage rather than a fixed 260px so the
     text column stays put as the panel width flexes. */
  padding-right: 38%;
  display: grid;
  gap: 12px;
  align-content: start;
}
.demo-root .page-crumb {
  font-size: 0.78rem;
  color: var(--d-teal-strong);
  margin: 0 0 8px;
}
.demo-root .page-heading {
  /* Neutral serifs on purpose, not the site's display face: these belong
     to the prospect's own website, and set in Fraunces the mock read as
     another slice of our page instead of somebody else's. */
  font-family: ui-serif, Georgia, "Times New Roman", serif;
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--d-ink-900);
  margin: 0 0 4px;
}
.demo-root .page-body {
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--d-ink-700);
  margin: 0;
  /* Sized for the page column left of the docked panel. Narrower than this
     and the prospect's site reads as a placeholder rather than a real page. */
  max-width: 52ch;
}
.demo-root .page-photo-row { display: flex; gap: 12px; margin: 8px 0 0; }
.demo-root .page-photo {
  width: 90px; height: 60px;
  border-radius: 8px;
  background: var(--d-paper-dim);
  border: 1px solid var(--d-hairline);
}

/* ---------- the panel ---------- */

.demo-root .panel-mock {
  background-color: var(--d-ink-900);
  color: var(--d-paper);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
  isolation: isolate;
}

.demo-variant-wide .panel-mock,
.demo-variant-sheet .panel-mock {
  position: absolute;
  /* Real Chrome docks the side panel UNDER the toolbar, which spans the full
     window width. Starting the panel at the top of the toolbar covered the
     omnibox and every control to the right of it. */
  top: var(--d-chrome-h);
  right: 0;
  bottom: 0;
  /* The cap used to be 270px, sized for a half-width hero. Now the frame
     spans the container, so the panel gets room to show a readable draft,
     which is the only thing in this demo a visitor actually needs to read. */
  width: clamp(280px, 34%, 380px);
  border-left: 1px solid var(--d-edge);
}

/* Panel-only variant: the extension side panel is already narrow, so a
   docked-at-42% panel would be unreadable. Full width, with a slim strip
   standing in for the browser to keep "it reads the page you're on" legible. */
.demo-variant-panel {
  display: flex;
  flex-direction: column;
  /* The container carries the dark ground, not just the panel inside it:
     the context strip sits on this surface and its text is white-on-dark. */
  background: var(--d-ink-900);
  border: 1px solid var(--d-edge);
  border-radius: 12px;
  overflow: hidden;
}
/* Explicit rather than inherited: a host stylesheet may well define its
   own .panel-mock (the extension's sidepanel.css does), and "no rule" is
   not the same as "wins". Every layout property the wide variant sets is
   reset here by name. */
.demo-variant-panel .panel-mock {
  position: static;
  width: 100%;
  inset: auto;
  border-left: none;
}
.demo-variant-panel .demo-context-strip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--d-fill-1);
  border-bottom: 1px solid var(--d-edge);
  font-size: 0.72rem;
}
.demo-variant-panel .demo-context-label {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.45);
}
.demo-variant-panel .demo-context-domain { color: rgba(255, 255, 255, 0.8); }
/* Tall enough that the draft and the send row are both visible without
   scrolling, because those are the two beats that carry the pitch. Capped
   against the viewport so it still fits a short side panel. */
.demo-variant-panel .panel-mock { max-height: min(72vh, 620px); }

.demo-root .panel-titlebar {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  font-weight: 600;
  opacity: 0.85;
}

.demo-root .panel-status {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--d-fill-1);
  border: 1px solid var(--d-edge);
  border-radius: 15px;
  padding: 8px 12px;
  font-size: 0.82rem;
}
.demo-root .live-dot {
  width: 8px; height: 8px; min-width: 8px;
  border-radius: 50%;
  background: var(--d-mint);
  animation: demo-pulse 1.8s ease-in-out infinite;
}
@keyframes demo-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

.demo-root .panel-block {
  background: var(--d-fill-1);
  border: 1px solid var(--d-edge);
  border-radius: 15px;
  padding: 12px;
}
.demo-root .panel-question p {
  font-size: 0.82rem;
  line-height: 1.4;
  margin: 0 0 8px;
  color: rgba(255, 255, 255, 0.85);
}
.demo-root .pill-row { display: flex; gap: 8px; }
.demo-root .pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 16px;
  border-radius: 999px;
  font-size: 0.72rem;
  background: var(--d-fill-2);
  border: 1px solid var(--d-edge);
  color: rgba(255, 255, 255, 0.75);
  transition: background-color 160ms ease, color 160ms ease;
}
.demo-root .pill-selected {
  background: var(--d-fill-3);
  color: var(--d-paper);
  font-weight: 600;
}

.demo-root .panel-narration {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 0.82rem;
}
.demo-root .narration-step {
  display: flex;
  align-items: center;
  gap: 8px;
  color: rgba(255, 255, 255, 0.55);
}
.demo-root .narration-step.is-done { color: rgba(255, 255, 255, 0.85); }
.demo-root .narration-step.is-active { color: var(--d-paper); font-weight: 600; }
.demo-root .narration-mark { color: var(--d-mint); font-size: 0.72rem; }
.demo-root .narration-spinner {
  width: 10px; height: 10px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.25);
  border-top-color: var(--d-mint);
  animation: demo-spin 900ms linear infinite;
}
@keyframes demo-spin { to { transform: rotate(360deg); } }

.demo-root .draft-field-label {
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.5);
  margin: 0 0 4px;
}
.demo-root .draft-subject {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--d-paper);
  margin: 0 0 8px;
}
.demo-root .draft-subject mark { background: transparent; color: var(--d-mint); }
.demo-root .draft-body {
  font-size: 0.82rem;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.75);
  margin: 0;
  white-space: pre-line;
}
/* The tighten is the whole point of the refine beat, so it gets a beat of
   its own visually: a brief mint edge as the shorter body lands. */
@keyframes demo-tighten {
  from { box-shadow: inset 2px 0 0 var(--d-mint); }
  to   { box-shadow: inset 2px 0 0 transparent; }
}
.demo-root .panel-draft.is-tightened { animation: demo-tighten 900ms ease-out both; }

/* composer */
.demo-root .demo-composer {
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--d-fill-2);
  border: 1px solid var(--d-edge);
  border-radius: 15px;
  padding: 8px 12px;
  font-size: 0.8rem;
  color: var(--d-paper);
}
.demo-root .demo-caret {
  width: 1px;
  height: 1em;
  background: var(--d-mint);
  animation: demo-blink 1s step-end infinite;
}
@keyframes demo-blink { 50% { opacity: 0; } }

/* send */
.demo-root .panel-send { display: flex; flex-direction: column; gap: 12px; }
.demo-root .send-primary-row { display: flex; align-items: center; gap: 12px; }
.demo-root .panel-btn-primary {
  flex: 1;
  text-align: center;
  background: var(--d-mint);
  color: var(--d-ink-900);
  font-weight: 700;
  font-size: 0.82rem;
  padding: 12px 16px;
  border-radius: 10px;
  transition: opacity 200ms ease;
}
.demo-root .panel-btn-primary.is-dimmed { opacity: 0.35; }
.demo-root .cost-chip {
  background: var(--d-fill-2);
  border: 1px solid var(--d-edge);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.8);
}
.demo-root .send-secondary-row { display: flex; gap: 8px; }

/* Wording matters here: "opened", never "sent". The demo must not depict a
   completed send. See company/ceo/prospect-finder-guardrails.md. */


/* ---------- controls ---------- */

.demo-controls { margin-top: 16px; }
.demo-control-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.demo-btn {
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--hairline, #e2ddd7);
  background: var(--paper, #fffafb);
  color: var(--ink-900, #0e2a26);
  cursor: pointer;
  transition: background-color 150ms ease, border-color 150ms ease;
}
.demo-btn:hover:not(:disabled) { background: var(--paper-dim, #f6f1ec); }
.demo-btn:disabled { opacity: 0.4; cursor: default; }
.demo-btn-play { min-width: 88px; }

.demo-chapters {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  flex: 1;
}
.demo-chapter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: inherit;
  font-size: 0.72rem;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink-500, #5c716a);
  cursor: pointer;
}
.demo-chapter:hover { color: var(--ink-900, #0e2a26); }
.demo-chapter.is-active {
  color: var(--ink-900, #0e2a26);
  border-color: var(--hairline, #e2ddd7);
  background: var(--paper-dim, #f6f1ec);
  font-weight: 600;
}
.demo-chapter-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.4;
}
.demo-chapter.is-active .demo-chapter-dot {
  background: var(--teal, #2f9c88);
  opacity: 1;
}
.demo-caption {
  margin: 12px 0 0;
  font-size: 0.9rem;
  color: var(--ink-500, #5c716a);
  min-height: 1.4em;
}

.demo-btn:focus-visible,
.demo-chapter:focus-visible {
  outline: 2px solid var(--teal, #2f9c88);
  outline-offset: 2px;
}

/* When space is tight the chapter labels stop paying for their width, so
   they collapse to dots. The title/aria-label carry the name either way. */
.demo-controls-compact .demo-chapter-label { display: none; }
.demo-controls-compact .demo-chapter { padding: 6px; }
.demo-controls-compact .demo-chapter-dot { width: 7px; height: 7px; }
.demo-controls-compact .demo-caption { font-size: 0.82rem; }
/* In a side panel the buttons and seven dots can't share one line without
   wrapping raggedly, so give the dots their own centred row underneath. */
.demo-controls-compact .demo-control-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas: "play spacer replay" "chapters chapters chapters";
  gap: 8px 8px;
  align-items: center;
}
.demo-controls-compact .demo-btn-play { grid-area: play; }
.demo-controls-compact .demo-btn-replay { grid-area: replay; }
.demo-controls-compact .demo-chapters {
  grid-area: chapters;
  justify-content: center;
  flex-wrap: nowrap;
  gap: 2px;
}

@media (max-width: 720px) {
  .demo-chapter-label { display: none; }
  .demo-chapter { padding: 8px; }
  .demo-chapter-dot { width: 8px; height: 8px; }
}

/* Below 900px the hero stacks, and the browser frame is no longer wide
   enough to hold real page text and a docked panel legibly. Drop the
   frame and let the panel stand alone as a card, the same degradation
   the static mock used before the demo replaced it. */
@media (max-width: 899px) {
  .demo-variant-wide .browser-frame,
  .demo-variant-sheet .browser-frame {
    height: auto;
    border: none;
    background: none;
    overflow: visible;
  }
  .demo-variant-wide .browser-chrome,
  .demo-variant-wide .browser-page,
  .demo-variant-sheet .browser-chrome,
  .demo-variant-sheet .browser-page { display: none; }
  .demo-variant-wide .panel-mock,
  .demo-variant-sheet .panel-mock {
    position: static;
    width: 100%;
    max-width: 420px;
    border-left: none;
    border: 1px solid var(--d-edge);
    border-radius: 12px;
  }
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .demo-root .demo-reveal.is-revealed,
  .demo-root .panel-draft.is-tightened { animation: none; }
  .demo-root .live-dot,
  .demo-root .narration-spinner,
  .demo-root .demo-caret { animation: none; }
  .demo-root .narration-spinner { border-top-color: var(--d-mint); }
  .demo-root .pill,
  .demo-root .panel-btn-primary,
  .demo-btn { transition: none; }
}

/* Collapse the setup blocks once the draft exists. Their story is told by
   then, and leaving them expanded pushes the draft (the only thing a
   visitor needs to actually read) below the fold. */
.demo-root .demo-reveal.is-collapsed { display: none; }

.demo-root .demo-narration-summary {
  display: none;
  align-items: center;
  gap: 8px;
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.5);
  padding: 0 4px;
}
.demo-root .demo-narration-summary.is-shown { display: flex; }


/* ---------- browser tabs ---------- */

.demo-root .demo-tab {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  box-sizing: border-box;
  padding: 0 8px 0 11px;
  width: 200px;
  min-width: 0;
  font-size: 0.7rem;
  color: #9aa0a6;
  background: transparent;
  border-radius: 9px 9px 0 0;
  transition: background-color 160ms ease, color 160ms ease;
}
/* The active tab is the same colour as the toolbar beneath it and sits flush
   against it, so the two read as one continuous surface. That fusion is the
   signature of a Chrome tab strip, and it is the detail a drawn mock misses. */
.demo-root .demo-tab.is-active {
  background: #2b2b2e;
  color: #e8eaed;
}
/* The small outward curves where the active tab meets the toolbar. Chrome
   draws these, and without them the tab looks like a plain rounded rectangle
   floating above a bar. */
.demo-root .demo-tab.is-active::before,
.demo-root .demo-tab.is-active::after {
  content: "";
  position: absolute;
  bottom: 0;
  width: 9px; height: 9px;
  background: #2b2b2e;
}
.demo-root .demo-tab.is-active::before {
  left: -9px;
  border-bottom-right-radius: 9px;
  box-shadow: 3px 3px 0 3px #2b2b2e;
  clip-path: inset(50% -10px 0 50%);
}
.demo-root .demo-tab.is-active::after {
  right: -9px;
  border-bottom-left-radius: 9px;
  box-shadow: -3px 3px 0 3px #2b2b2e;
  clip-path: inset(50% 50% 0 -10px);
}
.demo-root .demo-tab-favicon {
  width: 14px; height: 14px;
  border-radius: 3px;
  flex: none;
}
/* Stand-in favicons. The restaurant gets its own mark colour and the CRM tab
   gets the Sheets green, because a tab strip where every favicon is the same
   grey square is another thing real browsers never show. */
.demo-root .demo-tab-favicon-site {
  background: linear-gradient(150deg, #b8763f, #7d3f52);
}
/* The Sheets tab carries the real mark as SVG, so the square goes away and
   the icon sits in the slot instead. */
.demo-root .demo-tab-favicon-sheet {
  background: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.demo-root .demo-tab-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.demo-root .demo-tab-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px; height: 16px;
  border-radius: 50%;
  flex: none;
  color: #9aa0a6;
  opacity: 0;
}
/* Chrome only shows the close cross on the active tab and on hover. */
.demo-root .demo-tab.is-active .demo-tab-close { opacity: 1; }

.demo-root .browser-page { display: none; }
.demo-root .browser-page.is-active { display: grid; }

/* ---------- prompt + confirmation in the panel ---------- */

.demo-root .demo-prompt {
  background: var(--d-fill-2);
  border: 1px solid var(--d-edge);
  border-radius: 15px;
  padding: 10px 12px;
}
.demo-root .demo-prompt-text {
  font-size: 0.78rem;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.88);
  margin: 0 0 8px;
}
.demo-root .demo-prompt-acts { display: flex; gap: 6px; flex-wrap: wrap; }
.demo-root .demo-prompt-btn {
  font-size: 0.7rem;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--d-fill-2);
  border: 1px solid var(--d-edge);
  color: rgba(255, 255, 255, 0.78);
  transition: background-color 160ms ease, color 160ms ease;
}
.demo-root .demo-prompt-btn.is-primary {
  background: var(--d-mint);
  border-color: var(--d-mint);
  color: var(--d-ink-900);
  font-weight: 600;
}
.demo-root .demo-prompt-btn.is-chosen {
  outline: 2px solid var(--d-mint);
  outline-offset: 2px;
}

.demo-root .demo-confirm {
  font-size: 0.72rem;
  line-height: 1.4;
  color: var(--d-mint);
  padding: 0 4px;
}


/* ============================================================
   The prospect's site: Saltcedar Kitchen & Bar

   A fictional independent restaurant, built to the shape those
   sites are actually shipped in: tinted utility bar, dark hours
   strip, white header band with a centred serif wordmark, dark
   nav rail, then a full-bleed hero.

   The palette is the restaurant's own and shares nothing with
   Dandelion's, which is the point: this is somebody else's site.
   Deep aubergine and warm brass, on a cream ground.

   Everything is set small (~0.7rem body) because the page is
   being viewed inside a browser frame at roughly 60% scale.
   ============================================================ */

/* Chrome narrows the page when the side panel opens, so the mock does the
   same rather than letting the panel sit on top of the content. The width
   is the exact complement of the panel's. */
.demo-root .demo-site,
.demo-root .demo-gs {
  width: calc(100% - clamp(280px, 34%, 380px));
}
.demo-root .demo-site {
  /* The restaurant's palette, scoped to the restaurant. Nothing here reads
     a Dandelion token, so neither host can tint somebody else's brand. */
  --ds-plum-950: #180d1c;
  --ds-plum-900: #2c1832;
  --ds-plum-700: #4a2b52;
  --ds-brass: #a8752b;
  --ds-brass-lit: #e0b96a;
  --ds-cream: #fbf5ee;
  --ds-tint: #f2e9f0;
  --ds-ink: #2a1c2c;
  --ds-muted: #5f4f61;
  --ds-line: #e2d4e0;

  display: none;
  padding: 0;
  background: var(--ds-cream);
  color: var(--ds-ink);
}
.demo-root .demo-site.is-active { display: block; }

/* ---------- utility bar ---------- */

/* Three tracks, not a flex row: the centre link has to land on the page's
   own centre line, which it only does if the side slots are equal width. */
.demo-root .demo-site-util {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  padding: 5px 16px;
  background: var(--ds-tint);
  font-size: 0.56rem;
  color: var(--ds-muted);
}
.demo-root .demo-site-util-right { text-align: right; }
.demo-root .demo-site-util-mid {
  color: var(--ds-plum-700);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---------- hours strip ---------- */

.demo-root .demo-site-announce {
  padding: 5px 16px;
  background: var(--ds-plum-950);
  color: #e8d8bf;
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  text-align: center;
}

/* ---------- header band ---------- */

.demo-root .demo-site-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  padding: 11px 16px 13px;
  background: #fff;
}
.demo-root .demo-site-search {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  width: min(110px, 100%);
  padding: 4px 8px;
  border: 1px solid var(--ds-line);
  border-radius: 2px;
  font-size: 0.56rem;
  color: var(--ds-muted);
}
/* The magnifier is a circle plus a rotated handle drawn on ::after, so the
   header needs no icon font and no image request. */
.demo-root .demo-site-searchicon {
  position: relative;
  width: 7px; height: 7px;
  flex: none;
  border: 1px solid var(--ds-muted);
  border-radius: 50%;
}
.demo-root .demo-site-searchicon::after {
  content: "";
  position: absolute;
  right: -3px; bottom: -2px;
  width: 4px;
  border-top: 1px solid var(--ds-muted);
  transform: rotate(45deg);
}

.demo-root .demo-site-mast { text-align: center; }
/* A small brass lozenge above the wordmark, the house-mark slot every
   restaurant header has. Drawn rather than fetched. */
.demo-root .demo-site-mastmark {
  width: 7px; height: 7px;
  margin: 0 auto 5px;
  border: 1px solid var(--ds-brass);
  background: var(--ds-brass-lit);
  transform: rotate(45deg);
}
.demo-root .demo-site-brand {
  font-family: ui-serif, Georgia, "Times New Roman", serif;
  font-size: 1.34rem;
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--ds-plum-900);
}
.demo-root .demo-site-tagline {
  margin-top: 4px;
  font-size: 0.48rem;
  font-weight: 600;
  letter-spacing: 0.3em;
  /* Letterspacing leaves a trailing gap after the final letter, which centring
     counts as text and so parks the word visibly left. Push it back by one
     letter's worth. */
  text-indent: 0.3em;
  color: var(--ds-muted);
}

.demo-root .demo-site-actions {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
}
.demo-root .demo-site-cta {
  padding: 5px 11px;
  border: 1px solid var(--ds-plum-900);
  border-radius: 999px;
  font-size: 0.54rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ds-plum-900);
  white-space: nowrap;
}
.demo-root .demo-site-cta.is-filled {
  background: var(--ds-plum-900);
  color: var(--ds-cream);
}

/* ---------- nav rail ---------- */

.demo-root .demo-site-nav {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 14px;
  padding: 8px 16px;
  background: var(--ds-plum-900);
}
.demo-root .demo-site-navlink {
  font-size: 0.53rem;
  letter-spacing: 0.1em;
  color: rgba(251, 245, 238, 0.82);
  white-space: nowrap;
}
/* The active item is underlined in brass, the one place the accent appears
   in the nav. Padding keeps the rule off the baseline of the caps. */
.demo-root .demo-site-navlink.is-active {
  color: var(--ds-cream);
  padding-bottom: 3px;
  border-bottom: 2px solid var(--ds-brass-lit);
}
.demo-root .demo-site-navpill {
  padding: 3px 9px;
  border: 1px solid rgba(224, 185, 106, 0.7);
  border-radius: 999px;
  font-size: 0.5rem;
  letter-spacing: 0.12em;
  color: var(--ds-brass-lit);
  white-space: nowrap;
}

/* ---------- hero ---------- */

/* There is no photography in this project and the demo may not make network
   requests, so the "photograph" is built from gradients alone. The stack, in
   paint order from the front: two candle points, three pendant pools falling
   away to the right, a warm band across where a back bar would be, a plum
   foreground rolling in from the bottom, and a near-black ground. It is the
   specular points that sell it, because a real photograph of a dim room
   always has a few blown-out highlights and a flat gradient never does.

   ::before lays grain over the whole thing and ::after carries the vignette
   plus the left-hand scrim the headline sits on, which is what keeps the
   cream text well past 4.5:1 no matter how bright the lamps get. */
.demo-root .demo-site-hero {
  position: relative;
  isolation: isolate;
  min-height: 196px;
  display: flex;
  align-items: flex-end;
  padding: 18px 20px 14px;
  overflow: hidden;
  background-color: #140b18;
  background-image:
    radial-gradient(2.4% 4.6% at 63% 63%, rgba(255, 216, 152, 0.88), transparent 72%),
    radial-gradient(1.9% 3.8% at 72% 55%, rgba(255, 206, 138, 0.62), transparent 72%),
    radial-gradient(26% 40% at 75% 11%, rgba(255, 206, 130, 0.5), transparent 68%),
    radial-gradient(40% 56% at 89% 31%, rgba(206, 148, 74, 0.4), transparent 70%),
    radial-gradient(22% 34% at 47% 7%, rgba(224, 185, 106, 0.22), transparent 70%),
    linear-gradient(180deg, transparent 40%, rgba(168, 117, 43, 0.2) 52%, transparent 65%),
    radial-gradient(100% 58% at 50% 118%, rgba(74, 43, 82, 0.95), transparent 74%),
    linear-gradient(166deg, #3a2142 0%, #201325 46%, #0f0813 100%);
}
.demo-root .demo-site-hero::before,
.demo-root .demo-site-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* Grain. Two repeating rules at odd angles and a fine pitch read as film
   texture at this size, and cost nothing to paint. */
.demo-root .demo-site-hero::before {
  background-image:
    repeating-linear-gradient(37deg, rgba(255, 255, 255, 0.028) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(-54deg, rgba(0, 0, 0, 0.05) 0 1px, transparent 1px 4px);
  z-index: 0;
}
.demo-root .demo-site-hero::after {
  background-image:
    linear-gradient(96deg, rgba(12, 7, 15, 0.82) 0%, rgba(12, 7, 15, 0.44) 34%, rgba(12, 7, 15, 0) 62%),
    radial-gradient(118% 96% at 50% 38%, transparent 44%, rgba(0, 0, 0, 0.62) 100%);
  z-index: 1;
}
.demo-root .demo-site-herobody {
  position: relative;
  z-index: 2;
  max-width: 30ch;
}
.demo-root .demo-site-kicker {
  font-size: 0.5rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: var(--ds-brass-lit);
  margin-bottom: 9px;
}
.demo-root .demo-site-headline {
  font-family: ui-serif, Georgia, "Times New Roman", serif;
  font-size: 1.42rem;
  font-weight: 400;
  line-height: 1.14;
  letter-spacing: -0.01em;
  color: var(--ds-cream);
  margin-bottom: 11px;
}
.demo-root .demo-site-heroline { display: block; }
.demo-root .demo-site-herolink {
  display: inline-block;
  font-size: 0.6rem;
  color: var(--ds-cream);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1px;
}
/* Slide counter and progress rule: one third filled, matching the "1/3". */
.demo-root .demo-site-slide {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 14px;
}
.demo-root .demo-site-slidenum {
  font-size: 0.52rem;
  letter-spacing: 0.1em;
  color: rgba(251, 245, 238, 0.8);
}
.demo-root .demo-site-sliderule {
  display: block;
  width: 86px;
  height: 1px;
  background: rgba(251, 245, 238, 0.28);
}
.demo-root .demo-site-sliderule-fill {
  display: block;
  width: 33%;
  height: 100%;
  background: var(--ds-brass-lit);
}
/* The vertical label up the right edge. writing-mode plus a 180deg turn
   makes it read bottom to top, which is how these are always set. */
.demo-root .demo-site-scroll {
  position: absolute;
  right: 9px;
  bottom: 16px;
  z-index: 2;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 0.46rem;
  letter-spacing: 0.24em;
  color: rgba(251, 245, 238, 0.72);
}

/* ---------- body ---------- */

.demo-root .demo-site-body { padding: 18px 22px 0; }
.demo-root .demo-site-h1 {
  font-family: ui-serif, Georgia, "Times New Roman", serif;
  font-size: 1.28rem;
  font-weight: 400;
  color: var(--ds-plum-900);
  margin: 0 0 12px;
}
.demo-root .demo-site-p {
  font-size: 0.7rem;
  line-height: 1.62;
  color: var(--ds-ink);
  margin: 0 0 9px;
  max-width: 62ch;
}
.demo-root .demo-site-strong { font-weight: 600; color: var(--ds-plum-900); }
.demo-root .demo-site-reg {
  font-size: 0.63rem;
  color: var(--ds-muted);
  margin: 0 0 12px;
}

.demo-root .demo-site-team {
  display: flex;
  gap: 22px;
  flex-wrap: wrap;
  padding: 10px 0 14px;
  border-top: 1px solid var(--ds-line);
}
.demo-root .demo-site-person { display: flex; gap: 9px; align-items: center; }
.demo-root .demo-site-avatar {
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--ds-tint);
  border: 1px solid var(--ds-line);
  flex: none;
}
.demo-root .demo-site-name { font-size: 0.7rem; font-weight: 600; color: var(--ds-plum-900); }
.demo-root .demo-site-role { font-size: 0.62rem; color: var(--ds-muted); }
.demo-root .demo-site-email {
  font-size: 0.62rem;
  color: var(--ds-brass);
  text-decoration: underline;
}

/* The enquiry form. This is what "Fill via form" exists for. */
.demo-root .demo-site-form { padding: 4px 0 18px; }
.demo-root .demo-site-formlegend {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--ds-plum-900);
  margin-bottom: 9px;
}
.demo-root .demo-site-formgrid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 9px 16px;
  margin-bottom: 9px;
}
.demo-root .demo-site-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.62rem;
  color: var(--ds-ink);
  margin-bottom: 3px;
}
.demo-root .demo-site-req {
  font-size: 0.52rem;
  letter-spacing: 0.08em;
  color: var(--ds-muted);
}
.demo-root .demo-site-input {
  height: 22px;
  border: 1px solid #c6b6c4;
  border-radius: 2px;
  background: #fff;
}
.demo-root .demo-site-textarea { height: 48px; }
.demo-root .demo-site-submit {
  display: inline-block;
  margin-top: 10px;
  padding: 6px 16px;
  border-radius: 999px;
  background: var(--ds-plum-900);
  color: var(--ds-cream);
  font-size: 0.65rem;
  font-weight: 600;
}

.demo-root .demo-site-cookie {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 20px;
  background: rgba(24, 13, 28, 0.94);
  color: rgba(251, 245, 238, 0.9);
  font-size: 0.62rem;
}
.demo-root .demo-site-cookieacts { display: flex; gap: 6px; }
.demo-root .demo-site-cookiebtn {
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid rgba(251, 245, 238, 0.42);
  font-size: 0.6rem;
}
.demo-root .demo-site-cookiebtn.is-primary {
  background: var(--ds-brass-lit);
  color: var(--ds-plum-950);
  border-color: var(--ds-brass-lit);
}

/* ============================================================
   Google Sheets
   Rebuilt to match the real application: menu bar, toolbar, name
   box and formula bar, column letters, row numbers, and row 1
   frozen in the green the extension actually writes
   (SHEET_HEADER_BG, background.js) .
   ============================================================ */

.demo-root .demo-gs {
  display: none;
  padding: 0;
  background: #fff;
  font-family: Arial, Roboto, "Helvetica Neue", sans-serif;
}
/* Column layout so the grid takes the slack and the sheet tab bar sits on
   the bottom edge, where Google puts it. */
.demo-root .demo-gs.is-active { display: flex; flex-direction: column; height: 100%; }
/* min-height:0 lets the grid shrink inside the flex column instead of
   pushing the sheet tab bar off the bottom edge. */
.demo-root .demo-gs-gridwrap { flex: 1; min-height: 0; overflow: hidden; }

.demo-root .demo-gs-titlebar {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  padding: 7px 12px 3px;
}
.demo-root .demo-gs-icon { width: 22px; height: 22px; flex: none; margin-top: 2px; }
.demo-root .demo-gs-namerow { display: flex; align-items: center; gap: 7px; }
.demo-root .demo-gs-name { font-size: 0.8rem; color: #202124; }
.demo-root .demo-gs-star { font-size: 0.66rem; color: #5f6368; }
.demo-root .demo-gs-menus { display: flex; gap: 11px; margin-top: 1px; }
.demo-root .demo-gs-menu { font-size: 0.63rem; color: #202124; }

.demo-root .demo-gs-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 4px 10px 0;
  padding: 4px 10px;
  background: #edf2fa;
  border-radius: 999px;
}
.demo-root .demo-gs-tool {
  font-size: 0.66rem;
  color: #444746;
  min-width: 15px;
  text-align: center;
}
.demo-root .demo-gs-tool-wide { min-width: auto; padding: 0 4px; }
.demo-root .demo-gs-tool-b { font-weight: 700; }
.demo-root .demo-gs-tool-i { font-style: italic; }
.demo-root .demo-gs-tool-s { text-decoration: line-through; }
.demo-root .demo-gs-sep { width: 1px; height: 13px; background: #c7c7c7; }

.demo-root .demo-gs-formulabar {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 4px 12px;
  border-bottom: 1px solid #e1e3e1;
  font-size: 0.63rem;
  color: #444746;
}
.demo-root .demo-gs-namebox {
  min-width: 44px;
  padding: 2px 6px;
  border: 1px solid #e1e3e1;
  border-radius: 3px;
  color: #202124;
}
.demo-root .demo-gs-fx { font-style: italic; color: #5f6368; }
.demo-root .demo-gs-formulavalue {
  color: #202124;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  flex: 1;
}

/* Twelve columns genuinely overflow at this width in the real sheet too. */
.demo-root .demo-gs-gridwrap { overflow: hidden; }
.demo-root .demo-gs-grid {
  border-collapse: collapse;
  width: 190%;
  table-layout: fixed;
  font-size: 0.63rem;
  color: #202124;
}
.demo-root .demo-gs-grid th,
.demo-root .demo-gs-grid td {
  border: 1px solid #e1e3e1;
  padding: 3px 5px;
  height: 19px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  text-align: left;
  font-weight: 400;
}
.demo-root .demo-gs-letters th {
  background: #f8f9fa;
  color: #444746;
  text-align: center;
  font-size: 0.6rem;
  height: 17px;
}
.demo-root .demo-gs-corner,
.demo-root .demo-gs-rownum {
  width: 26px;
  background: #f8f9fa;
  color: #444746;
  text-align: center !important;
  font-size: 0.58rem;
}
/* Row 1: the header the extension paints deep green with white text. */
.demo-root .demo-gs-headerrow td:not(.demo-gs-rownum) {
  background: #0e2a26;
  color: #ffffff;
  font-weight: 700;
}
.demo-root .demo-gs-row { display: none; }
.demo-root .demo-gs-row.is-shown,
.demo-root .demo-gs-headerrow { display: table-row; }

@keyframes demo-gs-rowin {
  0%   { background: #b7e4d6; }
  100% { background: transparent; }
}
.demo-root .demo-gs-row.is-highlighted td:not(.demo-gs-rownum) {
  animation: demo-gs-rowin 2400ms ease-out both;
}
/* Google's own selection outline on the cell that just landed. */
.demo-root .demo-gs-row.is-highlighted td:nth-child(2) {
  box-shadow: inset 0 0 0 2px #1a73e8;
}

.demo-root .demo-gs-sheettabs {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 12px;
  border-top: 1px solid #e1e3e1;
  background: #f8f9fa;
}
.demo-root .demo-gs-plus { font-size: 0.8rem; color: #444746; }
.demo-root .demo-gs-sheettab {
  font-size: 0.62rem;
  padding: 3px 12px;
  border-radius: 3px;
  color: #202124;
}
.demo-root .demo-gs-sheettab.is-active { background: #c3e7d8; font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
  .demo-root .demo-gs-row.is-highlighted td:not(.demo-gs-rownum) {
    animation: none;
    background: #dff2ea;
  }
}


/* ============================================================
   Mobile (< 900px): authoritative overrides

   This block has to sit at the end of the file. The earlier
   max-width:899px block is outranked by everything declared after it
   (`.demo-root .browser-page.is-active`, `.demo-root .demo-site.is-active`,
   `.demo-root .demo-gs.is-active`), so on a phone the prospect's page came
   back at `calc(100% - 280px)` = ~78px wide, one word per line, three
   thousand pixels tall, with the panel pushed off the bottom. These rules
   are variant-scoped on .demo-root to outrank those, and last to win ties.
   ============================================================ */

@media (max-width: 899px) {
  /* The frame stops being a browser and becomes a plain stack. */
  .demo-root.demo-variant-wide .browser-frame,
  .demo-root.demo-variant-sheet .browser-frame {
    height: auto;
    border: none;
    background: none;
    overflow: visible;
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  /* Tabs and address bar are context nobody can read at 358px. */
  .demo-root.demo-variant-wide .browser-chrome,
  .demo-root.demo-variant-sheet .browser-chrome { display: none; }

  /* The prospect's contact page goes, in both demos: it is the one element
     that cannot degrade, since its text is sized for ~60% scale inside a frame. */
  .demo-root.demo-variant-wide .browser-page,
  .demo-root.demo-variant-wide .browser-page.is-active,
  .demo-root.demo-variant-wide .demo-site,
  .demo-root.demo-variant-wide .demo-site.is-active,
  .demo-root.demo-variant-sheet .demo-site,
  .demo-root.demo-variant-sheet .demo-site.is-active { display: none; }

  /* The sheet stays, because the row landing in it is the whole point of the
     second demo. Full width, fixed height, still clipping its twelve
     columns exactly like the real thing. */
  .demo-root.demo-variant-sheet .demo-gs,
  .demo-root.demo-variant-sheet .demo-gs.is-active {
    display: flex;
    /* .demo-gs.is-active carries the column direction; this rule also
       matches the inactive page, so it has to state the direction itself
       or the title bar, toolbar and grid lay out side by side. */
    flex-direction: column;
    width: 100%;
    height: 300px;
    border: 1px solid var(--d-hairline);
    border-radius: 12px;
    overflow: hidden;
  }

  /* Undocked: a card in the stack rather than a panel pinned to an edge. */
  .demo-root.demo-variant-wide .panel-mock,
  .demo-root.demo-variant-sheet .panel-mock {
    position: static;
    inset: auto;
    width: 100%;
    max-width: none;
    border-left: none;
    border: 1px solid var(--d-edge);
    border-radius: 12px;
  }
}

/* Playback controls are the one part of the demo a visitor actually taps,
   and at 21px the chapter dots were a smaller target than a fingertip. */
@media (pointer: coarse), (max-width: 720px) {
  .demo-btn { min-height: 44px; }
  .demo-chapter { min-height: 40px; padding: 8px 6px; }
}
