/* dashboard-demo.css — MARKETING CHROME ONLY.
 *
 * Nothing in here styles the dashboard. The dashboard is the real product, rendered by the real
 * public/app.js inside the frame and styled by the real public/styles.css loaded into that frame's
 * document. If you find yourself adding a rule for a card, a chart, a table or a KPI, stop: you are
 * re-skinning the product on a marketing page, and it will drift the first time the product changes.
 *
 * What this file owns:
 *   .idb-tabs   the tab strip above the frame (real tab labels, 2px active underline + fill cue)
 *   .idb-stage  the fixed-size stage the frame is scaled inside
 *   .idb-frame  the frame itself, laid out at full desktop size and CSS-scaled down
 *   .idb-fade   the bottom gradient so cut-off content fades instead of being sliced
 *
 * The token values below are deliberately literal rather than var(--…): this stylesheet loads on a
 * MARKETING page, whose palette is its own business, and reaching into the app's tokens from here
 * would couple the two.
 */

.idb {
  --idb-w: 1440px;          /* the frame's laid-out width — a real desktop, not a squeezed one */
  --idb-h: 860px;           /* the frame's laid-out height — one dashboard fold             */
  --idb-scale: 1;           /* written by the ResizeObserver in dashboard-demo.js           */
  --idb-radius: 14px;
  --idb-line: #E6E8E6;
  --idb-ink: #24272B;
  --idb-muted: #4A525A;
  --idb-accent: #376EC1;
  --idb-canvas: #F8F8F8;
  display: block;
  width: 100%;
  /* Text is not drag-selectable (this is a demo surface, not a document) but everything in it is
     clickable - see .idb-frame's pointer-events. */
  -webkit-user-select: none;
  user-select: none;
}

/* ---- the mount's reserved box --------------------------------------------------------- */
/* The host page writes an EMPTY <div data-inciteful-dashboard>, and everything below it — logo
   marquee, statement, the rest of the page — sits directly under a box of height 0 until this
   script mounts. On a fast machine the mount lands before first paint and nothing is visible;
   under load it lands after, the page grows by the full height of the embed in one frame, and
   that single shift is worth CLS 0.172 against a 0.1 budget (measured at 6x CPU throttle, which
   is what a loaded CI runner looks like). Same reasoning as .idb-tabs' min-height below, one
   level up.
   The ratio is not a guess: dashboard-demo.js lays the frame out at FRAME_W 1440 x FRAME_H 960
   and scales it by (container width / FRAME_W), so the mounted height is always exactly two
   thirds of the width — measured 1.5000 at 1440, 1180, 1024, 768 and 480.
   :empty stops applying the instant the first child is appended, so the mounted module keeps
   sizing itself and a future change to FRAME_H cannot be silently contradicted from here.
   Note for a future embed: with the tab strip ON this under-reserves by the strip's 38px plus
   its 14px margin. The only current mount (home) sets data-strip="off". */
[data-inciteful-dashboard]:empty { display: block; width: 100%; aspect-ratio: 3 / 2; }

/* ---- tab strip ------------------------------------------------------------------------- */
/* Hidden by data-strip="off" on the mount node. Display:none rather than visibility/opacity so it
   takes no space and no tab stop; the strip's machinery keeps running behind it (see the comment
   in dashboard-demo.js where this class is applied). */
.idb-tabs.is-hidden { display: none; }
.idb-tabs {
  display: flex;
  gap: 4px;
  align-items: flex-end;
  margin: 0 0 14px;
  padding: 0;
  /* The strip is built from the app's own DASHBOARD_TABS once the frame is up, so it starts empty.
     Holding its height stops the page jumping when the labels arrive. */
  min-height: 38px;
  overflow-x: auto;
  scrollbar-width: none;
  /* The strip must never become a horizontal scroll trap on the page itself. */
  overscroll-behavior-x: contain;
}
.idb-tabs::-webkit-scrollbar { display: none; }

