/*
 * Dictionary V2 grid — Notion / Sheets-like editable table.
 *
 * Built on top of Tabler's `card-table` styling. Adds five things
 * Tabler doesn't ship out of the box:
 *  1. Flush in-cell inputs that sit transparently inside `<td>`s,
 *     reveal a focus ring + light hover state, so the table reads
 *     as a sheet rather than a wall of form controls.
 *  2. Sticky header with an explicit bottom border so the
 *     row-separator doesn't scroll away with the first body row.
 *  3. Notion-style overhang affordances — col / row drag pills
 *     overhang the table's outer edges, "+" Add column floats at
 *     the top-right, "x" Row delete at the right of each row.
 *  4. Cell-rectangle multi-selection (Sheets-style) with azure
 *     tint + four-edge outline; classes stamped by the
 *     dictionary-grid Stimulus controller.
 *  5. A 0.875rem cell font so 4-5 column grids breathe on a
 *     typical project page.
 *
 * Markup contract (see app/views/dictionaries/show.html.erb):
 *
 *   <div class="card">
 *     <div class="dict-grid__wrapper">
 *       <table class="table table-vcenter card-table dict-grid"
 *              data-controller="dictionary-grid"
 *              data-dictionary-grid-paste-url-value="…">
 *         <thead><tr>
 *           <th data-sortable-id="…">
 *             <button class="dict-grid__col-drag">⋮⋮⋮</button>
 *             <span class="fw-bold">Label</span>
 *             <button class="dict-grid__col-edit">edit</button>
 *           </th>
 *         </tr></thead>
 *         <tbody><tr data-sortable-id="…">
 *           <td>
 *             <button class="dict-grid__row-drag">⋮</button>
 *             <form><input class="dict-grid__cell-input"
 *                          data-dictionary-grid-target="cell"></form>
 *             <form class="dict-grid__row-delete-floating">
 *               <button>×</button>
 *             </form>
 *           </td>
 *         </tr></tbody>
 *       </table>
 *     </div>
 *     <div class="dict-grid__add-rows">
 *       Add [N] more rows at the bottom
 *     </div>
 *     <button class="dict-grid__col-add-floating">+</button>
 *   </div>
 */

