/*
 * Dynamic-forms builder shell.
 *
 * Propshaft's `stylesheet_link_tag :app` links EVERY file in this directory on
 * EVERY page, so every selector here MUST be scoped under the `.builder` body
 * class or it will leak into the rest of the app.
 *
 * Remember `html { font-size: 62.5% }` — 1rem = 10px.
 */

body.builder {
  display: grid;
  grid-template-rows: 5.6rem 1fr;
  height: 100vh;
  margin: 0;
  overflow: hidden;
  font-family: var(--body-font);
}

.builder .builder__top-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing);
  padding: 0 2rem;
  background: #000;
  color: #fff;
}

.builder .builder__top-bar-brand {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-width: 0;
}

/* The way out. Sized like a target rather than a glyph so it can be hit
   without aiming, and quiet until it is wanted. */
.builder .builder__back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.8rem;
  height: 2.8rem;
  margin-left: -0.6rem;
  font-size: 1.8rem;
  line-height: 1;
  color: #bbb;
  text-decoration: none;
}

.builder a.builder__back:hover {
  color: #fff;
}

.builder .builder__logo {
  display: block;
  max-height: 3.2rem;
  width: auto;
}

.builder .builder__form-name {
  font-size: 1.6rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/*
 * Beside the name the pill is a qualifier rather than a status of its own, so
 * it is set smaller and tighter. Scoped to the bar: the rail's pill stands on
 * its own line and keeps its size.
 *
 * NO text-transform. The pill's words are what the version state is asserted
 * by (publishes_a_form_test reads "Published v1" off this bar), and Chrome
 * transforms innerText along with the rendering — the version number would
 * have been shouted too.
 */
.builder .builder__top-bar-brand .builder__pill {
  flex-shrink: 0;
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.builder .builder__top-bar-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-shrink: 0;
}

/* The only gold thing on a black bar: publishing is the one action in the
   builder that changes what a brand ambassador sees. Gold background means
   WHITE text, everywhere in the redesign. */
.builder .builder__publish {
  padding: 0.9rem 1.8rem;
  font-family: inherit;
  font-size: 1.3rem;
  font-weight: 600;
  color: #fff;
  background: var(--primary);
  border: 0;
  border-radius: 3px;
  cursor: pointer;
}

.builder .builder__publish:hover {
  background: #d3ae3d;
}

.builder .builder__shell {
  display: grid;
  grid-template-columns: 26rem 1fr 30rem;
  min-height: 0;
}

.builder .builder__palette {
  background: #fff;
  border-right: 1px solid var(--light-border-color);
  overflow-y: auto;
}

.builder .builder__canvas {
  background: #f5f5f5;
  overflow-y: auto;
}

.builder .builder__rail {
  background: #fff;
  border-left: 1px solid var(--light-border-color);
  overflow-y: auto;
}

/* --------------------------------------------------------------- Palette */

/* An instruction, not a label: the palette is the one place in the builder
   that asks the admin to do something. */
.builder .builder__palette-heading {
  margin: 0;
  padding: 2rem 2rem 1.5rem;
  font-size: 1.5rem;
  font-weight: 600;
  color: #242424;
}

.builder .builder__palette-tiles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  padding: 0 2rem 3rem;
}

/*
 * Section headings live in the grid rather than around their tiles — see the
 * component: SortableJS only manages its element's direct children, so the
 * tiles have to stay directly in here. Spanning both columns is what makes
 * them read as headings rather than as a first tile.
 */
.builder .builder__palette-section {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #888;
}

.builder .builder__palette-section ~ .builder__palette-section {
  margin-top: 1rem;
}

.builder .builder__palette-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  padding: 1.4rem 0.8rem;
  text-align: center;
  background: #fff;
  border: 1px solid var(--light-border-color);
  border-radius: 3px;
  cursor: grab;
}

.builder .builder__palette-tile:hover {
  border-color: var(--primary);
}

.builder .builder__palette-tile-icon {
  font-size: 1.6rem;
  color: var(--primary);
}

.builder .builder__palette-tile-label {
  font-size: 1.2rem;
  line-height: 1.3;
  color: #242424;
}

/* ---------------------------------------------------------------- Canvas */

.builder .builder__canvas-inner {
  max-width: 72rem;
  margin: 0 auto;
  padding: 3rem 2rem 6rem;
}

/* Same box as the list of cards, so the header lines up with them exactly. */
.builder .builder__canvas-header {
  max-width: 72rem;
  margin: 0 auto;
  padding: 3rem 2rem 0;
}

.builder .builder__canvas-header + .builder__canvas-inner {
  padding-top: 1.5rem;
}

/*
 * The form itself, at the head of its own preview. The gold edge marks it as
 * the one card on the canvas that is not a field — nothing here can be
 * dragged, selected or deleted.
 */
.builder .builder__form-card {
  padding: 2rem 2.5rem 2.5rem;
  background: #fff;
  border: 1px solid var(--light-border-color);
  border-top: 3px solid var(--primary);
  border-radius: 3px;
}

.builder .builder__form-card-name {
  margin: 0;
  font-size: 2.4rem;
  font-weight: 400;
  line-height: 1.3;
  color: #242424;
}

.builder .builder__form-card-description {
  margin: 0.8rem 0 0;
  font-size: 1.4rem;
  line-height: 1.5;
  color: #888;
}

/*
 * Conditional fields ship with `class="hidden"` so the BA-side
 * conditional-fields controller can reveal them. On the canvas every field
 * must be visible, so the utility is undone *inside the canvas only* —
 * components/utilities.css stays untouched. Only for DIVs: the upload well
 * hides its raw file input behind the same utility, and that one must stay
 * hidden — the well itself is the control.
 */
.builder .builder__canvas div.hidden {
  display: block;
}

/*
 * On a BA's phone every control fills the screen, but the BA page's own form
 * styles are scoped to its layout and absent here, so the UA default left the
 * preview controls ragged. Stretching the text-like controls to their card is
 * both the design and the truer preview. Checkboxes and radios keep their size.
 */
.builder .builder__field-card-body input.form-control,
.builder .builder__field-card-body select,
.builder .builder__field-card-body textarea,
.builder .builder__field-card-child input.form-control,
.builder .builder__field-card-child select,
.builder .builder__field-card-child textarea {
  width: 100%;
  box-sizing: border-box;
}

.builder .builder__canvas-empty {
  margin: 0;
  padding: 6rem 0;
  text-align: center;
  font-size: 1.5rem;
  color: #888;
}

