/* Gantt / Chronologie (spec §4.5).
 *
 * Vertical time axis (sticky left) + horizontal stage columns (sticky
 * top). Act blocks are absolutely positioned inside their stage column
 * using top/height set by the timeline Stimulus controller — this
 * keeps CSP strict and decouples the grid math from rendering.
 *
 * Density: 60 px per hour (1 px / minute).
 */

@layer components {
  .gantt {
    display: grid;
    grid-template-columns: 44px 1fr;
    grid-template-rows: 30px 1fr;
    margin-block: var(--block-space-s);
    border: 0.5px solid var(--color-border);
    border-radius: var(--radius);
    overflow: auto;
    max-block-size: min(75dvh, 48rem);
    background: var(--color-canvas);
  }

  /* ── Sticky chromes ──────────────────────────────────────────────── */

  .gantt__corner {
    grid-column: 1;
    grid-row: 1;
    position: sticky;
    inset-block-start: 0;
    inset-inline-start: 0;
    background: var(--color-canvas);
    z-index: 6;
    border-block-end: 0.5px solid var(--color-border);
    border-inline-end: 0.5px solid var(--color-border);
  }

  .gantt__stages-header {
    grid-column: 2;
    grid-row: 1;
    display: grid;
    grid-template-columns: repeat(var(--gantt-stage-count, 1), minmax(140px, 1fr));
    position: sticky;
    inset-block-start: 0;
    z-index: 5;
    background: var(--color-canvas);
    border-block-end: 0.5px solid var(--color-border);
  }

  .gantt__stage-header {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.375rem 0.5rem;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--sc);
    text-align: center;
    border-inline-end: 0.5px solid var(--color-border);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;

    &:last-child { border-inline-end: 0; }
  }

  /* Author display: flex wins over UA `[hidden] { display: none }` —
   * reassert it so stage filter can drop a column entirely. */
  .gantt__stage-header[hidden] {
    display: none;
  }

  /* ── Time column ─────────────────────────────────────────────────── */

  .gantt__time-col {
    grid-column: 1;
    grid-row: 2;
    position: sticky;
    inset-inline-start: 0;
    z-index: 4;
    background: var(--color-canvas);
    border-inline-end: 0.5px solid var(--color-border);
    min-block-size: calc(var(--gantt-total-minutes) * 1px);
  }

  .gantt__hour {
    position: absolute;
    inset-inline: 0;
    block-size: 60px;
    padding: 2px 4px;
    font-size: 0.6875rem;
    font-weight: 500;
    color: var(--color-ink-muted);
    font-variant-numeric: tabular-nums;
    border-block-start: 0.5px solid var(--color-border);

    &:first-child { border-block-start: 0; }
  }

  /* ── Stage grid + blocks ─────────────────────────────────────────── */

  .gantt__stages {
    grid-column: 2;
    grid-row: 2;
    display: grid;
    grid-template-columns: repeat(var(--gantt-stage-count, 1), minmax(140px, 1fr));
    position: relative;
    block-size: calc(var(--gantt-total-minutes) * 1px);
  }

  .gantt__stage-col {
    position: relative;
    border-inline-end: 0.5px solid var(--color-border);

    &:last-child { border-inline-end: 0; }

    /* Hour rules visible through each stage column. */
    background-image: repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent 59.5px,
      var(--color-border) 59.5px,
      var(--color-border) 60px
    );
    background-size: 100% 60px;
  }

  .gantt__block {
    position: absolute;
    inset-inline: 2px;
    padding: 5px 7px;
    background: color-mix(in oklch, var(--sc) 18%, var(--color-surface));
    border: 0.5px solid color-mix(in oklch, var(--sc) 40%, transparent);
    border-radius: var(--radius-sm);
    overflow: hidden;
    text-decoration: none;
    color: var(--color-ink);
    display: flex;
    flex-direction: column;
    gap: 1px;
    cursor: pointer;

    &:hover {
      background: color-mix(in oklch, var(--sc) 24%, var(--color-surface));
    }
  }

  /* Author display: flex wins over the UA `[hidden] { display: none }`
   * rule by source order. Reassert hide-when-hidden so client-side
   * filters (lineup-search) actually take blocks out of layout. */
  .gantt__block[hidden] {
    display: none;
  }

  /* Starred treatment — the one place the Gantt breaks the 0.5 px rule.
   * Amber border + warmer fill + subtle glow make starred blocks pop
   * through sunlight glare on a phone. Spec §4.5 "featured item".
   * Driven by `:has()` against the live wish-btn so the visual flips
   * the moment the turbo_stream replaces the toggle — no server-side
   * re-render of the outer block needed. */
  .gantt__block:has(.wish-btn--active) {
    border-width: 2px;
    border-color: oklch(var(--lch-golden));
    background: color-mix(in oklch, oklch(var(--lch-golden)) 10%, color-mix(in oklch, var(--sc) 22%, var(--color-surface)));
    box-shadow: 0 0 8px color-mix(in oklch, oklch(var(--lch-golden)) 30%, transparent);
  }

  .gantt__block-title {
    font-size: 0.6875rem;
    font-weight: 500;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Reserve space for the absolutely-positioned wish toggle in the
     * top-right corner so long titles don't run under it. */
    padding-inline-end: 24px;
    /* In a column flex container, the title's `overflow: hidden` makes
     * its default min-height resolve to 0 — so when crew avatars are
     * present and the block is short, the title silently collapses to
     * an empty line. Pinning flex-shrink keeps it always at least one
     * line tall. */
    flex-shrink: 0;
  }

  /* Blocks of 60 minutes or longer get enough vertical room for a
   * two-line title, so long band names don't get chopped mid-word.
   * The --long modifier is applied in the Ruby partial when duration
   * passes the threshold. */
  .gantt__block--long .gantt__block-title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    white-space: normal;
  }

  .gantt__block-time {
    font-size: 0.6875rem;
    line-height: 1.2;
    color: var(--color-ink-muted);
    font-variant-numeric: tabular-nums;
  }

  /* Sub-40-minute slots can't fit title + time without clipping. The
   * left time column already shows when the block starts, and the
   * popover reveals the full range on tap, so the in-block time and
   * crew avatars are both redundancies worth dropping at this size. */
  .gantt__block--short .gantt__block-time,
  .gantt__block--short .gantt__block-crew {
    display: none;
  }

  /* When the block carries crew avatars, drop the in-block time row.
   * Title + avatars always wins over title + time because the avatars
   * are unique info (which crew member starred this) — the start time
   * is already anchored by the row's vertical position in the time
   * column on the left. */
  .gantt__block:has(.gantt__block-crew) .gantt__block-time {
    display: none;
  }

  .gantt__block-crew {
    margin-block-start: auto;
  }

  /* Wish toggle, anchored top-right. Smaller than the list-view star
   * so it fits in 30-min blocks without dominating the title. The
   * button still has a generous tap area thanks to padding around the
   * 14 px icon (~28 × 28 hit target). */
  .gantt__block-action {
    position: absolute;
    inset-block-start: 2px;
    inset-inline-end: 2px;

    & .wish-btn {
      min-inline-size: 0;
      min-block-size: 0;
      padding: 4px;
      border-color: transparent;
      background: transparent;
      gap: 0;

      &:hover { background: transparent; }
    }

    & .wish-btn--active:hover {
      background: transparent;
    }

    & .wish-btn__icon {
      inline-size: 14px;
      block-size: 14px;
    }
  }

  /* ── NOW line ────────────────────────────────────────────────────── */

  .gantt__now {
    position: absolute;
    inset-inline: 0;
    block-size: 2px;
    background: oklch(var(--lch-laser));
    box-shadow: 0 0 8px color-mix(in oklch, oklch(var(--lch-laser)) 40%, transparent);
    z-index: 3;
    pointer-events: none;
  }

  .gantt__now-pill {
    position: absolute;
    inset-inline-start: 0;
    inset-block-start: -11px;
    padding: 0.125rem 0.5rem;
    background: oklch(var(--lch-laser));
    color: oklch(17% 0.02 276);
    font-size: 0.6875rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    border-radius: var(--radius-sm);
  }
}