.idb-tab {
  position: relative;
  flex: 0 0 auto;
  appearance: none;
  background: none;
  border: 0;
  border-radius: 0;
  padding: 8px 14px 10px;
  font: inherit;
  font-size: 14.5px;
  font-weight: 550;
  line-height: 1.2;
  color: var(--idb-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: color 220ms ease;
}
.idb-tab:hover { color: var(--idb-ink); }
.idb-tab:focus-visible { outline: 2px solid var(--idb-accent); outline-offset: 2px; border-radius: 4px; }

/* The rail every tab sits on, and the 2px active underline that rides it. */
.idb-tab::before {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--idb-line);
}
.idb-tab::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--idb-accent);
  transform: scaleX(0);
  transform-origin: left center;
}
.idb-tab.is-active { color: var(--idb-ink); font-weight: 650; }
/* Active but not advancing (rotation stopped, or reduced motion): the underline is simply there. */
.idb-tab.is-active::after { transform: scaleX(1); }
/* Active AND advancing: the underline fills across the dwell, so the rotation is legible rather
   than a surprise. The duration is written inline by the host from the same constant it counts. */
.idb-tab.is-active.is-advancing::after {
  transform: scaleX(0);
  animation: idb-fill var(--idb-dwell, 8000ms) linear forwards;
}
@keyframes idb-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ---- stage --------------------------------------------------------------------------- */
/* Crop mode (audit 1.2): the container is too narrow for a legible full-width scale, so the
   frame holds the floor and the right edge is CLIPPED behind a fade - the same sanctioned
   device as the photography wash, and this file is on the gradient allowlist for exactly
   this class of chrome. */
.idb-cropped .idb-stage::after {
  content: ''; position: absolute; top: 0; right: 0; bottom: 0; width: 96px; z-index: 5;
  pointer-events: none;
  background: linear-gradient(270deg, var(--idb-canvas) 0%, rgba(252, 252, 252, 0) 100%);
}

.idb-demochip {
  position: absolute; top: 10px; right: 10px; z-index: 6; pointer-events: none;
  display: inline-flex; align-items: center; height: 24px; padding: 0 10px;
  border: 1px solid var(--dust, #CED0CE); border-radius: 999px; background: var(--panel, #FFFFFF);
  font-family: var(--mono, ui-monospace, monospace); font-size: 10px; font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted, #4A525A);
}

.idb-stage {
  position: relative;
  width: 100%;
  /* Height is the scaled height of the frame; written by the host alongside --idb-scale. */
  height: calc(var(--idb-h) * var(--idb-scale));
  overflow: hidden;
  border: 1px solid var(--idb-line);
  border-radius: var(--idb-radius);
  background: var(--idb-canvas);
  box-shadow: 0 1px 2px rgba(7, 7, 10, .04), 0 12px 32px -12px rgba(7, 7, 10, .18);
  /* Nothing inside the stage may capture a scroll, a click or a drag. */
  contain: paint;
}

.idb-frame {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--idb-w);
  height: var(--idb-h);
  border: 0;
  display: block;
  background: var(--idb-canvas);
  transform-origin: left top;
  transform: scale(var(--idb-scale));
  /* THE INTERACTION RULE. This is a DEMO, not a screenshot: the frame takes pointer events, so a
     visitor can switch tabs, open a rival, change the engine filter - the product answering is the
     entire point of putting it here. Page scroll is protected structurally instead: the frame's own
     html/body are overflow:hidden (see the boot script), so a wheel over it has nothing to scroll
     and the event bubbles to the page. */
  pointer-events: auto;
}

/* The cross-fade. The panel leaves quickly and arrives on the product's own easing. */
.idb-swap {
  position: absolute;
  inset: 0;
  opacity: 1;
  transform: translateY(0);
  transition: opacity 700ms cubic-bezier(0.16, 1, 0.3, 1), transform 700ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: opacity, transform;
}
.idb-stage.is-swapping .idb-swap {
  opacity: 0;
  transform: translateY(10px);
  transition-duration: 220ms;
}

/* Content cut off by the fold fades out rather than being sliced through a card. */
.idb-fade {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 137px;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(248, 248, 248, 0) 0%, rgba(248, 248, 248, .72) 45%, rgba(248, 248, 248, 1) 100%);
}

/* First paint: the frame's own document is still assembling. One quiet line, never a spinner
   competing with the product's own loading states. */
.idb-boot {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font: inherit;
  font-size: 13.5px;
  color: var(--idb-muted);
  background: var(--idb-canvas);
  transition: opacity 400ms ease;
}
.idb-stage.is-ready .idb-boot { opacity: 0; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .idb-swap,
  .idb-tab,
  .idb-boot { transition: none; }
  .idb-tab.is-active.is-advancing::after { animation: none; transform: scaleX(1); }
  .idb-stage.is-swapping .idb-swap { opacity: 1; transform: none; }
}