/* ----------------------------------------------------------- Field cards */

/*
 * The card is a container, not a box: its white box is `-main`, and a group's
 * children hang off it BELOW that box (see the component). Everything the
 * drag controller moves is one of these, children and all.
 */
.builder .builder__field-card {
  margin-bottom: 1.5rem;
}

.builder .builder__field-card-main,
.builder .builder__field-card-child {
  padding: 1.5rem 2rem 2rem;
  background: #fff;
  border: 1px solid var(--light-border-color);
  border-radius: 3px;
}

.builder .builder__field-card,
.builder .builder__field-card-child {
  cursor: pointer;
}

/*
 * Half-width fields render at half the canvas width, matching the BA-side
 * `.dynamic-field--half`. The modifier is standalone so it works on a card
 * and on a conditional child alike.
 */
.builder .builder__field-card--half {
  max-width: 50%;
}

/* The highlight goes round the white box the admin clicked on — on a parent
   that is `-main`, never the group hanging under it. */
.builder .builder__field-card--selected > .builder__field-card-main,
.builder .builder__field-card-child.builder__field-card--selected {
  outline: 2px solid var(--primary);
  outline-offset: -1px;
}

/* The grip floats over the card's corner, so the box needs to anchor it. */
.builder .builder__field-card-main,
.builder .builder__field-card-child {
  position: relative;
}

.builder .builder__field-card-main .builder__chips {
  margin-bottom: 1rem;
}

/*
 * Sized rather than shrink-wrapped around its icon: the grip is the drag
 * handle, so it needs a hit area that is there before Font Awesome has
 * swapped the icon in, and one that is comfortable to grab afterwards.
 * Absolutely positioned so it costs the card no height of its own.
 */
.builder .builder__grip {
  position: absolute;
  top: 1.2rem;
  right: 1.2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.8rem;
  height: 2rem;
  font-size: 1.4rem;
  color: #ccc;
  cursor: grab;
}

/*
 * The same handle on a child's smaller card. A class of its OWN rather than a
 * modifier of the one above: the canvas list drags by `.builder__grip` and
 * SortableJS matches a handle anywhere inside the card it is dragging, so a
 * child wearing that class — even alongside a modifier — would pick its whole
 * parent up. The child's own list drags by this one.
 */
.builder .builder__child-grip {
  position: absolute;
  top: 1rem;
  right: 1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.8rem;
  font-size: 1.2rem;
  color: #ccc;
  cursor: grab;
}

/*
 * The BA partial opens with an <h3> carrying the browser's own 1em top
 * margin. Under a chrome row that is now mostly grip, that margin reads as a
 * hole between the handle and the field's name, so it is closed here — inside
 * the canvas only, where the chrome is what precedes it.
 */
.builder .builder__field-card-body h3,
.builder .builder__field-card-child h3 {
  margin-top: 0;
}

.builder .builder__chips {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  flex-wrap: wrap;
}

/*
 * inline-FLEX with a gap rather than a margin on the icon: Font Awesome
 * rewrites the <i> into an <svg> after paint, so any selector naming the tag
 * stops matching the moment the page settles.
 */
.builder .builder__chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.2rem 0.8rem;
  border-radius: 3px;
  font-size: 1.2rem;
  line-height: 1.6;
  white-space: nowrap;
}

.builder .builder__chip--repeatable,
.builder .builder__chip--logic {
  color: var(--primary);
  background: rgba(189, 154, 52, 0.08);
  border: 1px solid var(--primary);
}

/*
 * A repeat group's members: inside the parent's white box, under the same rule
 * the BA's form draws between a repeatable field and the fields that repeat
 * with it (`.child-responses.border-top`). No rail and no chip — being in the
 * box IS what these fields have in common with the one above them.
 */
.builder .builder__field-card-members {
  margin-top: 1.6rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--light-border-color);
}

/* Tinted so a member reads as a panel WITHIN the white box rather than as a
   second card floating on top of it. Everything else a child card wears — its
   border, its padding, the anchor its grip is positioned against — already
   applies out here. */
.builder .builder__field-card-members .builder__field-card-child {
  background: #fafafa;
}

/*
 * An empty group's invitation, and the only thing giving that group's list a
 * box big enough for a pointer to aim at. Dashed, because what it outlines is
 * a space waiting to be filled rather than a field that is there.
 */
.builder .builder__field-card-members-hint {
  margin: 0;
  padding: 1.2rem;
  border: 1px dashed var(--light-border-color);
  border-radius: 3px;
  font-size: 1.3rem;
  color: #999;
  text-align: center;
}

/*
 * A group of CONDITIONAL children: indented behind a gold rail, on the canvas
 * rather than inside the parent's box. The rail is the whole treatment — the
 * wrapper has no background of its own, so each child reads as its own card.
 */
.builder .builder__field-card-children {
  margin-top: 1.2rem;
}

/* The rail belongs to the RUN, not the group: the gold line breaks between
 * two runs, so adjacent groups with different conditions read as separate. */
.builder .builder__field-card-run {
  padding-left: 2rem;
  border-left: 3px solid var(--primary);
}

.builder .builder__field-card-run + .builder__field-card-run {
  margin-top: 1.6rem;
}

.builder .builder__field-card-child + .builder__field-card-child {
  margin-top: 1.2rem;
}

/* The condition is stated over the fields it governs, so it sits above the
   run rather than inside the first card of it. */
.builder .builder__field-card-run .builder__chips {
  margin-bottom: 0.8rem;
}

/* ------------------------------------------------------------ Drag & drop */

/*
 * Three states, all driven by SortableJS' class options (see
 * builder/sortable_controller.js):
 *
 *   --ghost    the placeholder left where the item will land
 *   --chosen   the item the pointer picked up
 *   --dragging the copy that follows the pointer (the `forceFallback` clone)
 *
 * The ghost is the insertion line: a gold rule along the top edge of the slot
 * the drop will take, with the item's own contents faded back so the line
 * reads as a position rather than as a field. A palette tile takes the tile
 * ghost while it is still in the palette and the card ghost once it is over
 * the canvas — Sortable hands the placeholder to whichever list it is in —
 * so both wear the same insertion line.
 */

.builder .builder__field-card--ghost > .builder__field-card-main,
.builder .builder__palette-tile--ghost {
  border-color: var(--primary);
  background: rgba(189, 154, 52, 0.06);
  box-shadow: inset 0 3px 0 var(--primary);
}

/* Everything the placeholder is standing in for fades — its own gold edge is
   drawn on `-main` above, so the fade has to start inside it. */
