/* Capped so that three columns of short titles stay close together. Full
   width spread them 448px apart at 1440px. A grid of four or more columns
   needs the room, so it keeps the whole window. */
.start-page {
  width: 100%;
  max-width: min(76rem, 100% - 2em);

  &:has(.start-page-grid:is([data-columns="4"], [data-columns="5"], [data-columns="6"])) {
    max-width: calc(100% - 2em);
  }
}

.start-page-header {
  position: fixed;

  display: flex;
  justify-content: right;
  align-items: center;
  background: var(--bg-color);
  box-shadow: none;
  box-sizing: border-box;
  padding: 0 1em 1em;

  svg {
    display: block;
    height: 1.25em;
    margin: 0;
  }

  h1 {
    margin: 0;
    color: var(--fg-color);
    font-size: 1.25rem;
  }
}

.start-page-actions {
  display: flex;
  gap: 0.5em;
}

.button-link {
  background: var(--bg-color);
  fill: var(--mid-color);
  color: var(--mid-color);
  text-decoration: none;
  font-size: 0.875em;
  height: auto;
  transition: none;

  svg {
    fill: var(--mid-color);
  }

  &:hover {
    color: var(--fg-color);
    box-shadow: none;
    svg {
      fill: var(--fg-color);
    }
  }
}

.start-page-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem 3rem;
  margin: 2em 0 3.5em;

  /* A label, not a heading: smaller than the links under it, and set apart
     from them by case, tracking and the accent. The tiles are what you read;
     the name only says where a group starts. */
  section > h2 {
    margin: 0 1rem 0.5rem;
    padding-bottom: 0.5rem;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--highlight-color);
    border-bottom: 0.0625rem solid var(--border-color);
  }

  ul {
    display: flex;
    flex-direction: column;
    gap: 0em;
    margin: 0;
    padding: 0;
    list-style: none;

    &.drop-zone-active {
      background-color: var(--bg-highlight-color);
      border: 0.125rem dashed var(--highlight-color);
      border-radius: 0.5em;
      padding: 0.5em;
      margin: 0.25em 0;
      transition: all 0.2s ease;
    }
  }

  li a {
    font-size: 1.0625rem;
    color: var(--fg-color);
    display: block;
    padding: 0.25rem 1rem;
    border-radius: 0.5rem;

    &:hover {
      text-decoration: none;
      background-color: var(--accent-wash);
    }
  }

  /* Responsive - Tablets */
  @media screen and (min-width: 45em) {
    &[data-columns="2"] {
      grid-template-columns: repeat(2, 1fr);
    }

    &[data-columns="3"] {
      grid-template-columns: repeat(3, 1fr);
    }
  }

  /* Responsive - Desktop */
  @media screen and (min-width: 60em) {
    &[data-columns="2"] {
      grid-template-columns: repeat(2, 1fr);
    }

    &[data-columns="3"] {
      grid-template-columns: repeat(3, 1fr);
    }

    &[data-columns="4"] {
      grid-template-columns: repeat(4, 1fr);
    }

    &[data-columns="5"] {
      grid-template-columns: repeat(5, 1fr);
    }

    &[data-columns="6"] {
      grid-template-columns: repeat(6, 1fr);
    }
  }
}

/* More space between groups than between the tiles in a group, so the
   spacing alone says which tiles belong together. */
.start-page-column {
  display: flex;
  flex-direction: column;
  gap: 2.25rem;

  h3 {
    font-size: 0.75em;
    text-align: center;
    text-transform: uppercase;
    margin: 0;
  }

  &.drop-zone-active {
    background-color: var(--bg-highlight-color);
    border: 0.125rem dashed var(--highlight-color);
    border-radius: 0.5em;

    h3 {
      color: var(--highlight-color);
      font-weight: bold;
    }
  }
}

.command-bar {
  position: relative;
  margin-bottom: 2.5rem;

  /* A magnifier, so the box reads as search before anyone types. It is drawn
     in CSS as a mask, so it takes --mid-color in both themes, and the markup
     the controller reads stays as it is. */
  &::before {
    content: "";
    position: absolute;
    left: 1.125rem;
    top: 50%;
    translate: 0 -50%;
    width: 1.125rem;
    height: 1.125rem;
    background: var(--mid-color);
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='m15.5 15.5 5 5'/%3E%3C/svg%3E") center / contain no-repeat;
    pointer-events: none;
  }

  input {
    width: 100%;
    padding: 0.875rem 1rem 0.875rem 3rem;
    border: 0.0625rem solid var(--border-color);
    border-radius: 0.75rem;
    font-size: 1.0625rem;
    background: var(--bg-color);
    color: var(--fg-color);
    box-sizing: border-box;
    transition: none;

    &::placeholder {
      color: var(--mid-color);
    }

    &:focus {
      outline: none;
      border-color: var(--highlight-color);
      /* Relative colour syntax: rgba() cannot hold an oklch() accent, and the
         browser drops the whole declaration when it tries. */
      box-shadow: 0 0 0 0.25rem oklch(from var(--highlight-color) l c h / 0.22);
    }
  }
}

