/*
 * The keynote's content blocks (js/ui/keynote-blocks.js).
 *
 * These sit beside the lesson, on every slide of the agentic track and on the
 * one slide of the narrating track that carries a shelf of models. They are the
 * only place in the app with a real table, a log and a bar chart, so the rules
 * here are deliberately narrow: nothing outside `.keynote__blocks` is affected.
 *
 * The loops live here rather than in JS on purpose. A CSS animation is silenced
 * by the global prefers-reduced-motion rule in base.css and holds no reference to
 * the node it runs on, so a discarded slide cannot keep one alive.
 */

.keynote__blocks {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  /*
   * The centred slide layouts centre everything under them, and a table, a log
   * or a list of sources cannot survive that. Blocks always read left.
   */
  text-align: left;
}

.knote-caption {
  margin-bottom: var(--space-2);
  font-size: var(--text-helper);
  font-weight: var(--weight-label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* --------------------------------- points -------------------------------- */

.knote-points {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  list-style: none;
}

.knote-point {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
}

/* The gradient disc is the app's mark for "this is one of a set". */
.knote-point__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-pill);
  background: var(--gradient-primary);
  color: var(--text-on-accent);
}

.knote-point__body {
  display: block;
  min-width: 0;
}

.knote-point__label {
  display: block;
  font-size: var(--text-label);
  font-weight: var(--weight-label);
  color: var(--text-primary);
}

.knote-point__text {
  display: block;
  margin-top: 2px;
  font-size: var(--text-body);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
}

/* --------------------------------- table --------------------------------- */

/* Wide content scrolls inside its own box; the slide never scrolls sideways. */
.knote-table__scroll {
  overflow-x: auto;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface);
}

.knote-table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
  font-size: var(--text-body);
}

.knote-table th {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-default);
  background: var(--surface-muted);
  font-size: var(--text-helper);
  font-weight: var(--weight-label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}

.knote-table__cell {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border-subtle);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
  vertical-align: top;
}

.knote-table__row:first-child .knote-table__cell {
  border-top: none;
}

/* The first column names the thing the row is about. */
.knote-table__cell--lead {
  font-weight: var(--weight-label);
  color: var(--text-primary);
  white-space: nowrap;
}

/* ---------------------------------- flow --------------------------------- */

.knote-flow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  list-style: none;
  counter-reset: none;
}

.knote-flow__step {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

.knote-flow__chip {
  display: inline-block;
  padding: 6px var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: var(--text-helper);
  color: var(--text-primary);
  /* One shared pulse, offset per chip in JS, so the light travels the row. */
  animation: knote-pulse 1280ms var(--ease-out) infinite;
}

.knote-flow__arrow {
  display: inline-flex;
  color: var(--text-disabled);
}

.knote-flow__back {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin-top: var(--space-3);
  font-size: var(--text-body);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

.knote-flow__back .icon {
  flex: none;
  margin-top: 3px;
  color: var(--accent);
}

@keyframes knote-pulse {
  0%,
  70%,
  100% {
    border-color: var(--border-default);
    background: var(--surface);
  }
  18% {
    border-color: var(--accent);
    background: var(--accent-soft);
  }
}

/* ---------------------------------- trace -------------------------------- */

.knote-trace {
  display: flex;
  flex-direction: column;
  list-style: none;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-inset);
  overflow: hidden;
}

.knote-trace__row {
  display: grid;
  /* Wide enough for "Resposta final", the longest label, and no wider. */
  grid-template-columns: 126px minmax(0, 1fr);
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--text-body);
  line-height: var(--leading-normal);
}

.knote-trace__row:first-child {
  border-top: none;
}

.knote-trace__kind {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-helper);
  font-weight: var(--weight-label);
  color: var(--text-muted);
  white-space: nowrap;
}

.knote-trace__icon {
  display: inline-flex;
}

.knote-trace__text {
  color: var(--text-secondary);
}

/* Each kind of turn gets its own colour, so the rhythm of the trace is legible
   before a single word of it is read. */
.knote-trace__row[data-kind='input'] .knote-trace__kind {
  color: var(--text-primary);
}