.builder .builder__field-card--ghost .builder__field-card-main > *,
.builder .builder__field-card--ghost > .builder__field-card-children,
.builder .builder__palette-tile--ghost > * {
  opacity: 0.35;
}

.builder .builder__field-card--dragging,
.builder .builder__palette-tile--dragging {
  opacity: 0.95;
}

.builder .builder__field-card--dragging > .builder__field-card-main,
.builder .builder__palette-tile--dragging {
  border-color: var(--primary);
  box-shadow: 0 0.8rem 2.4rem rgba(0, 0, 0, 0.18);
}

.builder .builder__field-card--chosen .builder__grip,
.builder .builder__field-card--dragging .builder__grip,
.builder .builder__palette-tile--chosen,
.builder .builder__palette-tile--dragging {
  cursor: grabbing;
}

.builder .builder__field-card--chosen .builder__grip {
  color: var(--primary);
}

/*
 * The same three states for a child reordering inside its run, or a member
 * inside its group. The child card is its own box (a parent's is `-main` under
 * the card), so the insertion line is drawn on the card itself and the fade
 * starts one level in.
 *
 * The second selector of each pair is a member dragged OUT onto the canvas:
 * Sortable hands the placeholder whichever ghost class the list it is
 * currently over uses, so out there a child card wears the canvas's — and the
 * rules above reach only as far as a top-level card's `-main` box.
 */
.builder .builder__field-card-child--ghost,
.builder .builder__field-card-child.builder__field-card--ghost {
  border-color: var(--primary);
  background: rgba(189, 154, 52, 0.06);
  box-shadow: inset 0 3px 0 var(--primary);
}

.builder .builder__field-card-child--ghost > *,
.builder .builder__field-card-child.builder__field-card--ghost > * {
  opacity: 0.35;
}

.builder .builder__field-card-child--dragging {
  opacity: 0.95;
  border-color: var(--primary);
  box-shadow: 0 0.8rem 2.4rem rgba(0, 0, 0, 0.18);
}

.builder .builder__field-card-child--chosen .builder__child-grip,
.builder .builder__field-card-child--dragging .builder__child-grip {
  cursor: grabbing;
}

.builder .builder__field-card-child--chosen .builder__child-grip {
  color: var(--primary);
}

/* ------------------------------------------------------------------ Rail */

.builder .builder__rail-tabs {
  display: flex;
  border-bottom: 1px solid var(--light-border-color);
}

/* Half the rail each, so the strip reads as one control split in two rather
   than as a pair of links that happen to sit next to each other. The active
   half's gold rule is then as wide as its share. */
.builder .builder__rail-tab {
  flex: 1;
  padding: 1.5rem 0;
  font-size: 1.4rem;
  font-weight: 600;
  text-align: center;
  color: #888;
  text-decoration: none;
}

.builder a.builder__rail-tab:hover {
  color: #000;
}

.builder .builder__rail-tab--active {
  color: #000;
  box-shadow: inset 0 -2px 0 var(--primary);
}

.builder .builder__rail-section {
  padding: 2rem;
  border-bottom: 1px solid var(--light-border-color);
}

.builder .builder__rail-heading {
  margin: 0 0 1rem;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #888;
}

.builder .builder__rail-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.builder .builder__rail-value {
  font-size: 1.4rem;
  color: #242424;
}

.builder p.builder__rail-value {
  margin: 0;
}

.builder .builder__rail-note {
  margin: 0.5rem 0 0;
  font-size: 1.2rem;
  color: #888;
}

/* A fact and its qualifier on one line: unlike --rail-row these belong
   together, so they sit side by side rather than at opposite ends. */
.builder .builder__rail-line {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin-top: 0.4rem;
}

.builder .builder__rail-annotation {
  font-size: 1.2rem;
  color: #888;
}

/* What the Publish button would do, in the admin's own words. Set as prose
   rather than as a note: it is two sentences, and it is the only thing on the
   rail that has to be read rather than scanned. */
.builder .builder__rail-explainer {
  margin: 1rem 0 0;
  font-size: 1.2rem;
  line-height: 1.5;
  color: #666;
}

/* Under the version's own facts rather than in a footer row, so it takes its
   air from them. */
.builder .builder__version-action {
  margin-top: 1.5rem;
}

.builder .builder__pill {
  padding: 0.2rem 1rem;
  border-radius: 999px;
  font-size: 1.2rem;
  white-space: nowrap;
}

/* Live, being worked on, not there yet. Read on the rail's white and on the
   top bar's black, so each carries its own foreground. */
.builder .builder__pill--published {
  color: #fff;
  background: var(--success);
}

.builder .builder__pill--draft {
  color: var(--primary);
  border: 1px solid var(--primary);
}

.builder .builder__pill--none {
  color: #888;
  border: 1px solid #555;
}

.builder .builder__meter {
  height: 0.5rem;
  margin-top: 1rem;
  background: var(--light-border-color);
  border-radius: 999px;
  overflow: hidden;
}

.builder .builder__meter-fill {
  height: 100%;
  background: var(--primary);
}

/*
 * Field tab footer. Duplicate does something and Delete warns about something,
 * so the prompt is a stack rather than a row of two matching buttons: the
 * button, then the red link, then the line that says what the link would cost.
 */
.builder .builder__rail-prompt {
  padding: 2rem;
}

.builder .builder__rail-prompt .builder__link--delete {
  display: inline-block;
  margin-top: 1.5rem;
}

.builder .builder__rail-prompt .builder__rail-note {
  margin-top: 0.5rem;
}

/*
 * Each button is its own button_to <form>, so the flex row sizes the forms and
 * the buttons fill them.
 */
.builder .builder__rail-actions {
  display: flex;
  gap: 1rem;
  padding: 2rem;
}

/* Inside the prompt the padding belongs to the stack, not to the row. */
.builder .builder__rail-prompt .builder__rail-actions {
  padding: 0;
}

.builder .builder__rail-actions form {
  flex: 1;
}

.builder .builder__rail-action {
  width: 100%;
  padding: 1.1rem 0;
  font-family: inherit;
  font-size: 1.3rem;
  font-weight: 600;
  color: #242424;
  background: #fff;
  border: 1px solid var(--light-border-color);
  border-radius: 3px;
  cursor: pointer;
}

.builder .builder__rail-action:hover {
  border-color: #242424;
}

.builder .builder__rail-action--delete {
  color: var(--error);
}

.builder .builder__rail-action--delete:hover {
  color: #fff;
  background: var(--error);
  border-color: var(--error);
}