/* ==========================================================================================
   THE SHOWCASE - the homepage stage (George, 2026-09-05; A2 ruled the same day).
   The mount carries data-stage="showcase": a 1320 x 792 frame at Searchable's measured showcase
   scale (the sheet dashboard-showcase.css is injected into the frame), and a 60px tab strip that
   belongs to the SITE - dark, hairlines, one 2px underline that slides, a progress fill under the
   active tab that describes the dwell. Values are the dark marketing profile in
   ui-contract/tokens.json (profiles.marketing.dark.stage), written literally here for the same
   reason every value in this file is: this sheet must not reach for another document's tokens.
   ========================================================================================== */
[data-inciteful-dashboard][data-stage="showcase"]:empty { aspect-ratio: 1320 / 866; }   /* 60 strip + 14 gap + 792 frame */
.idb.idb-showcase {
  --idb-w: 1320px;
  --idb-h: 792px;
  --idb-radius: 0;
  --idb-canvas: #FFFFFF;
  --idb-line: rgba(255, 255, 255, .10);
  --idb-ink: #F2F3F4;
  --idb-muted: #A3A8AE;
  --idb-accent: #F2F3F4;
}
.idb-showcase .idb-tabs {
  box-sizing: border-box;   /* 60 including the two hairlines, as the mockup measured */
  display: grid;
  grid-template-columns: repeat(var(--idb-tabs-n, 4), minmax(0, 1fr));
  position: relative;
  height: 60px;
  min-height: 60px;
  margin: 0 0 14px;
  gap: 0;
  align-items: stretch;
  overflow: visible;
  border-top: 1px solid rgba(255, 255, 255, .10);
  border-bottom: 1px solid rgba(255, 255, 255, .10);
}
.idb-showcase .idb-tab {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 24px;
  border-left: 1px solid rgba(255, 255, 255, .10);
  border-radius: 0;
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  letter-spacing: -.01em;
  color: #A3A8AE;
  transition: color .15s, background-color .15s;
}
.idb-showcase .idb-tab:first-child { border-left: 0; }
.idb-showcase .idb-tab:hover { color: #F2F3F4; background: rgba(255, 255, 255, .03); }
.idb-showcase .idb-tab.is-active { color: #F2F3F4; font-weight: 500; }
.idb-showcase .idb-tab:focus-visible { outline: 2px solid #55A8FF; outline-offset: -3px; border-radius: 0; }
/* The strip's own border is the rail, so the per-tab rail is not painted. */
.idb-showcase .idb-tab::before { display: none; }
/* The sliding underline: one element for the whole strip, moved by --idb-slide-i (the host). */
.idb-showcase .idb-tabs::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 2px;
  width: calc(100% / var(--idb-tabs-n, 4));
  background: #F2F3F4;
  transform: translateX(calc(var(--idb-slide-i, 0) * 100%));
  transition: transform .35s cubic-bezier(.2, .7, .2, 1);
  pointer-events: none;
}
/* The progress fill: the promise about when the view changes, at 30% so the slide stays the mark. */
.idb-showcase .idb-tab::after { bottom: -1px; background: #F2F3F4; opacity: .3; }
.idb-showcase .idb-tab.is-active::after { transform: scaleX(0); }
.idb-showcase .idb-tab.is-active.is-advancing::after { animation: idb-fill var(--idb-dwell, 8000ms) linear forwards; }
.idb-showcase .idb-tabs.is-paused .idb-tab::after { animation-play-state: paused; }
.idb-showcase .idb-tabs.is-stopped .idb-tab::after { display: none; }
.idb-showcase .idb-stage {
  border: 0;
  border-radius: 0;
  background: #FFFFFF;
  box-shadow: 0 40px 100px -40px rgba(0, 0, 0, .9), 0 0 0 1px rgba(255, 255, 255, .06);
}
.idb-showcase .idb-frame { background: #FFFFFF; }
.idb-showcase .idb-fade { display: none; }
.idb-showcase .idb-boot { background: #FFFFFF; color: #5F6670; }   /* 5.6:1 on white; #737A82 measured 4.34:1 */
@media (prefers-reduced-motion: reduce) {
  .idb-showcase .idb-tabs::after { transition: none; }
}