.knote-trace__row[data-kind='thought'] .knote-trace__kind {
  color: var(--accent-deep);
}

.knote-trace__row[data-kind='action'] .knote-trace__kind {
  color: var(--accent);
}

.knote-trace__row[data-kind='observation'] .knote-trace__kind {
  color: var(--warning);
}

.knote-trace__row[data-kind='final'] {
  background: var(--success-soft);
}

.knote-trace__row[data-kind='final'] .knote-trace__kind {
  color: var(--success);
}

.knote-trace__row[data-kind='action'] .knote-trace__text {
  font-family: var(--font-mono);
  font-size: var(--text-helper);
}

/* ---------------------------------- meter -------------------------------- */

.knote-meter {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  list-style: none;
}

.knote-meter__row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.knote-meter__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.knote-meter__label {
  font-size: var(--text-label);
  font-weight: var(--weight-label);
  color: var(--text-primary);
}

.knote-meter__value {
  font-size: var(--text-section-title);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  background: var(--gradient-primary);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.knote-meter__track {
  display: block;
  height: 10px;
  border-radius: var(--radius-pill);
  background: var(--surface-muted);
  overflow: hidden;
}

/* Scaled from the left so the growth reads as filling rather than as sliding. */
.knote-meter__fill {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--gradient-primary);
  transform-origin: left center;
}

.knote-meter__detail {
  font-size: var(--text-helper);
  color: var(--text-muted);
}

/* --------------------------------- compare ------------------------------- */

.knote-compare {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.knote-compare__column {
  padding: var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface);
}

/* The agent side is the expensive one, and it is marked as such. */
.knote-compare__column[data-side='right'] {
  border-color: var(--accent-soft-strong);
  background: var(--accent-soft);
}

.knote-compare__title {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: var(--space-3);
  font-size: var(--text-label);
  font-weight: var(--weight-label);
  color: var(--text-primary);
}

.knote-compare__icon {
  display: inline-flex;
  color: var(--accent);
}

.knote-compare__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  list-style: none;
  font-size: var(--text-body);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

.knote-compare__list li {
  padding-left: var(--space-4);
  position: relative;
}

.knote-compare__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  opacity: 0.5;
}

/* --------------------------------- ladder -------------------------------- */

.knote-ladder {
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-start;
  gap: var(--space-1);
}

.knote-ladder__rung {
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--text-label);
  font-weight: var(--weight-label);
  color: var(--text-primary);
}

/*
 * Each step is indented past the one below it, so the stack reads as a climb.
 * Hand-written rather than generated because there are exactly four of them and
 * the last one carries the gradient.
 */
.knote-ladder__rung[data-level='1'] {
  margin-left: var(--space-4);
}

.knote-ladder__rung[data-level='2'] {
  margin-left: var(--space-8);
}

.knote-ladder__rung[data-level='3'] {
  margin-left: var(--space-12);
  border-color: transparent;
  background: var(--gradient-primary);
  color: var(--text-on-accent);
}

.knote-ladder__adds {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-left: var(--space-4);
  font-size: var(--text-helper);
  color: var(--text-muted);
}

.knote-ladder__adds[data-level='2'] {
  padding-left: var(--space-8);
}

.knote-ladder__adds[data-level='3'] {
  padding-left: var(--space-12);
}

.knote-ladder__plus {
  font-weight: var(--weight-bold);
  color: var(--accent);
}

/* ---------------------------------- links -------------------------------- */

/*
 * Two columns, because this block only appears on a closing slide that also has
 * to fit the call to action. Six sources stacked pushed the buttons below the
 * fold, and the buttons are the point of the deck.
 */
.knote-links {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
  list-style: none;
}

.knote-link__anchor {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  height: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface);
  text-decoration: none;
  transition:
    border-color var(--duration-base) var(--ease-out),
    background-color var(--duration-base) var(--ease-out);
}

.knote-link__anchor:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.knote-link__body {
  display: block;
  min-width: 0;
}

.knote-link__label {
  display: block;
  font-size: var(--text-body);
  font-weight: var(--weight-medium);
  line-height: var(--leading-normal);
  color: var(--text-primary);
}