/* A panel that floats over the grid: a shadow and spacing separate the rows,
   not rules between them. */
.command-bar-suggestions {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--bg-color);
  border: 0.0625rem solid var(--border-color);
  border-radius: 0.75rem;
  margin-top: 0.5rem;
  padding: 0.375rem;
  box-shadow: 0 1.125rem 2.5rem -0.75rem oklch(0 0 0 / 0.25);
  max-height: 300px;
  overflow-y: auto;
  z-index: 1000;
  display: none;
}

/* The title wraps if it has to, and the URL stays on one line and ends in an
   ellipsis. A long URL used to take a second line on its own. */
.command-bar-suggestion {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.625rem 0.75rem;
  border-radius: 0.5rem;
  cursor: pointer;

  &:hover,
  &.selected {
    background: var(--accent-wash);
  }
}

.suggestion-title {
  font-weight: 600;
  color: var(--fg-color);
}

.suggestion-url {
  flex: 1 1 12rem;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 0.875em;
  color: var(--mid-color);
}

/* The same label as a group name on the page. Uppercase is CSS, so a test
   that reads innerText sees "FROM 127.0.0.1". */
.command-bar-section-header {
  padding: 0.75rem 0.75rem 0.25rem;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mid-color);
}

.command-bar-searching,
.command-bar-notice {
  padding: 0.625rem 0.75rem;
  color: var(--mid-color);
  font-style: italic;
}

.start-page-empty {
  margin: 0;
  padding: 3em 1em;
  text-align: center;
  color: var(--mid-color);
}

.group-header {
  display: flex;
  align-items: center;
  margin: 0 0.5em 0.25em;
  border-bottom: 0.0625rem solid var(--border-color);
  gap: var(--control-gap);
  min-height: var(--control-size);
}

/* The accent, like the group labels on the start page, but in the name's own
   case: this is where a group is renamed, so it shows the name as stored. */
.group-name {
  flex: 1;
  font-weight: 600;
  color: var(--highlight-color);
  overflow-wrap: break-word;
}

.start-page-group {
  transition: opacity 0.2s ease, transform 0.2s ease;

  &.dragging {
    opacity: 0.5;
    transform: rotate(5deg);
  }
}

.start-page-item {
  transition: opacity 0.2s ease, transform 0.2s ease;

  &.dragging {
    opacity: 0.5;
    transform: rotate(2deg);
  }

  &.editable {
    border: 1px solid transparent;
    border-radius: var(--control-radius);
    transition: 0.2s ease-out all;
  }
}

/* The drop zone for a group's tiles. An empty group has nothing in here, and a
   zero-height target cannot be dragged into — the placeholder text used to hold
   it open by accident, so the floor has to be deliberate. */
.group-items {
  min-height: var(--control-size);
}

.item-row {
  display: flex;
  align-items: center;
  gap: var(--control-gap);
  padding: 0.25em 0.5em;
  min-height: var(--control-size);
}

.item-title {
  flex: 1;
  overflow-wrap: break-word;
}

/* One size for every control in the editor: handles, icon buttons, inputs and
   submits alike. Anything that lands in a row with the others measures
   --control-size and nothing else. */
.drag-handle,
.item-actions button {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  flex: none;
  height: var(--control-size);
  border-radius: var(--control-radius);
  border: none;
  cursor: pointer;
  padding: 0;

  svg {
    display: block;
    /* The icons are full-bleed in their viewBox, so the inset has to come from
       here or the glyph runs edge to edge. */
    width: 1.5rem;
    height: 1.5rem;
    fill: var(--border-color);
    margin: 0;
  }

  &:hover svg {
    fill: var(--fg-color);
    fill-opacity: 0.5;
  }
}

.drag-handle {
  cursor: grab;
  user-select: none;

  &:active {
    cursor: grabbing;
  }
}

.item-actions button {
  background: var(--bg-color);
  color: var(--fg-color);
  font-size: 1rem;
}

.item-actions {
  display: flex;
  gap: var(--control-gap);

  .remove-button:hover svg {
    fill: var(--danger-color);
  }
}

/* A row's controls stay faint until the row is in play: hovered, or focused
   by the keyboard highlight, which also covers a row that is picked up. With
   three controls on every tile they outweighed the titles. Opacity, not
   display or visibility, so nothing moves and a pointer can still find them.
   TestBrowserTheHighlightedRowShowsItsControls holds the keyboard half. */
