/* ————— Sales deck (Headway proposal decks) —————
   Self-hosted brand fonts + the handful of styles Tailwind utilities can't
   express cleanly. Everything except @font-face is scoped under `.sales-deck`
   (the 1440×810 slide canvas) so nothing leaks into app UI.
   Theme tokens live in app/assets/tailwind/application.css (@theme deck-*). */

@font-face {
  font-family: "Poppins";
  src: url("/assets/sales_deck/poppins-400-latin-f3f0f5ee.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("/assets/sales_deck/poppins-500-latin-ce788af2.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("/assets/sales_deck/poppins-600-latin-1f3eca1a.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "DM Sans";
  src: url("/assets/sales_deck/dm-sans-vf-latin-97b33bb4.woff2") format("woff2");
  font-weight: 100 1000;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Lora";
  src: url("/assets/sales_deck/lora-vf-latin-3476d662.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Lora";
  src: url("/assets/sales_deck/lora-vf-italic-latin-9d30d990.woff2") format("woff2");
  font-weight: 400 700;
  font-style: italic;
  font-display: swap;
}

/* ————— Slide canvas ————— */
/* Fixed 1440×810 design surface, scaled to the viewport by --deck-scale
   (set by the sales-deck Stimulus controller on its container). */
.deck-slide-frame {
  position: relative;
  width: 100%;
  height: calc(810px * var(--deck-scale, 1));
  overflow: hidden;
}
.sales-deck {
  position: absolute;
  top: 0;
  left: 0;
  width: 1440px;
  height: 810px;
  transform: scale(var(--deck-scale, 1));
  transform-origin: top left;
  overflow: hidden;
}

/* ————— Brand gradient helpers ————— */
.sales-deck .deck-grad {
  background-image: linear-gradient(92deg, var(--color-deck-grad-from), var(--color-deck-grad-to));
}
/* Figma's text gradients put the yellow stop far past the glyphs (the gradient
   line is ~3× the text box, yellow at 76% of it), so text only samples the
   teal→sea-green start of the ramp. Overshooting the end stop to 210% (with a
   slight downward tilt like the Figma line) reproduces that soft drift —
   a 0–100% ramp reads far too yellow at the right end. */
.sales-deck .deck-grad-text {
  background-image: linear-gradient(97deg, var(--color-deck-grad-from), var(--color-deck-grad-to) 210%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* 1.5px gradient border drawn in the padding box (why-card, constraint card,
   guarantee panel). Apply to a `relative rounded-*` element. */
.sales-deck .deck-grad-border::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  background: linear-gradient(92deg, var(--color-deck-grad-from), var(--color-deck-grad-to));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

/* ————— Topography texture ————— */
/* Contour lines anchored to the bottom of dark slides, fading out upward.
   topography-fill.svg is a black FILL of the landmass regions — the contour
   lines are the gaps between fills. Painting it over a faint light underlay
   leaves only thin light lines (canonical peak line luminance ≈ 19/255),
   with a mask so nothing shows in the upper half of the slide. */
.sales-deck .deck-topo-bottom {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    url("/assets/sales_deck/topography-fill-e9f95553.svg") left calc(50% - 40px) bottom -60px / 1160px auto repeat,
    #141414;
  -webkit-mask-image: linear-gradient(180deg, transparent 54%, #000 82%);
  mask-image: linear-gradient(180deg, transparent 54%, #000 82%);
}

/* ————— Editable-zone affordance ————— */
/* Preview of the text zones the deck editor will bind to Lexxy: dashed brand
   outline + pill on hover. Purely visual until the editor task lands. */
/* This sheet is UNLAYERED, so it beats Tailwind's @layer utilities regardless
   of specificity (:where() doesn't help) — absolutely-positioned zones (e.g.
   the lean cycle sub-list) must be excluded explicitly or position:relative
   stretches them full-width. */
.sales-deck .deck-zone:not(.absolute) {
  position: relative;
}
.sales-deck .deck-zone {
  border-radius: 8px;
  /* Gradient headings set color: transparent (background-clip: text), which
     would make the text caret invisible while editing — pin it to the brand
     lime so it reads on every zone. */
  caret-color: #b8eb86;
}
.sales-deck .deck-zone::before {
  content: "";
  position: absolute;
  inset: -8px -12px;
  border-radius: 10px;
  border: 1.5px dashed transparent;
  transition: border-color 0.15s ease;
  pointer-events: none;
}
/* Edit affordances are OPT-IN via .deck-editing (the authoring page).
   Display surfaces — present stage, public viewer, any future export —
   never set it, so frozen HTML keeping the deck-zone class stays inert. */
.deck-editing .sales-deck .deck-zone:hover::before {
  border-color: rgba(184, 235, 134, 0.55);
}
/* While editing: no native focus ring (it draws its own mismatched box) —
   the dashed outline just brightens instead, keeping one consistent shape. */
.sales-deck .deck-zone:focus,
.sales-deck .deck-zone:focus-within {
  outline: none;
}
.deck-editing .sales-deck .deck-zone:focus::before,
.deck-editing .sales-deck .deck-zone:focus-within::before {
  border-color: rgba(184, 235, 134, 0.85);
}
/* No-allocation markers: calm gray for clients; red in the editor
   (scroll + overview) so an unstaffed week can't slip out unnoticed. */
.deck-editing .sales-deck .deck-noalloc {
  border-color: rgba(239, 68, 68, 0.55);
  color: rgba(239, 68, 68, 0.85);
}

/* Post-Escape: stay quiet under the still-hovering pointer until it leaves */
.deck-editing .sales-deck .deck-zone.deck-zone-quiet::before {
  border-color: transparent;
}

/* ————— Overview / scroll view modes ————— */
/* Slides live inside per-category .deck-section-slides lists (drag targets).
   Overview: each category lays out as an auto-fill thumbnail grid.
   Scroll: full-width frames. */
.deck-view-overview .deck-section-slides {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(236px, 1fr));
  gap: 24px 20px;
  align-items: start;
}
.deck-view-overview .deck-section-slides [data-slide-frame-key] {
  margin-bottom: 0;
  cursor: pointer;
}
/* Overview: slide name reads as an annotation under the thumbnail; the top
   row keeps handle + number + controls. */
.deck-view-overview [data-slide-name] {
  display: none;
}
.deck-view-overview [data-slide-annotation] {
  display: block;
  cursor: text;
}
/* Scroll view: no category chrome (headers stay for grouping; adding
   categories happens in the overview). */
.deck-view-scroll .deck-add-category {
  display: none;
}
/* Scroll view: no category headers (sections stay in the DOM for grouping). */
.deck-view-scroll .deck-section > .group\/section {
  display: none;
}
.deck-view-scroll .deck-section {
  margin-top: 0;
}

/* Overview breathes between categories. */
.deck-view-overview .deck-section {
  margin-top: 64px;
}
.deck-view-overview .deck-section:first-of-type {
  margin-top: 0;
}
.deck-view-overview .deck-section .group\/section {
  margin-bottom: 20px;
}

/* ————— Bulk-select mode ————— */
/* Selection is the only affordance: slide/category names stay for
   identification, every other control disappears. */
.deck-bulk-mode [data-slide-controls],
.deck-bulk-mode [data-drag-handle],
.deck-bulk-mode .deck-add-category,
.deck-bulk-mode button[data-action="sales-deck#deleteSection"] {
  display: none !important;
}
/* Frames become plain click targets; inner interactions are inert. */
.deck-bulk-mode [data-slide-frame-key] {
  cursor: pointer;
}
.deck-bulk-mode [data-slide-frame-key] :is(button, [contenteditable], [data-drag-handle], .sales-deck) {
  pointer-events: none;
}
.deck-bulk-selected .deck-slide-frame {
  outline: 2.5px solid #31aab7;
  outline-offset: 3px;
}
.deck-bulk-selected .deck-slide-frame::after {
  content: "✓";
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 40;
  display: grid;
  place-items: center;
  height: 22px;
  width: 22px;
  border-radius: 9999px;
  background: #31aab7;
  color: #04222a;
  font-size: 13px;
  font-weight: 700;
}

/* Drag styling: the in-list placeholder becomes a quiet dashed well; the
   floating clone reads as a picked-up card. */
.deck-drag-ghost {
  opacity: 1 !important;
}
.deck-drag-ghost .deck-slide-frame {
  box-shadow: none; /* drop the ring */
  outline: 1.5px dashed #3c4046;
  outline-offset: -1.5px;
  border-radius: 12px;
}
.deck-drag-ghost .deck-slide-frame .sales-deck,
.deck-drag-ghost [data-slide-annotation],
.deck-drag-ghost > div:first-child {
  visibility: hidden;
}
.deck-drag-item {
  opacity: 0.95 !important;
  transform: rotate(1.2deg) scale(0.98);
  background: transparent !important;
}
.deck-drag-item > div:first-child,
.deck-drag-item [data-slide-annotation] {
  visibility: hidden;
}
.deck-drag-item .deck-slide-frame {
  box-shadow: 0 26px 70px rgba(0, 0, 0, 0.65), 0 0 0 1px #31aab7;
}

/* Empty categories stay droppable. */
.deck-section-slides:not(:has([data-slide-frame-key])) {
  min-height: 74px;
  border: 1.5px dashed #2a2d33;
  border-radius: 12px;
}
/* Drag handle only shows in the overview grid (where reordering happens);
   the slide name stays visible in both views, truncated, edited inline. */
[data-slide-frame-key] [data-drag-handle] {
  display: none;
}
.deck-view-overview [data-slide-frame-key] [data-drag-handle] {
  display: block;
}

/* Template-slide chrome (add item/line buttons) hides while presenting. */
.deck-present-stage [data-deck-chrome] {
  display: none;
}
/* Present mode is display-only and end-user facing: no edit affordances,
   no editing cursors. Interaction handlers guard on .deck-present-stage. */
.deck-present-stage .deck-zone::before {
  display: none;
}
.deck-present-stage .deck-zone,
.deck-present-stage [data-image-picker],
.deck-present-stage [contenteditable] {
  cursor: default;
}

/* ————— Sticky header seam guard (live story map board) ————— */
/* Sticky cells become their own compositing layers; under the canvas's
   fractional scale() the layer's bottom edge resamples and lets ~1px of the
   cards scrolling beneath show through (reads as a colored underline per
   chip). A background-colored skirt overdraws the seam. */
.sales-deck .deck-sticky-seam {
  /* skirt below the layer-edge seam; no upward skirt — the activity and step
     rows are flush (44px each), and an upward shadow would square off the
     rounded bottoms of the blue activity cards in the row above */
  box-shadow: 0 2px 0 0 var(--color-deck-bg);
}

/* ————— Timeline card editing (light background variant of the zone look) ————— */
.sales-deck .deck-card-editable {
  position: relative;
  outline: none;
  caret-color: #166534;
  border-radius: 5px;
}
.sales-deck .deck-card-editable::before {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 7px;
  border: 1.5px dashed transparent;
  transition: border-color 0.15s ease;
  pointer-events: none;
}
.deck-editing .sales-deck .deck-card-editable:hover::before {
  border-color: rgba(101, 163, 13, 0.55);
}
.deck-editing .sales-deck .deck-card-editable:focus::before {
  border-color: rgba(101, 163, 13, 0.9);
}

/* ————— Technology list auto-columns ————— */
/* Content-heavy stacks (Elixir) reflow into the canonical two-column wide
   layout; short lists stay a single centered column. Toggled by JS measure. */
.sales-deck .deck-tech-listwrap--cols {
  width: 1180px;
}
.sales-deck .deck-tech-list--cols {
  columns: 2;
  column-gap: 64px;
  font-size: 17.5px;
  line-height: 1.7;
}
.sales-deck .deck-tech-list--cols > li {
  break-inside: avoid;
  margin-bottom: 0.9em;
}

/* ————— Editable bullet lists ————— */
/* The UL is the editable zone; li styling and the dot live HERE (element
   level, driven by custom properties) so new <li> created by pressing Enter
   while editing inherit spacing and the bullet automatically. */
.sales-deck ul.deck-li-dot {
  --dot-color: #fff;
  --dot-size: 0.26em;
  --dot-left: 0.66em;
  --li-pad: 1.8em;
  --li-gap: 0.8em;
}
.sales-deck ul.deck-li-dot > li {
  position: relative;
  padding-left: var(--li-pad);
  margin-bottom: var(--li-gap);
}
.sales-deck ul.deck-li-dot > li:last-child {
  margin-bottom: 0;
}
.sales-deck ul.deck-li-dot > li.deck-li-plain::before {
  content: none; /* an "exited" bullet: the line stays, the dot goes */
}
.sales-deck ul.deck-li-dot > li::before {
  content: "";
  position: absolute;
  left: var(--dot-left);
  /* Optically center the dot on the first line box — 1lh tracks the li's
     computed line-height, so tall leading never drifts the dot. --dot-top
     remains an escape hatch for odd layouts. */
  top: var(--dot-top, calc(0.5lh - var(--dot-size) / 2));
  width: var(--dot-size);
  height: var(--dot-size);
  border-radius: 999px;
  background: var(--dot-color);
}

/* ————— Wheel inline rename editor ————— */
.sales-deck .deck-wheel-editor {
  position: absolute;
  z-index: 30;
  min-width: 320px;
  transform: translate(-50%, -50%);
  text-align: center;
  font: 500 17px var(--font-deck-body);
  letter-spacing: 0.02em;
  color: #fff;
  background: #17191c;
  border: 1.5px solid var(--color-deck-teal);
  border-radius: 9px;
  padding: 8px 12px;
  outline: none;
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.6);
}

/* ————— Uploaded-image framing (pan / zoom / crop by framing) ————— */
.sales-deck .deck-img-wrap {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
  touch-action: none;
  /* Same editable affordance as text zones — outline (not a pseudo) because
     the wrap clips its children; outline-offset gives it breathing room. */
  outline: 1.5px dashed transparent;
  outline-offset: 6px;
  transition: outline-color 0.15s ease;
}
/* Shrink-to-fit variant (cover client logo): the wrap takes the image's
   natural width at slot height instead of a fixed box. No crop frame means
   no pan/zoom — just replace, floated above the slot so the tiny wrap
   (which would otherwise clip its own corner controls) can't hide it. */
.sales-deck .deck-img-wrap--fit {
  width: auto;
}
.sales-deck .deck-img-wrap--fit,
.sales-deck .deck-img-wrap--float {
  overflow: visible;
}
.sales-deck .deck-img-wrap--fit .deck-img-controls,
.sales-deck .deck-img-wrap--float .deck-img-controls {
  top: auto;
  right: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(50%);
}
.sales-deck .deck-img-wrap.deck-img-wrap--fit img,
.sales-deck .deck-img-wrap.deck-img-wrap--float img {
  cursor: default; /* no pan on replace-only slots */
}
.sales-deck .deck-img-wrap img {
  user-select: none;
  -webkit-user-drag: none;
}
.deck-editing .sales-deck .deck-img-wrap img {
  cursor: grab;
}
.deck-editing .sales-deck .deck-img-wrap img:active {
  cursor: grabbing;
}
/* Editor-only pointer cursors survive in frozen class lists — neutralize
   everywhere outside the editor. */
.sales-deck .cursor-pointer {
  cursor: default;
}
.deck-editing .sales-deck .cursor-pointer {
  cursor: pointer;
}
.sales-deck .deck-img-controls {
  position: absolute;
  right: 8px;
  top: 8px;
  z-index: 10;
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.sales-deck .deck-img-wrap:hover .deck-img-controls {
  opacity: 1;
}
.sales-deck .deck-img-wrap:hover {
  outline-color: rgba(184, 235, 134, 0.55);
}
.sales-deck .deck-img-controls button {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  border: 1px solid #3a3e44;
  background: rgba(10, 10, 12, 0.85);
  color: #dfe3e7;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}
.sales-deck .deck-img-controls button:hover {
  border-color: #b8eb86;
  color: #fff;
}

/* ————— Overview eyelid state ————— */
.deck-excluded .deck-slide-frame {
  outline: 1.5px dashed #3c4046;
  outline-offset: -1.5px;
}
.deck-excluded .sales-deck {
  filter: grayscale(1) brightness(0.45);
}

/* ————— Present mode ————— */
.deck-present-overlay {
  position: fixed;
  inset: 0;
  z-index: 10050;
  display: grid;
  place-items: center;
  background: #060607;
}
.deck-present-stage {
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55), 0 0 0 1px #26282c;
}
.deck-present-hud {
  position: fixed;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 16px;
  color: #9aa3ab;
  font-size: 12px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  white-space: nowrap;
}
.deck-present-nav {
  position: fixed;
  top: 0;
  bottom: 0;
  width: 16%;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.deck-present-nav.prev { left: 0; }
.deck-present-nav.next { right: 0; }

/* ————— Scrollable data slides ————— */
/* Timeline (horizontal) and roadmap (vertical) scroll inside their slide. */
.sales-deck .deck-scroll-x {
  overflow-x: auto;
  overflow-y: hidden;
}
.sales-deck .deck-scroll-y {
  overflow-y: auto;
  overflow-x: hidden;
}
.sales-deck .deck-scroll-xy {
  overflow: auto;
}
.sales-deck .deck-scroll-x::-webkit-scrollbar {
  height: 11px;
}
.sales-deck .deck-scroll-y::-webkit-scrollbar {
  width: 11px;
}
.sales-deck .deck-scroll-xy::-webkit-scrollbar {
  width: 11px;
  height: 11px;
}
.sales-deck .deck-scroll-x::-webkit-scrollbar-track,
.sales-deck .deck-scroll-y::-webkit-scrollbar-track,
.sales-deck .deck-scroll-xy::-webkit-scrollbar-track {
  background: #0b0b0b;
}
.sales-deck .deck-scroll-x::-webkit-scrollbar-thumb,
.sales-deck .deck-scroll-y::-webkit-scrollbar-thumb,
.sales-deck .deck-scroll-xy::-webkit-scrollbar-thumb {
  background: #383c43;
  border-radius: 6px;
  border: 2px solid #0b0b0b;
}
.sales-deck .deck-scroll-xy::-webkit-scrollbar-corner {
  background: #0b0b0b;
}
