/* The stage board: an intake tray above hand-ordered columns, every column
   collapsing to a vertical edge pill, terminal stages starting collapsed. On a
   phone the columns snap, one flick at a time. Board grammar per
   docs/planning/fizzy-kanban-v2.md and HANSHI.md (Boards).

   Drag state lives in drag_and_drop.css, unqualified, so every draggable gets
   it — see the note there.

   Element selectors here are always scoped inside a component class; a bare
   element rule in this layer outranks every :where() the embedded Lexxy editor
   ships, whatever the specificity. See inputs.css. */
@layer components {
  /* The board takes the whole window but not more than fizzy's 1400px cap,
     centred — a three-column board floats in the middle of a wide screen
     instead of leaning on its left edge (user, 2026-08-07). */
  .board {
    display: grid;
    gap: var(--block-space);
    inline-size: 100%;
    max-inline-size: 87.5rem;
    margin-inline: auto;
  }

  /* The arrivals row: the intake tray with the Not now rail riding at its end
     — what has not been placed, and what has been set aside, side by side
     above the flow (user, 2026-08-07; fizzy stands its rail beside triage).
     The rail takes the tray's own height here, not the columns' 12rem. */
  .board__triage {
    display: flex;
    align-items: stretch;
    gap: var(--inline-space-double);
  }

  .board__triage .board__column:not([open]) {
    min-block-size: auto;
  }

  /* Intake is a tray, not a column: what has arrived and has not been placed.
     Dashed, because nothing here is committed yet. The label and the cards
     share one line so the tray stays a band above the board rather than a
     second row of columns. */
  .board__intake {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--block-space-half) var(--inline-space-double);
    flex: 1 1 auto;
    border: var(--border-size) dashed var(--color-line);
    border-radius: var(--border-radius);
    padding: var(--block-space-half) var(--inline-space-double);
  }

  .board__intake-cards {
    display: flex;
    flex-wrap: wrap;
    gap: var(--block-space-half) var(--inline-space);
    flex: 1 1 auto;
  }

  /* An intake card is one line: the name, then where it came from. Cards hug
     their content — the tray reads as a handful of arrivals, not a grid. */
  .board__intake .board-card {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--inline-space-half);
    flex: 0 1 auto;
    max-inline-size: 100%;
  }

  .board__columns {
    display: flex;
    align-items: flex-start;
    gap: var(--inline-space-double);
    overflow-x: auto;
    padding-block-end: var(--block-space);
  }

  .board__column {
    flex: 0 0 30ch;
    display: flex;
    flex-direction: column;
    gap: var(--block-space);
  }

  .board__column summary {
    display: flex;
    align-items: center;
    gap: var(--inline-space);
    cursor: pointer;
    list-style: none;
  }

  .board__column summary::-webkit-details-marker {
    display: none;
  }

  /* A column head is text, not a heading shouted in bold: the stage name sits
     one step above its count and nothing else competes. */
  .board__column summary h3 {
    font-weight: 500;
    color: var(--color-ink);
  }

  /* The name is a link to the column's own page (user, 2026-08-07 — BC's
     grammar), spoken in the head's own ink: the underline appearing on hover
     is the whole affordance, the way a written line invites. The hover itself
     is drawn in rows.css, which owns that one voice for every heading that is
     a link — this file lists no `.row` rule of its own. */
  .board__title {
    color: inherit;
    text-decoration: none;
  }

  /* A faint count beside the stage name, never a badge (reference 05). The
     component owns the size and the ink now: it used to ride on `txt-small
     txt-subtle` in the markup, which sits in @layer utilities and so quietly
     outranked anything said here. Tabular figures stop the head jiggling when
     the controller bumps the number mid-drag. */
  .board__count {
    font-size: var(--text-small);
    color: var(--color-ink-faint);
    font-variant-numeric: tabular-nums;
  }

  /* The corner controls wait for the pointer. Opacity, not display — both are
     buttons that must stay in the tab order, and focus has to reveal them or
     the keyboard lands on something invisible. The collapse button pushes the
     pair to the end. */
  .board__column summary .board__collapse {
    margin-inline-start: auto;
  }

  /* The disc the circle button wears elsewhere reads as a blob here, between
     the intake's dashed edge and the column's own (user, 2026-08-07 — the ⋯
     looked odd on the board). A variant retunes rather than restates: drop
     the wash and the ink darkening is the whole hover, as it is on a card. */
  .board__column summary .btn--circle {
    --btn-background-hover: transparent;

    opacity: 0;
    transition: opacity var(--speed-quick) var(--ease-out);
  }

  .board__column summary:hover .btn--circle,
  .board__column summary .btn--circle:focus-visible {
    opacity: 1;
  }

  /* Nothing hovers on a touch screen; there the controls are simply there —
     said once for every pointer-waiting control in hover-reveals.css. */

  /* One button, two promises: the visible glyph is the opposite of what the
     column currently is. */
  .board__column[open] .board__expand-glyph,
  .board__column:not([open]) .board__collapse-glyph {
    display: none;
  }

  /* Collapsed: a vertical rail at the edge of the board — the count up top,
     the name written down the spine, a hairline running out the rest of the
     height (fizzy's collapsed column, spoken in ink — HANSHI Deviations).
     Still a drop target, which is why a finished stage stays on the board at
     all. It stretches to the row so the rail reads as a place, not a stub. */
  .board__column:not([open]) {
    flex: 0 0 auto;
    align-self: stretch;
    min-block-size: 12rem;
  }

  .board__column:not([open]) summary {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: var(--block-space-half);
    writing-mode: vertical-rl;
    padding: var(--inline-space) var(--block-space-half);
    background-color: var(--color-canvas);
    border: var(--border);
    border-radius: var(--border-radius);
    color: var(--color-ink-subtle);
  }

  /* The count rides on top, upright — the one glance a closed column owes.
     The expand button follows it, upright too and simply there: a rail has no
     hover to speak of, and a hidden way back in is no way back in. */
  .board__column:not([open]) .board__count {
    order: -2;
    writing-mode: horizontal-tb;
  }

  .board__column:not([open]) .board__collapse {
    order: -1;
    margin-inline-start: 0;
    writing-mode: horizontal-tb;
    opacity: 1;
  }

  /* The hairline that finishes the rail: where the cards would be, a string. */
  .board__column:not([open]) summary::after {
    content: "";
    flex: 1 1 auto;
    align-self: center;
    block-size: var(--border-size);
    background-color: var(--color-line);
  }

  /* A rail carries no menu — fizzy's own rule for its edge columns; ours
     extends it to every closed one. Open it, and the ⋯ is back. */
  .board__column:not([open]) summary [popovertarget] {
    display: none;
  }

  /* Tall enough that two cards and some air still read as a place to work,
     not a shelf (user, 2026-08-06 — BC's breathing room). */
  .board__column ul {
    display: grid;
    align-content: start;
    gap: var(--block-space-half);
    min-block-size: 12rem;
  }

  /* An empty column has to look droppable, not blank — and say so: fizzy's
     "Drag cards here", a dashed footing with the invitation written faint.
     :has(), not :empty — the template leaves whitespace text nodes behind,
     and so do Turbo removals. The hint takes over the empty list's whole
     footing (the list gives up its height and border to it), and the moment
     anything is in the list — a card, the drop ghost — the hint is gone. */
  .board__column ul:not(:has(*)) {
    border: var(--border-size) dashed var(--color-line);
    border-radius: var(--border-radius);
  }

  .board__column ul:not(:has(*)):has(+ .board__drop-hint) {
    min-block-size: 0;
    border: none;
  }

  .board__drop-hint {
    display: grid;
    place-content: center;
    min-block-size: 12rem;
    border: var(--border-size) dashed var(--color-line);
    border-radius: var(--border-radius);
    font-size: var(--text-small);
    color: var(--color-ink-faint);
  }

  .board__column ul:has(*) + .board__drop-hint {
    display: none;
  }

  /* Cards stay terse: name, value, owner, at most one chip. Paper on paper,
     held by a hairline — no frame heavier than the data inside it. */
  .board-card {
    padding: var(--block-space-half) var(--inline-space-double);
    background-color: var(--color-canvas);
    border: var(--border);
    border-radius: var(--border-radius);
    cursor: grab;
  }

  /* Hover darkens the hairline — the same move a written line makes. */
  .board-card:hover {
    border-color: var(--color-ink-faint);
  }

  .board-card a {
    color: var(--color-ink);
    text-decoration: none;
    font-weight: 500;
  }

  @container main (max-width: 70ch) {
    .board__columns {
      scroll-snap-type: inline mandatory;
    }

    /* One flick, one column: skipping three at a time is tolerable on a short
       todo board and wrong on a nine-stage pipeline. Fizzy omits this. */
    .board__columns > * {
      scroll-snap-align: center;
      scroll-snap-stop: always;
    }

    /* Nearly the whole width, with the neighbours peeking either side. */
    .board__column[open] {
      flex-basis: calc(100% - var(--inline-space-double) * 3);
    }
  }
}