:is(.item-row, .group-header) :is(.drag-handle, .item-actions button) {
  opacity: 0.35;
  transition: opacity 0.15s ease;
}

:is(.item-row, .group-header):is(:hover, :focus-visible, :focus-within) :is(.drag-handle, .item-actions button) {
  opacity: 1;
}

/* --- inline add / edit forms ---
   The trigger and the form it guards are both in the DOM; inline_form_controller
   swaps which one is hidden. */

.inline-form-slot {
  margin: 0.25em 0.5em 0;
}

.add-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  gap: 0.375em;
  width: 100%;
  height: var(--control-size);
  padding: 0 0.5em;
  font: inherit;
  font-size: 0.875em;
  color: var(--mid-color);
  background: transparent;
  border: 0.0625rem dashed var(--border-color);
  border-radius: var(--control-radius);
  cursor: pointer;
  transition: 0.2s ease-out all;

  svg {
    display: block;
    width: 1rem;
    height: 1rem;
    /* The icons are solid chips with the glyph knocked out, so this has to
       match the resting weight of the row's other buttons or the plus reads
       as the heaviest thing in the column. */
    fill: var(--border-color);
    margin: 0;
  }

  /* The label is a flex item, so it is a block, and text-box reaches it.
     Trimmed to the capitals, flex centres the letters and not the line box,
     which put them 1px low in Literata. See .action-button in buttons.css. */
  span {
    text-box: trim-both cap alphabetic;
  }

  &:hover {
    color: var(--fg-color);
    border-color: var(--highlight-color);
    border-style: solid;

    svg {
      fill: var(--highlight-color);
    }
  }
}

.inline-form {
  padding: 0.5em;
  background: var(--bg-highlight-color);
  border-radius: var(--control-radius);
}

.inline-form-body {
  display: flex;
  flex-direction: column;
  gap: var(--control-gap);
  max-width: none;
}

.inline-form-actions {
  display: flex;
  gap: var(--control-gap);
}

/* These beat forms.css's input[type=text] (0,1,1) on specificity rather than on
   load order — the class-only .group-name-field this replaces lost that fight
   and its padding never applied. */
.start-page-grid input.control,
.start-page-grid button.control {
  box-sizing: border-box;
  width: 100%;
  height: var(--control-size);
  margin: 0;
  padding: 0 0.5em;
  font: inherit;
  font-size: 0.875em;
  border-radius: var(--control-radius);
}

/* Their labels sat 1px low in Literata, for the reason .action-button's did
   (buttons.css). A button centres its own content, so trimming the text box
   to the capitals is all it takes. The submits are <button>s and not inputs
   because Safari does not trim inside an input. Not on the text fields:
   there it would shorten the caret. */
.start-page-grid button.control {
  text-box: trim-both cap alphabetic;
}

.start-page-grid input[type="text"].control,
.start-page-grid input[type="url"].control {
  color: var(--fg-color);
  background: var(--bg-color);
  border: 0.0625rem solid var(--border-color);
  outline: medium solid var(--bg-color);
  transition: 0.3s ease outline;

  &:focus {
    border-color: var(--highlight-color);
    outline: medium solid var(--highlight-color);
  }
}

.start-page-grid button[type="submit"].control {
  flex: 1;
  font-weight: bold;
  color: var(--button-fg-color);
  background: var(--button-bg);
  border: none;
  cursor: pointer;
}

.start-page-grid button.control.secondary {
  flex: 1;
  color: var(--fg-color);
  background: var(--bg-color);
  border: 0.0625rem solid var(--border-color);
  cursor: pointer;

  &:hover {
    background: var(--bg-highlight-color);
  }
}

.form-errors {
  margin: 0 0 0.25em;
  padding-left: 1.25em;
  color: var(--danger-color);
  font-size: 0.75em;
}

.potential-drop-target {
  background-color: oklch(from var(--highlight-color) l c h / 0.1);
  border: 0.125rem solid oklch(from var(--highlight-color) l c h / 0.3);
  border-radius: 0.5em;
  transition: all 0.2s ease;

  ul {
    padding: 0.5em;
    margin: 0.25em 0;
  }

  .start-page-column {
    background-color: oklch(from var(--highlight-color) l c h / 0.05);
  }
}

.hidden {
  display: none !important;
}

/* Shown when the connected app's token has been rejected — federated search is off
   until someone reconnects. */
.search-disconnected {
  max-width: 40em;
  margin: 0 auto 1em;
  padding: 0.75em 1em;
  border: 0.0625rem solid var(--danger-color);
  border-radius: 0.5em;
  color: var(--danger-color);
  font-size: 0.875em;
  text-align: center;

  code {
    font-family: ui-monospace;
    overflow-wrap: anywhere;
  }
}