/* The way in to the modal: outlined rather than filled, because it opens
   something rather than saving anything. */
.builder .builder__rail-action--manage {
  margin-top: 1.5rem;
  color: var(--primary);
  border-color: var(--primary);
}

.builder .builder__rail-action--manage:hover {
  color: #fff;
  background: var(--primary);
  border-color: var(--primary);
}

/*
 * Delete's double opt-in: the first button reveals a panel that names what the
 * delete takes, and the panel holds the button that actually deletes.
 *
 * Both halves are hidden with the `hidden` attribute, so this rule has to beat
 * the flex row's own display — hence the attribute selector.
 */
.builder .builder__rail-prompt[hidden],
.builder .builder__rail-confirm[hidden] {
  display: none;
}

/* The reveal and Cancel buttons are bare buttons rather than button_to forms,
   so they take their share of the row themselves. */
.builder .builder__rail-actions > .builder__rail-action {
  flex: 1;
}

/* Tinted from --error (#b61d1d) at low emphasis: distinct from the rest of the
   rail without shouting over the button that does the deleting. */
.builder .builder__rail-confirm {
  background: rgba(182, 29, 29, 0.04);
  border-top: 1px solid rgba(182, 29, 29, 0.25);
}

.builder .builder__rail-confirm-copy {
  margin: 0;
  padding: 2rem 2rem 0;
  font-size: 1.3rem;
  line-height: 1.5;
  color: #242424;
}

.builder .builder__rail-confirm .builder__rail-actions {
  padding-top: 1.5rem;
}

/*
 * Discard's own double opt-in, in the Version section rather than in a footer.
 * The section already carries the page's padding, so this panel is a boxed
 * card inside it instead of a band bled to the rail's edges.
 */
.builder .builder__discard {
  margin-top: 1.5rem;
}

.builder .builder__rail-confirm--inline {
  padding: 1.5rem;
  border: 1px solid rgba(182, 29, 29, 0.25);
  border-radius: 3px;
}

.builder .builder__rail-confirm--inline .builder__rail-confirm-copy,
.builder .builder__rail-confirm--inline .builder__rail-actions {
  padding: 0;
}

.builder .builder__rail-confirm--inline .builder__rail-actions {
  margin-top: 1.5rem;
}

/* ------------------------------------------------- Availability modal */

/*
 * Fixed to the viewport rather than to the rail it is rendered inside: the
 * modal is over the whole builder, and nothing between here and the body sets
 * a transform, so `fixed` still means the window.
 *
 * Hidden with the `hidden` attribute — a save streams the block it lives in
 * back, and a freshly rendered modal is a closed one — so this rule has to
 * beat the flex display below it.
 */
.builder .builder__modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
}

.builder .builder__modal[hidden] {
  display: none;
}

.builder .builder__modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(43, 46, 56, 0.9);
}

/* Column so the header and footer stay put and only the airports scroll:
   Save has to be reachable from anywhere in an eighty-row list. */
.builder .builder__modal-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 64rem;
  max-width: calc(100vw - 4rem);
  max-height: calc(100vh - 8rem);
  background: #fff;
  border-radius: 5px;
}

.builder .builder__modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 2rem;
  padding: 2.4rem 2.4rem 2rem;
  border-bottom: 1px solid var(--light-border-color);
}

.builder .builder__modal-title {
  margin: 0;
  font-size: 1.8rem;
  font-weight: 700;
  color: #242424;
}

.builder .builder__modal-sub {
  margin: 0.4rem 0 0;
  font-size: 1.3rem;
  color: #888;
}

.builder .builder__modal-close {
  flex-shrink: 0;
  width: 3.2rem;
  height: 3.2rem;
  font-family: inherit;
  font-size: 2rem;
  line-height: 1;
  color: #888;
  background: none;
  border: 0;
  cursor: pointer;
}

.builder .builder__modal-close:hover {
  color: #242424;
}

.builder .builder__modal-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0 2.4rem 1.6rem;
}

/* Above the regions and stuck there: the one control that reaches every box
   has to stay reachable while the list under it scrolls. */
.builder .builder__modal-master {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  padding: 1.8rem 0;
  background: #fff;
  border-bottom: 1px solid var(--light-border-color);
}

.builder .builder__modal-row-label {
  font-size: 1.5rem;
  font-weight: 700;
  color: #242424;
}

.builder .builder__modal-hint {
  margin: 0.2rem 0 0;
  font-size: 1.3rem;
  color: #888;
}

.builder .builder__modal-group {
  padding-top: 1.8rem;
}

.builder .builder__modal-group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  margin-bottom: 1rem;
}

.builder .builder__modal-group-name {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0;
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #888;
}

.builder .builder__modal-group-count {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

/* Two columns: eighty airports one under the other is twice the scrolling for
   no more information. */
.builder .builder__modal-airports {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.8rem 2rem;
}

.builder .builder__modal-airport {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-width: 0;
}

.builder .builder__modal-airport .builder__toggle-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.builder .builder__modal-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  padding: 1.8rem 2.4rem;
  border-top: 1px solid var(--light-border-color);
}

/* What Save would change, filled in by the controller. Empty until something
   is ticked, so it takes no room in the row until it has something to say. */
.builder .builder__modal-pending {
  margin: 0;
  font-size: 1.3rem;
  color: #888;
}

.builder .builder__modal-actions {
  display: flex;
  gap: 1rem;
  margin-left: auto;
}

.builder .builder__modal-actions .builder__rail-action {
  width: auto;
  padding: 1.1rem 2rem;
}

.builder .builder__modal-save {
  padding: 1.1rem 2rem;
  font-family: inherit;
  font-size: 1.3rem;
  font-weight: 600;
  color: #fff;
  background: var(--primary);
  border: 1px solid var(--primary);
  border-radius: 3px;
  cursor: pointer;
}

.builder .builder__modal-save:hover {
  background: #d3ae3d;
  border-color: #d3ae3d;
}

/*
 * A checkbox wearing a switch, rather than a div pretending to be one: with
 * `appearance: none` the input keeps its own state, its own keyboard
 * behaviour and its own place in the form, and the track and thumb are drawn
 * on it. Without JavaScript the airport boxes below it still submit.
 */
.builder .builder__switch {
  position: relative;
  flex-shrink: 0;
  appearance: none;
  width: 4rem;
  height: 2.2rem;
  margin: 0;
  background: #d9d9d9;
  border-radius: 999px;
  cursor: pointer;
}