.knote-link__source {
  display: block;
  font-size: var(--text-helper);
  color: var(--text-muted);
}

.knote-link__go {
  display: inline-flex;
  flex: none;
  color: var(--accent);
}

/* ------------------------------- responsive ------------------------------ */

@media (max-width: 860px) {
  .knote-compare,
  .knote-links {
    grid-template-columns: minmax(0, 1fr);
  }

  .knote-trace__row {
    grid-template-columns: minmax(0, 1fr);
    gap: 2px;
    padding: var(--space-3) var(--space-4);
  }

  .knote-ladder__rung[data-level='1'],
  .knote-ladder__adds[data-level='1'] {
    margin-left: 0;
    padding-left: var(--space-3);
  }

  .knote-ladder__rung[data-level='2'],
  .knote-ladder__adds[data-level='2'] {
    margin-left: var(--space-3);
    padding-left: var(--space-4);
  }

  .knote-ladder__adds[data-level='3'] {
    padding-left: var(--space-5);
  }

  .knote-ladder__rung[data-level='3'] {
    margin-left: var(--space-5);
  }
}

/* -------------------------------- picker --------------------------------- */

/*
 * The one block you use rather than read: a rail of companies, and the shelf
 * behind whichever is pressed.
 *
 * The shelf has a floor. Without it the column's height would track whichever
 * company has the most models, and because the stage centres its row, picking a
 * company with three models after one with four would shift the whole
 * composition, puppet included, up by half a row. A list that moves the drawing
 * when you read it is worse than a list with a gap at the bottom.
 */

.knote--picker {
  /* The block owns its clicks; see OWN_CLICK in js/ui/keynote.js. */
  cursor: default;
}

.knote-picker__field {
  display: block;
  cursor: pointer;
}

.knote-picker__label {
  display: block;
  margin-bottom: 5px;
  font-size: var(--text-helper);
  font-weight: var(--weight-label);
  color: var(--text-secondary);
}

/*
 * The caret is drawn rather than left to the platform, because `appearance: none`
 * is what makes the control match the app's inputs and it takes the native arrow
 * with it. Positioned over the select, and not listening for clicks, so the
 * whole field still opens the dropdown.
 */
.knote-picker__control {
  position: relative;
  display: block;
}

.knote-picker__select {
  appearance: none;
  padding-right: 36px;
  font-size: var(--text-label);
  font-weight: var(--weight-label);
  cursor: pointer;
}

.knote-picker__caret {
  position: absolute;
  top: 50%;
  right: 12px;
  transform: translateY(-50%);
  display: inline-flex;
  pointer-events: none;
  color: var(--text-muted);
}

.knote-picker__select:focus + .knote-picker__caret {
  color: var(--accent);
}

.knote-picker__shelf {
  margin-top: var(--space-3);
}

/*
 * Two lines held open whether the sentence needs them or not. Both floors here
 * are the same idea as the shelf comment above: every company has to occupy the
 * same height, or reading the list moves the drawing next to it.
 */
.knote-picker__note {
  min-height: 36px;
  margin-bottom: var(--space-2);
  font-size: var(--text-helper);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

.knote-picker__models {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  list-style: none;
  /*
   * Four rows and their three gaps, at the height a two line description takes.
   * The descriptions are the companies' own words now, and several of them do
   * not fit on one line, so the floor is measured on the taller row.
   */
  min-height: 326px;
}

.knote-picker__model {
  padding: 8px 11px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-secondary);
}

.knote-picker__model[data-pick='true'] {
  border-color: transparent;
  background: var(--accent-soft);
  box-shadow: 0 0 0 1.5px var(--accent);
}

.knote-picker__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.knote-picker__name {
  font-size: var(--text-label);
  font-weight: var(--weight-label);
  color: var(--text-primary);
}

.knote-picker__badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: none;
  font-size: 11px;
  font-weight: var(--weight-label);
  letter-spacing: 0.02em;
  color: var(--accent-deep);
}