.dict-grid thead th {
  background: var(--tblr-bg-surface-tertiary, #f8f9fa);
  font-weight: 600;
  vertical-align: middle;
  /* Sticky header: pins the type/name row to the top of whichever
     scrolling ancestor wraps the table (the page scroll, or a
     `table-responsive` with vertical overflow). z-index keeps the
     header above hover-highlighted cells. The explicit border-bottom
     replaces the row-separator that card-table draws on the next
     row's border-top — without it, scrolling pulls the separator
     away with the first body row. */
  position: sticky;
  top: 0;
  z-index: 2;
  border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
}

.dict-grid td {
  padding: 0;
}

/* Tabler's `.card-table` adds extra padding-left to the first cell of
   every row (and the matching <th>) — that's correct for read-only
   data tables but here it shifts the first input so its focus ring
   no longer aligns with the other columns. Body cells (<td>) need
   to be zero on the edges so the input fills the cell and the
   row-drag pill in the left gutter lines up with x=0. Override with
   higher specificity than Tabler's `.card > .card-table:first-child
   > tbody > tr > td:first-child`. */
.dict-grid.card-table > tbody > tr > td:first-child,
.dict-grid.card-table > tbody > tr > td:last-child {
  padding-left: 0;
  padding-right: 0;
}

/* Header cells (<th>) keep symmetric horizontal padding regardless
   of position so the first column's label doesn't sit flush against
   the card edge. Matches the input's internal padding (0.75rem) so
   header label and body input align column-by-column. */
.dict-grid.card-table > thead > tr > th {
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

/* Column separators — light vertical hairlines between every cell so
   the table reads as a spreadsheet grid rather than a stack of rows.
   `+ td` / `+ th` skips the first column (no left edge to draw).
   The right-edge "+" / actions column gets a separator too via the
   same rule. */
.dict-grid th + th,
.dict-grid td + td {
  border-left: 1px solid var(--tblr-border-color, #e6e7e9);
}

.dict-grid__cell-input,
.dict-grid input.dict-grid__cell-input {
  border: 0;
  background: transparent;
  box-shadow: none;
  width: 100%;
  border-radius: 0;
  padding: 0.5rem 0.75rem;
  /* Match the body font-size token so the grid lines up with the
     case-records table (both inherit `--tblr-body-font-size`,
     0.8rem). Headers stay at the inherited weight so they remain
     dominant. */
  font-size: var(--tblr-body-font-size, 0.8rem);
}

.dict-grid__plain {
  padding: 0.5rem 0.75rem;
  font-size: var(--tblr-body-font-size, 0.8rem);
}

/* Hover bg only on cells NOT in the active selection. Otherwise
   the gray hover would mask the blue selection tint underneath
   (the input fills the cell, so its bg sits on top of the td bg). */
.dict-grid td:not(.is-selected):hover .dict-grid__cell-input {
  background: var(--tblr-bg-surface-secondary, #f8f9fa);
}

.dict-grid .dict-grid__cell-input:focus {
  background: var(--tblr-bg-surface, #fff);
  box-shadow: inset 0 0 0 2px var(--tblr-primary, #f76707);
}

/* Per-column edit pencil — hidden until the user hovers (or
   keyboard-focuses) the header cell. Different from the drag
   pills (which stay visible at low opacity) because the pencil
   carries a destructive secondary action and shouldn't be
   competing with the column label at rest. */
.dict-grid__col-edit,
.dict-grid__row-delete {
  opacity: 0;
  transition: opacity 0.12s ease-in-out;
}

.dict-grid th:hover .dict-grid__col-edit,
.dict-grid th:focus-within .dict-grid__col-edit {
  opacity: 1;
}

/* Notion-style column drag handle. Sits as a small floating pill
   above the column header — surfaced only on header hover so the
   header reads as calm at rest. The pill is anchored absolutely to
   the (sticky) <th>; -10px top makes it overhang slightly above
   the header strip for a clear "drag me" affordance. */
.dict-grid th {
  position: relative;
}

.dict-grid__col-drag {
  position: absolute;
  top: -10px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 1px 8px;
  background: var(--tblr-bg-surface, #fff);
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 999px;
  color: var(--tblr-secondary, #6c757d);
  cursor: grab;
  line-height: 1;
  z-index: 4;
  opacity: 0;
  transition: opacity 0.12s ease-in-out;
}

.dict-grid__col-drag:hover {
  background: var(--tblr-bg-surface-secondary, #f8f9fa);
}

.dict-grid__col-drag:active {
  cursor: grabbing;
}

/* Visible only on the specific column being hovered or focused —
   matches the row-delete X visibility model so the table reads as
   calm at rest. */
.dict-grid th:hover .dict-grid__col-drag,
.dict-grid th:focus-within .dict-grid__col-drag {
  opacity: 1;
}

/* SortableJS classes the dragged item with `.sortable-ghost` (the
   placeholder where it'll land) and `.sortable-chosen` (the picked
   item). Match the design system surface so the placeholder reads
   as a neutral target rather than the default purple Sortable
   defaults to in some setups. */
.dict-grid th.sortable-ghost {
  opacity: 0.4;
  background: var(--tblr-bg-surface-secondary, #f8f9fa);
}

/* Floating affordances — both the "+" Add column and the per-row
   "X" delete live OUTSIDE the table, in a right-side gutter the
   wrapper reserves via `padding-right`. The "+" anchors to the top
   of that gutter (header-row line); each row's "X" anchors to its
   last data cell and overflows into the gutter. Both render as
   small Tabler btn-icon-style buttons that fade in on hover. */

.dict-grid__wrapper {
  position: relative;
  /* No left or right gutter — every floating affordance overhangs
     its respective table edge directly (mirror of the column drag
     pill which overhangs the header's top edge). The card itself
     (with overflow visible) hosts the overhang. */
}

/* Shared visual style for the two floating icons (col-add "+" and
   row-delete "X"). Pill weight matches the col-drag and row-drag
   handles so all four affordances read as a coherent set. */
.dict-grid__floating-btn {
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--tblr-bg-surface, #fff);
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  color: var(--tblr-secondary, #6c757d);
  padding: 0;
  line-height: 1;
  z-index: 4;
  opacity: 0;
  transition: opacity 0.12s ease-in-out, background 0.12s;
}

.dict-grid__floating-btn:hover {
  background: var(--tblr-bg-surface-secondary, #f8f9fa);
}

/* "+" Add column — overhangs the table's right edge at header
   level. Fades in when the user is anywhere over the table wrapper. */
.dict-grid__col-add-floating {
  position: absolute;
  top: 10px;
  right: -13px;
}

.dict-grid__wrapper:hover .dict-grid__col-add-floating,
.dict-grid__wrapper:focus-within .dict-grid__col-add-floating {
  opacity: 1;
}

/* Per-row "X" delete — positioned absolutely inside the row's last
   data cell with `right: -13px` so it overhangs the table's right
   edge by ~half the pill's width. Mirrors the row-drag pill at
   left: -10px on the other side. */
.dict-grid tbody td:last-child {
  position: relative;
}

.dict-grid__row-delete-floating {
  position: absolute;
  top: 50%;
  right: -13px;
  transform: translateY(-50%);
}

.dict-grid tbody tr:hover .dict-grid__row-delete-floating {
  opacity: 1;
}

/* Per-row left-gutter affordances — a Notion-style pair of pills
   (insert-row "+" and drag handle) that live OUTSIDE the table on
   the left side of the first cell. The cluster is absolutely
   positioned against the first cell and pushed far enough left
   that its right edge sits just past the table's left border, so
   no part of either button covers the cell content. Visible only
   on row hover. */
.dict-grid tbody td:first-child {
  position: relative;
}

.dict-grid__row-actions {
  position: absolute;
  top: 50%;
  /* Two ~16px pills + a 4px gap = ~36px cluster, plus a 6px
     breathing gap to the cell border. Tweakable per design. */
  left: -42px;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  z-index: 4;
  opacity: 0;
  transition: opacity 0.12s ease-in-out;
}

/* Visible only on the row currently under the mouse — intentionally
   no `:focus-within` trigger so clicking a cell doesn't stick the
   gutter pills on the row whose cell last had focus. */
.dict-grid tbody tr:hover .dict-grid__row-actions {
  opacity: 1;
}

/* Shared pill styling for both gutter buttons. Matches the column
   drag handle's surface / border weight so the four affordances
   (col-drag, row-add, row-drag, row-delete) read as one set. */
.dict-grid__row-add,
.dict-grid__row-drag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px 1px;
  background: var(--tblr-bg-surface, #fff);
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 999px;
  color: var(--tblr-secondary, #6c757d);
  line-height: 1;
}

.dict-grid__row-add:hover,
.dict-grid__row-drag:hover {
  background: var(--tblr-bg-surface-secondary, #f8f9fa);
}

.dict-grid__row-add { cursor: pointer; }
.dict-grid__row-drag { cursor: grab; }
.dict-grid__row-drag:active { cursor: grabbing; }

.dict-grid tr.sortable-ghost {
  opacity: 0.4;
  background: var(--tblr-bg-surface-secondary, #f8f9fa);
}

/* Cell-rectangle selection — Sheets-style. The JS controller
   stamps `.is-selected` on every <td> inside the active rectangle
   plus `.is-selection-{top,right,bottom,left}` on the cells at
   the rectangle's outer edges. Bg tint comes from `.is-selected`;
   the four-CSS-variable trick lets the corner cells compose
   borders on multiple sides via a single multi-shadow declaration.
   td-level rule wins over the alternating card-table row stripe. */
.dict-grid tbody td.is-selected {
  background: rgba(66, 153, 225, 0.12);
  --sel-top:    0 0 0 0 transparent;
  --sel-right:  0 0 0 0 transparent;
  --sel-bottom: 0 0 0 0 transparent;
  --sel-left:   0 0 0 0 transparent;
  box-shadow: var(--sel-top), var(--sel-right), var(--sel-bottom), var(--sel-left);
}

.dict-grid tbody td.is-selection-top    { --sel-top:    inset 0  1px 0 var(--tblr-azure, #4299e1); }
.dict-grid tbody td.is-selection-right  { --sel-right:  inset -1px 0 0 var(--tblr-azure, #4299e1); }
.dict-grid tbody td.is-selection-bottom { --sel-bottom: inset 0 -1px 0 var(--tblr-azure, #4299e1); }
.dict-grid tbody td.is-selection-left   { --sel-left:   inset 1px  0 0 var(--tblr-azure, #4299e1); }

/* While the user is actively editing a cell, hide ONLY the column
   drag pill (which sits at the top-edge of the header and would
   compete with the focus ring on the cell directly below). Row
   drag pills sit on the left gutter — out of the way of any focused
   cell — and double as the row-select affordance, so they stay
   visible at reduced opacity even while a cell is focused. */
.dict-grid:focus-within thead th .dict-grid__col-drag {
  opacity: 0;
}

/* Bottom-right Tabler-styled toast surfaced by the dictionary-grid
   stimulus controller after a bulk paste, carrying the rows-written
   / cells-skipped summary from the /rows/paste response. */
.dict-grid__toast {
  position: fixed;
  bottom: 1rem;
  right: 1rem;
  z-index: 1080;
  margin-bottom: 0;
  box-shadow: 0 6px 16px -4px rgba(0, 0, 0, 0.15);
}

/* Choice-cell combobox: dropdown menu floats over the grid (overlay)
   instead of growing the row inline. Anchored to the cell wrapper,
   width matches the cell, z-index above the grid's sticky header. */
.dict-choice-cell {
  position: relative;
}

.dict-choice-cell__menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1050;
  min-width: 100%;
  width: max-content;
  max-width: 24rem;
  margin-top: 2px;
  background: var(--tblr-bg-surface, #ffffff);
  border: 1px solid var(--tblr-border-color, rgba(0, 0, 0, 0.125));
  border-radius: var(--tblr-border-radius, 4px);
  box-shadow: 0 6px 16px -4px rgba(0, 0, 0, 0.15);
  padding: 0.25rem 0;
  max-height: 16rem;
  overflow-y: auto;
}

.dict-choice-cell__menu .dropdown-menu {
  box-shadow: none;
  border: 0;
  margin: 0;
  padding: 0;
  background: transparent;
  position: static;
}