.builder .builder__switch::after {
  content: "";
  position: absolute;
  top: 0.2rem;
  left: 0.2rem;
  width: 1.8rem;
  height: 1.8rem;
  background: #fff;
  border-radius: 50%;
  transition: left 0.15s ease;
}

.builder .builder__switch:checked {
  background: var(--primary);
}

.builder .builder__switch:checked::after {
  left: 2rem;
}

.builder .builder__switch:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* ------------------------------------------------------------- Save state */

.builder .builder__save-state {
  font-size: 1.3rem;
  color: #bbb;
}

.builder .builder__save-state--error {
  color: #b61d1d;
}

/* The tick is the whole message at a glance — the words are the caption. */
.builder .builder__save-state-tick {
  margin-right: 0.5rem;
}

/* ------------------------------------------------------- Field tab inputs */

.builder .builder__input {
  display: block;
  width: 100%;
  height: 4.3rem;
  padding: 0 1rem;
  font-family: inherit;
  font-size: 1.4rem;
  color: #242424;
  background: #fff;
  border: 1px solid var(--light-border-color);
  border-radius: 3px;
}

.builder .builder__input--textarea {
  height: auto;
  padding: 1rem;
  resize: vertical;
}

.builder .builder__input:focus {
  outline: none;
  border-color: var(--primary);
}

/*
 * A section that opens: the heading doubles as the control, with the state it
 * is in read off the caret. A <button> can only hold phrasing content, so the
 * heading inside it is a span and loses the block heading's own spacing.
 */
.builder .builder__disclosure {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
}

.builder .builder__disclosure .builder__rail-heading {
  margin: 0;
}

.builder .builder__disclosure-caret {
  font-size: 1.1rem;
  color: #888;
}

/* The closed state says what it holds; the boxes behind it still submit, which
   is what keeps a cleared rule clearing. */
.builder .builder__disclosure + .builder__rail-note {
  margin-top: 1rem;
}

.builder .builder__rail-rules[hidden] {
  display: none;
}

.builder .builder__rail-rules {
  margin-top: 1rem;
}

/*
 * Segmented control: the radios themselves are hidden and their labels do the
 * work, so the pair still behaves like a normal radio group for keyboards and
 * for FormData.
 */
.builder .builder__segmented {
  display: flex;
  border: 1px solid var(--light-border-color);
  border-radius: 3px;
  overflow: hidden;
}

.builder .builder__segmented-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.builder .builder__segmented-label {
  flex: 1;
  padding: 1.1rem 0;
  font-size: 1.3rem;
  text-align: center;
  cursor: pointer;
}

.builder .builder__segmented-input:checked + .builder__segmented-label {
  color: #fff;
  background: var(--primary);
}

.builder .builder__segmented-input:focus-visible + .builder__segmented-label {
  box-shadow: inset 0 0 0 2px var(--primary);
}

.builder .builder__toggle {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.5rem 0;
}

/* The switch sits at the end of its row rather than beside its label: it is
   the row's control, and the caption under the label would otherwise push it
   out of line. */
.builder .builder__toggle--switch {
  align-items: flex-start;
  justify-content: space-between;
  padding: 0.8rem 0;
}

.builder .builder__toggle--switch .builder__toggle-label {
  display: block;
}

/* A label with no caption under it has nothing to align to the top of, so it
   sits level with the switch it names. */
.builder .builder__toggle--switch > label.builder__toggle-label {
  align-self: center;
}

.builder .builder__toggle-label {
  font-size: 1.4rem;
  color: #242424;
  cursor: pointer;
}

.builder .builder__checkbox {
  width: 1.8rem;
  height: 1.8rem;
  accent-color: var(--primary);
  cursor: pointer;
}

/* ------------------------------------------------------------ Form details */

/*
 * A row of the Details section: a label on the left, what it says on the
 * right. Read state and edit state are both rendered and the `hidden`
 * attribute picks one, so this rule has to beat their own display.
 */
.builder .builder__detail-read[hidden],
.builder .builder__detail-edit[hidden] {
  display: none;
}

.builder .builder__detail-read,
.builder .builder__detail-row {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 0.8rem 0;
}

.builder .builder__detail-label {
  flex-shrink: 0;
  font-size: 1.4rem;
  color: #242424;
}

/* The value takes the rest of the row and gives way to the Edit link, which
   is what the row is for. */
.builder .builder__detail-value {
  flex: 1;
  min-width: 0;
  font-size: 1.4rem;
  font-weight: 600;
  color: #242424;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.builder .builder__detail-fact {
  margin-left: auto;
  font-size: 1.4rem;
  color: #888;
}

.builder .builder__detail-row .builder__link {
  margin-left: auto;
}

.builder .builder__detail-edit {
  padding: 0.8rem 0;
}

.builder .builder__detail-actions {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-top: 0.8rem;
}

.builder .builder__detail-sep {
  font-size: 1.3rem;
  color: #bbb;
}

/* Gold text, no box: these are the quiet actions of the rail — open an editor,
   commit it, abandon it, go and read the responses. */
.builder .builder__link,
.builder a.builder__link {
  padding: 0;
  font-family: inherit;
  font-size: 1.3rem;
  color: var(--primary);
  background: none;
  border: 0;
  text-decoration: none;
  cursor: pointer;
}

.builder .builder__link:hover,
.builder a.builder__link:hover {
  text-decoration: underline;
}

/* The one link that isn't gold: red is the whole warning, and the line under
   it is the detail. */
.builder .builder__link--delete {
  color: var(--error);
  font-weight: 600;
}

/* The editor's box is the one open input in the Details section, so it wears
   the gold edge that says which one it is. */
.builder .builder__detail-edit .builder__input {
  border-color: var(--primary);
}

/* --------------------------------------------------- Choices & validation */

.builder .builder__choices {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
}

/* Label box first, then the button that drops the row: the hidden input that
   carries the stored value takes no space between them. */
.builder .builder__choice {
  display: flex;
  align-items: center;
  gap: 0.8rem;
}

.builder .builder__choice .builder__input {
  flex: 1;
}

.builder .builder__choice-remove {
  flex-shrink: 0;
  width: 3.2rem;
  height: 3.2rem;
  font-family: inherit;
  font-size: 1.8rem;
  line-height: 1;
  color: #888;
  background: none;
  border: 1px solid transparent;
  border-radius: 3px;
  cursor: pointer;
}

.builder .builder__choice-remove:hover {
  color: var(--error);
  border-color: var(--light-border-color);
}

/* The add button borrows the rail action's look, so the two read as the same
   kind of control — it only needs holding off the last row. */