.knote-picker__use {
  display: block;
  margin-top: 2px;
  font-size: var(--text-helper);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

.knote-picker__source {
  margin-top: var(--space-2);
  font-size: 11px;
  line-height: var(--leading-normal);
  color: var(--text-muted);
}

.knote-picker__footnote {
  margin-top: var(--space-3);
  font-size: 11px;
  color: var(--text-muted);
}

/*
 * Stacked, the shelf is under the rail rather than beside anything, so the floor
 * that keeps the desktop composition still is just dead space here.
 */
@media (max-width: 1000px) {
  .knote-picker__note,
  .knote-picker__models {
    min-height: 0;
  }
}

/* ------------------------------- tradeoff -------------------------------- */

/*
 * Two approaches side by side, each split into what it buys and what it costs.
 *
 * Distinct from `compare` on purpose. That one is for "these are different
 * things"; this is for "both are valid, and here is the bill", so the split is
 * the content and not decoration. The two columns are the same width whatever
 * they hold, because the moment one looks bigger than the other the drawing has
 * made an argument the words did not.
 */

.knote-tradeoff {
  display: grid;
  /* Box, channel, box. The middle is fixed so the two boxes stay identical. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: var(--space-2);
  align-items: stretch;
}

/* ---- the channel between the two boxes ---- */

.knote-tradeoff__bridge {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
  width: 52px;
  padding: var(--space-4) 0;
}

.knote-tradeoff__track {
  position: absolute;
  top: 10px;
  bottom: 10px;
  left: 50%;
  margin-left: -1px;
  border-left: 2px dashed var(--border-strong);
}

/* The request, falling. */
.knote-tradeoff__drop {
  position: absolute;
  left: 50%;
  width: 9px;
  height: 9px;
  margin-left: -4.5px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft);
  animation: knote-bridge-drop 2400ms linear infinite;
}

/* One pair of arrows, pointing into both boxes at once. */
.knote-tradeoff__rung {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  color: var(--accent);
  opacity: 0.2;
  animation: knote-bridge-rung 2400ms var(--ease-out) infinite;
}

@keyframes knote-bridge-drop {
  0% {
    top: 2%;
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  86% {
    opacity: 1;
  }
  100% {
    top: 95%;
    opacity: 0;
  }
}

/*
 * Standing still, the channel still has to say what it says.
 *
 * The global reduce rule in base.css collapses these loops to nothing, which
 * would leave the arrows at the quarter opacity they rest at between beats and
 * the dot wherever the layout happened to drop it. Pinned to the middle and
 * turned up, the still picture is the same claim the animation makes: one
 * request, arriving, going both ways.
 */
@media (prefers-reduced-motion: reduce) {
  .knote-tradeoff__rung {
    opacity: 0.8;
  }

  .knote-tradeoff__drop {
    top: 50%;
    margin-top: -4.5px;
  }
}

@keyframes knote-bridge-rung {
  0%,
  100% {
    opacity: 0.2;
  }
  8% {
    opacity: 1;
  }
  34% {
    opacity: 0.2;
  }
}

.knote-tradeoff__column {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--surface-secondary);
}

.knote-tradeoff__title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-label);
  font-weight: var(--weight-label);
  color: var(--text-primary);
}

.knote-tradeoff__icon {
  display: inline-flex;
  color: var(--accent);
}

/* The pair of these is the argument: same request, two shapes. */
.knote-tradeoff__example {
  padding: 7px 9px;
  border-radius: var(--radius-sm);
  background: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

.knote-tradeoff__side-label {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: var(--weight-label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.knote-tradeoff__side[data-kind='pros'] .knote-tradeoff__side-icon {
  color: var(--success);
}

.knote-tradeoff__side[data-kind='cons'] .knote-tradeoff__side-icon {
  color: var(--danger);
}

.knote-tradeoff__side-icon {
  display: inline-flex;
}

.knote-tradeoff__list {
  margin-top: 5px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  list-style: none;
  font-size: var(--text-helper);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

/*
 * Stacked, the two stop being a comparison and become two lists in a row, and a
 * channel that ran between them would now run above one of them and mean nothing.
 */
@media (max-width: 1000px) {
  .knote-tradeoff {
    grid-template-columns: minmax(0, 1fr);
  }

  .knote-tradeoff__bridge {
    display: none;
  }
}