.builder .builder__list-add {
  margin-top: 1rem;
}

/* Min and max are one rule read together, so they sit on one line. */
.builder .builder__rail-pair {
  display: flex;
  gap: 1rem;
}

.builder .builder__rail-pair .builder__rail-subfield {
  flex: 1;
}

.builder .builder__rail-subfield + .builder__rail-subfield {
  margin-top: 1.5rem;
}

.builder .builder__rail-pair .builder__rail-subfield + .builder__rail-subfield {
  margin-top: 0;
}

.builder .builder__rail-section .builder__rail-pair + .builder__rail-subfield {
  margin-top: 1.5rem;
}

/* Quieter than the section's own heading — it names one box, not the group —
   but still read rather than skimmed, so darker than a note. */
.builder label.builder__rail-sublabel {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 1.2rem;
  color: #555;
}

/* --------------------------------------------------- Data source & logic */

/* The toggle sits between two boxes rather than in a group of its own, so it
   takes the same air as the box above it. */
.builder .builder__rail-section .builder__rail-subfield + .builder__toggle {
  margin-top: 1.5rem;
}

.builder .builder__rail-section .builder__toggle + .builder__rail-subfield {
  margin-top: 1rem;
}

.builder .builder__conditions {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/*
 * One condition reads as a small card of its own: three pickers side by side
 * in a 300px rail would each be too narrow to read, so the trigger and the
 * test take a line each and the value shares the last one with the button
 * that drops the row.
 */
.builder .builder__condition {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.8rem;
  padding: 1rem;
  background: #fafafa;
  border: 1px solid var(--light-border-color);
  border-radius: 3px;
}

.builder .builder__condition > .builder__input {
  flex: 1 1 100%;
}

/* The value shares its line with the button that drops the row, whether it is
   typed into or picked from. */
.builder .builder__condition > .builder__condition-value {
  flex: 1 1 60%;
}

/* Several values are picked from a list that has to show more than one of
   them, so that one takes a line of its own. */
.builder .builder__condition > select.builder__condition-value[multiple] {
  flex: 1 1 100%;
  min-height: 7rem;
  padding: 0.4rem;
}

/* Right-aligned whether or not the value box is on its line: present and
   empty ask about the answer itself and hide it. */
.builder .builder__condition > .builder__choice-remove {
  margin-left: auto;
}

/* The row controller hides the value box by attribute, which has to beat the
   flex rule above it. */
.builder .builder__condition > [hidden] {
  display: none;
}

/* The sentence the rows below it finish, which is the only thing that says a
   field with no conditions is simply always shown. */
.builder .builder__logic-intro {
  margin: 0 0 1.5rem;
}

/* And/or means nothing until there is a second condition to combine, so the
   picker shows itself when one appears. It is rendered — and submitted —
   either way: logic on its own is what clears the column. */
.builder .builder__logic-combine {
  display: none;
  margin-bottom: 1.5rem;
}

.builder .builder__logic:has(.builder__condition ~ .builder__condition) .builder__logic-combine {
  display: block;
}

/* ------------------------------------------------------------- BA preview */

/*
 * The preview is the builder's black bar over the BA's own form. It reuses
 * the bar's styles wholesale and adds only what the builder has no equivalent
 * of: the way back as words, the note, and the card the form sits on.
 *
 * Everything under the bar lives in ONE element: body.builder is a two-row
 * grid, so a banner as a row of its own would have been stretched to fill it.
 */
.builder .builder__preview {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;
  background: #f5f5f5;
}

/* Words rather than the builder's bare arrow: this screen is somewhere an
   admin arrives at deliberately and has to be able to leave. */
.builder a.builder__preview-back {
  flex-shrink: 0;
  margin-left: -0.4rem;
  font-size: 1.3rem;
  color: #bbb;
  text-decoration: none;
}

.builder a.builder__preview-back:hover {
  color: #fff;
}

/* Who this is being seen as. Muted: it is a caption on the screen, not an
   action on it — the airport beside it is the only part that can be changed. */
.builder .builder__preview-role {
  font-size: 1.3rem;
  color: #999;
}

/* Caption and control read as one sentence, so they sit on one baseline with
   a single word's gap between them. */
.builder .builder__preview-airport {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin: 0;
}

/*
 * The airport being previewed. Quiet enough to belong in the bar's right
 * cluster beside its caption, but unmistakably a control: it keeps a border,
 * a chevron and a pointer, because an admin who does not notice this is a
 * select will read every scoped field as if it were the only airport.
 *
 * The whole appearance is reset — a native dark-on-light select in a black bar
 * is a white slab, and no OS renders it the same way.
 */
.builder .builder__preview-airport-select {
  appearance: none;
  padding: 0.4rem 2.4rem 0.4rem 0.9rem;
  max-width: 22rem;
  font-family: inherit;
  font-size: 1.3rem;
  color: #fff;
  background-color: #2a2a2a;
  /* Chevron as a data URI: the bar has no icon font of its own, and this one
     has to tint with the text rather than sit on top of it. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath fill='%23999' d='M0 0h10L5 6z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.9rem center;
  background-size: 0.9rem;
  border: 1px solid #3f3f3f;
  border-radius: 3px;
  cursor: pointer;
  text-overflow: ellipsis;
}

.builder .builder__preview-airport-select:hover {
  border-color: #5a5a5a;
}

.builder .builder__preview-airport-select:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

/* The dropdown itself is drawn by the OS, which does not inherit the bar's
   colours — name them so the open list is not white text on white. */
.builder .builder__preview-airport-select option {
  color: #000;
  background: #fff;
}

/*
 * The one thing on the page that isn't the BA's. Full width and directly
 * under the bar so it is read before anything is typed, and gold rather than
 * red because nothing here can go wrong — it just doesn't count.
 */
.builder .builder__preview-note {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  flex-shrink: 0;
  padding: 1.4rem 2rem;
  background: #fcf8ed;
  border-bottom: 1px solid var(--primary);
  font-size: 1.4rem;
  color: #7a6a1f;
}

.builder .builder__preview-page {
  flex: 1;
  padding: 4rem 2rem 8rem;
}

.builder .builder__preview-card {
  max-width: 68rem;
  margin: 0 auto;
  padding: 3rem 4rem 4rem;
  background: #fff;
  border-radius: 3px;
}

.builder .builder__preview-title {
  margin: 0;
  font-size: 2.4rem;
  font-weight: 400;
  line-height: 1.3;
  color: #242424;
}

.builder .builder__preview-description {
  margin: 1.2rem 0 0;
  font-size: 1.4rem;
  line-height: 1.5;
  color: #888;
}

.builder .builder__preview-title + .dynamic-form,
.builder .builder__preview-description + .dynamic-form {
  margin-top: 3rem;
}

/*
 * Same fix as the canvas needed, for the same reason: the BA page's form
 * styles are scoped to its own layout, so a control on body.builder falls
 * back to the UA default. The BA form class above restores the widths;
 * box-sizing is what stops the padded ones overflowing their card.
 * Checkboxes and radios keep their size.
 */
.builder .builder__preview-card input.form-control,
.builder .builder__preview-card select,
.builder .builder__preview-card textarea {
  width: 100%;
  box-sizing: border-box;
}

/*
 * NOTE the absence of a `.hidden` override here. The canvas force-reveals
 * conditional fields (`.builder .builder__canvas div.hidden`) because a
 * builder has to show every field; the preview must not, because hide and
 * reveal is the behaviour being previewed. That rule is scoped to
 * `.builder__canvas`, which is why this page must never use that class.
 */

.builder .builder__preview-empty {
  margin: 3rem 0 0;
  font-size: 1.5rem;
  color: #888;
}

.builder .builder__preview-actions {
  display: flex;
  align-items: center;
  gap: 1.6rem;
  margin-top: 3rem;
}

/* Gold with WHITE text — the convention across the redesign. */
.builder .builder__preview-submit,
.builder a.builder__preview-submit {
  display: inline-block;
  padding: 1.1rem 2.4rem;
  font-family: inherit;
  font-size: 1.4rem;
  font-weight: 600;
  color: #fff;
  text-decoration: none;
  background: var(--primary);
  border: 1px solid var(--primary);
  border-radius: 3px;
  cursor: pointer;
}

.builder .builder__preview-submit:hover,
.builder a.builder__preview-submit:hover {
  background: #d3ae3d;
  border-color: #d3ae3d;
  color: #fff;
}

.builder a.builder__preview-outline {
  display: inline-block;
  padding: 1.1rem 2.4rem;
  font-size: 1.4rem;
  font-weight: 600;
  color: var(--primary);
  text-decoration: none;
  background: #fff;
  border: 1px solid var(--primary);
  border-radius: 3px;
}

.builder a.builder__preview-outline:hover {
  background: #fcf8ed;
  color: var(--primary);
}

/* The banner's promise, said again where it is about to be tested. */
.builder .builder__preview-reminder {
  font-size: 1.3rem;
  color: #888;
}

/* The way in, from the builder's own bar. Outlined rather than filled: gold
   filled is Publish, and these two must not read as the same weight. */
.builder a.builder__preview-link {
  padding: 0.9rem 1.6rem;
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--primary);
  text-decoration: none;
  background: transparent;
  border: 1px solid var(--primary);
  border-radius: 3px;
}

.builder a.builder__preview-link:hover {
  background: rgba(189, 154, 52, 0.15);
  color: var(--primary);
}

/* ---------------------------------------------------- Preview: submitted */

.builder .builder__preview-card--success {
  max-width: 50rem;
  padding: 4rem 4rem 4.5rem;
  text-align: center;
}

.builder .builder__preview-tick {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 6.4rem;
  height: 6.4rem;
  margin: 0 auto 2.4rem;
  font-size: 2.8rem;
  color: #fff;
  background: var(--success);
  border-radius: 50%;
}

.builder .builder__preview-success-heading {
  margin: 0;
  font-size: 2.2rem;
  font-weight: 400;
  color: #242424;
}

.builder .builder__preview-success-body {
  margin: 1.6rem 0 0;
  font-size: 1.4rem;
  line-height: 1.6;
  color: #888;
}

.builder .builder__preview-success-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.2rem;
  margin-top: 2.8rem;
}

/* ===========================================================================
 * The forms index — /admin/builder/forms
 *
 * The doorway into the builder, and the one builder screen that renders inside
 * the application layout: sidebar, white page, no immersive chrome. It
 * therefore does NOT carry the `.builder` body class, so every rule below is
 * scoped under `.builder-index` instead. Same reason as the note at the top of
 * this file: Propshaft links every stylesheet on every page.
 *
 * The chips here are a palette of this screen's own, deliberately not the
 * builder bar's pills — a list where most rows are published has no use for a
 * green alarm on each of them.
 * ======================================================================== */

.builder-index {
  max-width: 100rem;
  padding-bottom: 6rem;
}

.builder-index__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 2rem;
  margin: 3rem 0 3.2rem;
}

/* Title and hint are one lockup: the hint is about the list, and a gap wide
   enough to separate them would hand it to the first row instead. */
.builder-index__lockup {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

/* No gold underline, deliberately — the app's page-header signature separated
   the title from the hint that belongs to it. Gold lives in the button and the
   chips on this screen. */
.builder-index__title {
  margin: 0;
  font-size: 2.8rem;
  font-weight: 500;
  line-height: 1.2;
  color: #242424;
}

.builder-index__hint {
  margin: 0;
  font-size: 1.4rem;
  color: #888;
}

.builder-index__new {
  flex-shrink: 0;
  padding: 1.2rem 2rem;
  font-family: inherit;
  font-size: 1.5rem;
  font-weight: 600;
  color: #fff;
  background: var(--primary);
  border: 1px solid var(--primary);
  border-radius: 0.8rem;
  cursor: pointer;
}

.builder-index__new:hover {
  background: #d3ae3d;
  border-color: #d3ae3d;
}

/* --- tabs ----------------------------------------------------------------
 *
 * Two menus, never shown together: the reports brand ambassadors see, and the
 * admin-only ones. The gold underline on the active half is the rail's tab
 * treatment, sized for a page rather than a 30rem column.
 */
.builder-index__tabs {
  display: flex;
  gap: 2.4rem;
  margin-bottom: 2.4rem;
  border-bottom: 1px solid #ececec;
}

.builder-index__tab {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0 0 1.2rem;
  font-family: inherit;
  font-size: 1.5rem;
  font-weight: 600;
  color: #999;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  cursor: pointer;
  transition: color 120ms ease;
}

.builder-index__tab:hover {
  color: #555;
}

.builder-index__tab--active {
  color: #242424;
  border-bottom-color: var(--primary);
}

/* The size of the menu, said quietly: it qualifies the tab rather than
   competing with it. */
.builder-index__tab-count {
  padding: 0.1rem 0.7rem;
  font-size: 1.2rem;
  font-weight: 600;
  color: #8c8c8c;
  background: #f2f2f2;
  border-radius: 999px;
}

.builder-index__panel[hidden] {
  display: none;
}

.builder-index__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Archived reports are still here to be read, reopened or republished, but
   they are in neither menu — so they sit under their own heading, below the
   order they are not part of. */
.builder-index__archived-heading {
  margin: 3.2rem 0 0;
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #b0b0b0;
}

/* Faded until read: the state has to be unmissable at a glance and the row
   still has to be legible when it is the one being looked for. */
.builder-index__row--archived {
  opacity: 0.5;
  transition: background-color 120ms ease, opacity 120ms ease;
}

.builder-index__row--archived:hover {
  opacity: 1;
}

/*
 * A divider list rather than cards: on white, card shadows go muddy, so the
 * rules carry the separation and the chips carry the colour.
 *
 * The pill inset is permanent and invisible: 1.6rem of side padding cancelled
 * by matching negative margins, so the text sits exactly where it would with no
 * padding at all, and the background — when it appears — has room to bleed
 * past it. Nothing about the geometry changes on hover. In a list whose whole
 * job is order, a row that shifts sideways when the pointer crosses it reads as
 * movement in the list itself.
 *
 * The negative margins bleed into the container's own padding (5rem on desktop,
 * 2rem below it), so they cost the page no horizontal scroll.
 */
.builder-index__row {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 1.6rem;
  margin: 0 -1.6rem;
  padding: 2rem 1.6rem;
  border-radius: 0.8rem;
  transition: background-color 120ms ease;
}

.builder-index__row + .builder-index__row {
  border-top: 1px solid #f0f0f0;
}

/* A wash, not a box: a border or a shadow here would re-box the rows the
   divider list just un-boxed. Colour only — see the geometry note above. */
.builder-index__row:hover {
  background-color: rgba(189, 154, 52, 0.06);
}

.builder-index__link {
  flex: 1;
  min-width: 0;
  text-decoration: none;
  color: inherit;
}

.builder-index__heading {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.8rem;
}

.builder-index__name {
  font-size: 1.7rem;
  font-weight: 700;
  color: #242424;
  transition: color 120ms ease;
}

/* The app's own link hover, so the row reads as the link it is. */
.builder-index__row:hover .builder-index__name {
  color: #8b7a26;
}

.builder-index__description {
  margin: 0.6rem 0 0;
  font-size: 1.4rem;
  color: #555;
}

.builder-index__facts {
  margin: 0.6rem 0 0;
  font-size: 1.3rem;
  color: #999;
}

/*
 * Visible at rest rather than revealed on hover: a drag handle nobody can see
 * is a feature nobody finds. Sized like the canvas grip, and wrapping the icon
 * in an element of its own — Font Awesome rewrites every <i> into an <svg>
 * after paint, and the handle has to be a stable box from the first frame.
 */
.builder-index__grip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.8rem;
  height: 2.4rem;
  font-size: 1.4rem;
  color: #ccc;
  cursor: grab;
  transition: color 120ms ease;
}

.builder-index__row:hover .builder-index__grip {
  color: #8c8c8c;
}

.builder-index__row--ghost {
  opacity: 0.4;
}

.builder-index__row--chosen,
.builder-index__row--dragging {
  background-color: rgba(189, 154, 52, 0.06);
}

.builder-index__empty {
  padding: 4rem 0;
  font-size: 1.5rem;
  color: #888;
}

/* --- chips ---------------------------------------------------------------
 *
 * Fully rounded and tinted. Published is barely there on purpose: it is the
 * state most rows are in, so it is the one that should cost the least
 * attention. Draft is amber because an open draft is unfinished business, and
 * Inactive is filled because a retired report is not a shade of the others.
 */
.builder-index__chip {
  padding: 0.3rem 1rem;
  font-size: 1.2rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  border: 1px solid transparent;
  border-radius: 999px;
}

.builder-index__chip--published {
  color: #6b6b6b;
  background: #f2f2f2;
}

.builder-index__chip--draft {
  color: #8a6d1f;
  background: #faf1d8;
}

.builder-index__chip--admin {
  color: #4f4f4f;
  background: #e8e8e8;
}

.builder-index__chip--inactive {
  color: #fff;
  background: #3d3d3d;
}

.builder-index__chip--none {
  color: #8c8c8c;
  background: transparent;
  border-color: #dcdcdc;
}

/* --- new report modal ----------------------------------------------------
 *
 * The rail's availability modal in miniature: hidden with the `hidden`
 * attribute so the server can render it open — which is exactly what a refused
 * create does, with the name still in the box.
 */
.builder-index__modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
}

.builder-index__modal[hidden] {
  display: none;
}

.builder-index__modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(43, 46, 56, 0.9);
}

.builder-index__modal-panel {
  position: relative;
  width: 44rem;
  max-width: calc(100vw - 4rem);
  padding: 2.4rem;
  background: #fff;
  border-radius: 5px;
}

.builder-index__modal-title {
  margin: 0 0 1.6rem;
  font-size: 2rem;
  font-weight: 600;
  color: #242424;
}

.builder-index__modal-label {
  display: block;
  margin-bottom: 0.6rem;
  font-size: 1.3rem;
  font-weight: 600;
  color: #444;
}

.builder-index__modal-input {
  width: 100%;
  padding: 1rem 1.2rem;
  font-family: inherit;
  font-size: 1.5rem;
  color: #242424;
  border: 1px solid #ddd;
  border-radius: 3px;
}

.builder-index__modal-input:focus {
  border-color: var(--primary);
  outline: none;
}

.builder-index__modal-hint {
  margin: 0.8rem 0 0;
  font-size: 1.2rem;
  line-height: 1.5;
  color: #888;
}

.builder-index__modal-error {
  margin: 0.8rem 0 0;
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--error);
}

.builder-index__modal-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1.2rem;
  margin-top: 2.4rem;
}

.builder-index__modal-cancel {
  padding: 1.1rem 2rem;
  font-family: inherit;
  font-size: 1.3rem;
  font-weight: 600;
  color: #444;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 3px;
  cursor: pointer;
}

.builder-index__modal-create {
  padding: 1.1rem 2rem;
  font-family: inherit;
  font-size: 1.3rem;
  font-weight: 600;
  color: #fff;
  background: var(--primary);
  border: 1px solid var(--primary);
  border-radius: 3px;
  cursor: pointer;
}

.builder-index__modal-create:hover {
  background: #d3ae3d;
  border-color: #d3ae3d;
}
