/* The shared rows (shared/rows/), one root: .row-. Site#show's Summary, Pages, Forms and
   Emails draw one row, urls/_source_row with a drawer of _drawer's three
   parts. The row itself is application.css's (.row and the compact row). What
   is below is what those tabs and onboarding's screens share: the drawer, its
   bar and settings, the greyed row, its lines, acts and tags, and a Form's
   picture beside its facts. What only onboarding does to a row stays in its
   own files.

   Folded in from prototype/site-tab-rows (variant E, 2026-10-15), its
   `pstr-` classes renamed `row-`.

   THIS FILENAME IS A CASCADE DECISION, as onboarding_email.css says of its
   own: Propshaft serves one <link> per stylesheet in alphabetical order and
   there is no @layer, so this sorts after application.css and both
   onboarding files. */

/* ---------- The drawer ----------

   Full width UNDER the row rather than a popover over it, so the controls and
   the check's own status stay readable at the same time and the rows below
   move down instead of being covered.

   IT IS PART OF THE ROW, NOT A BOX INSIDE IT: no radius at the top and no tint
   of its own. It used to be --color-bg, which is the same value as the row's
   hover, so a resting drawer read as a permanently-hovered something; and a
   tinted rounded panel inside an untinted row is the cards-inside-cards shape
   this list refuses everywhere else.

   THE SEAM IS ITS OWN. The row and its drawer are one tinted entity, and once
   open the pressable half and the panel would be one unbroken block of colour
   with nothing to say where the half that answers a click stops. The hairline
   is the weight, colour and width of the hairline BETWEEN rows, because it is
   the same statement -- this is where one thing ends. On the drawer, it is
   there exactly while the drawer is, and a row inside it draws none of its own.

   It stops at the row's edges, but the box reaches past them for the hover tint,
   so ::before draws it over the box's top border. The clip margin keeps the line
   out of the clip the drawer holds while it moves.

   ONE SET OF NUMBERS for a row's drawer and a check's (Chris, 2026-10-15:
   "the spacing seems all over the place"). The drawer's padding is the space
   under the seam whatever comes first.

   A PHONE'S DRAWER DOES NOT INDENT, at any level, and every row inside one is
   compact (application.css, under .row--compact). Each level of indent took a
   row's mark and gap, so three left a Summary row three deep a 102px column
   that its bar ran out of. A row sits flush with the one that opened it; the
   seam and the drawer's tint say it is inside. Folded in from the phone
   nested-rows UI prototype (2026-11-10, .claude/skills/prototype/UI.md),
   variant b as reworked in its third round, over a smaller step per level, a
   step halving each tier, a bar that stacks (which fixed the bar and left the
   words and fields as narrow) and a bottom sheet from two deep. The
   reasoning is in .scratch/row-bar-controls/issues/13. */
.row-drawer {
  margin-inline: calc(var(--card-padding) / -2);
  padding: calc(var(--card-padding) / 2);
  padding-left: calc(var(--card-padding) / 2 + var(--row-gutter));
  padding-right: calc(var(--card-padding) / 2 + var(--row-gutter) / 4);
  position: relative;
  border-top: 1px solid transparent;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  overflow-clip-margin: 1px;

  @media (max-width: 40rem) {
    padding-inline: calc(var(--card-padding) / 2);
  }

  &::before {
    content: "";
    position: absolute;
    top: -1px;
    inset-inline: calc(var(--card-padding) / 2);
    border-top: 1px solid var(--color-border);
  }

  /* A drawer nothing shuts, so it has no join with its row to mark. */
  &.borderless {
    border-top: 0;

    &::before {
      content: none;
    }

    /* The tint carries on into a drawer open under it (an undecided Form's). */
    &:has(+ .row-drawer:not([hidden])) {
      border-radius: 0;
    }
  }

  /* The contents fade rather than the drawer, or the seam would fade with them:
     it is there from the drawer's first frame. */
  > * {
    margin: 0;
    transition: opacity 0.2s ease;

    @starting-style {
      opacity: 0;
    }
  }

  /* OPENING AND SHUTTING. The drawer grows from nothing and shrinks back
     rather than snapping (prototype/site-micro-interactions). `hidden` stays
     the state (disclosure_controller.js); display transitions discretely so
     the shut drawer stays drawn until it has shrunk. Height reaches `auto`
     only through interpolate-size, which Safari lacks: there its contents
     fade and it snaps.

     The clip is on only while it moves, or it would cut off the Snooze menu
     that hangs out of the drawer's bar: an animation as long as the move
     holds it, one name each way, so each open and each shut starts its own.
     A drawer open as the page loads clips for a moment, with nothing yet
     hanging out of it to cut. */
  interpolate-size: allow-keywords;
  transition:
    height 0.28s var(--ease-out),
    padding-block 0.28s var(--ease-out),
    display 0.28s allow-discrete;
  animation: row-drawer-opening 0.28s;

  &[hidden] {
    height: 0;
    padding-block: 0;
    animation-name: row-drawer-shutting;

    > * {
      opacity: 0;
    }
  }

  @starting-style {
    &:not([hidden]) {
      height: 0;
      padding-block: 0;
    }
  }
}

@keyframes row-drawer-opening {
  from, to {
    overflow: clip;
  }
}

@keyframes row-drawer-shutting {
  from, to {
    overflow: clip;
  }
}

.row-drawer-head {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 700;
}

/* ---------- Rows nested under a row ----------

   What a row holds, listed beneath it with no drawer: the Console's Site row
   and its pages, addresses and Forms. Indented by the row's mark and gap, so
   each starts under the words of the row it belongs to, and set off from that
   row's own head by the hairline between rows. A phone's drawer does not do
   this, and deliberately (the drawer, above). */
.row-list--nested {
  margin-left: 2.5rem;
  border-top: 1px solid var(--color-border);
}

/* ---------- The bar ----------

   A bar with nothing under it draws no rule, so a check's drawer doesn't end in
   two lines.

   TWO GROUPS (consistency.md C10). Active and Snooze are standing choices a
   User sets and leaves, so they start the bar; how often, Run now and Stop
   monitoring act on the checking itself, so they end it. When the bar is too
   narrow for one line the end group drops below as one piece and stays at the
   end, rather than its controls scattering under the start group's.

   Stop monitoring is last and behind a hairline, the weight and colour of the
   seam between rows, because it takes the whole resource off the User's
   lists. The line is drawn only when something stands before it, so a bar of
   Stop monitoring alone doesn't start with a rule. A phone's drawer is too
   narrow to keep the end group on one line, so Stop monitoring wraps onto a
   line of its own, where a rule beside it would divide it from nothing; there
   it has no line, and being last and alone sets it apart instead.

   It is an icon, so its button is as wide as it is tall: the icon's box is
   the text's line, so the button is the height of its neighbours, and its
   sides take the block padding plus what that line adds over the icon, a
   rem wherever it is not already the phone's 44px square. */
.row-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.8rem;
  /* !important to beat application.css's :first-child reset. */
  margin-top: calc(var(--card-padding) / -2) !important;
  padding: calc(var(--card-padding) / 2) 0;
  border-bottom: 1px solid var(--color-border);

  &:last-child {
    border-bottom: 0;
  }

  > .row-bar-start,
  > .row-bar-end {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: inherit;
  }

  > .row-bar-end {
    justify-content: flex-end;
    margin-left: auto;

    > * + form:has(.row-stop) {
      padding-left: 0.8rem;
      border-left: 1px solid var(--color-border);
    }
  }

  /* A PHONE'S TAP TARGETS. The drawer is where a row's controls are, so it
     is where a phone keeps or breaks the promise: sized for a desktop drawer
     these are about 26px tall. 44px is what both platform guidelines ask
     for, in px since the root, and so a rem, is 16px from 641px up (the root
     steps in application.css); 52rem is the row's own phone breakpoint,
     which a media query reads at 16px. */
  @media (max-width: 52rem) {
    gap: 0.6rem 0.8rem;

    > .row-bar-end > * + form:has(.row-stop) {
      padding-left: 0;
      border-left: 0;
    }

    .button,
    .form-toggle label {
      display: inline-flex;
      align-items: center;
      min-height: 44px;
    }
  }
}

/* button_to wraps its button in a form, which flex would otherwise stretch. */
.row-bar form {
  display: inline-flex;
  margin: 0;
}

.row-stop {
  display: inline-flex;
  align-items: center;
  padding-inline: calc(0.5rem + (1lh - 1rem) / 2);

  > svg {
    height: 1lh;
  }

  /* Square at the phone's 44px too (the bar's PHONE'S TAP TARGETS). */
  @media (max-width: 52rem) {
    justify-content: center;
    min-width: 44px;
  }
}

/* ---------- The row's settings ---------- */
.row-settings {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  padding: var(--card-padding) 0;

  .row-fields {
    max-width: 36rem;
  }

  /* Paragraphs, not fields: an empty Product Service row's drawer
     (sites/show/_services) reads as prose, so its margins space it. */
  &.row-settings--prose {
    display: block;
  }
}

/* ---------- A Concern's problem in a service row's drawer ----------
   sites/show/_service_concern. Its meaning, evidence and steps are the
   Action Card's (action_card.css, "A problem's words"); this is only the
   heading and the line under it.

   Folded in from the Broken link monitoring row UI prototype (2026-11-08,
   .claude/skills/prototype/UI.md) -- variant d won out over a drawer of the
   links alone with a jump to the card (e), a compact row per broken link
   (f), d headed by the check's question (d2), and round 1's a, b and c; b
   never opened, and lost because the row would leave the Site page without
   Pause or Snooze. The prototype branch was deleted once d won; the
   reasoning is in .scratch/broken-link-service-row/issues/01. */
.row-issue {
  h3 {
    margin: 0;
    font-size: 1.1rem;
  }
}

.row-issue-looked {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem;
  margin: 0.2rem 0 0.8rem;

  small {
    color: var(--color-text-muted);
  }
}

/* ---------- How often (_cadence_menu) ---------- */
.row-cadence-caret {
  /* em, not a step: the caret is sized against the label it trails. */
  font-size: 0.75em;
  color: var(--color-text-muted);
}

.row-cadence-tick {
  margin-left: 0.5rem;
}

/* ---------- Shared with onboarding's screens ----------

   `:is()` takes its most specific argument, so on onboarding each selector
   weighs exactly what it did nested, and nothing it used to beat or lose to
   has moved. `.row-list` is every other list of rows, the Dashboard's
   included: a skipped or stopped row there is greyed as it is here. */
:is(.onboarding .card section, .row-stack, .row-list) .row {
  /* A row with nothing to do on it -- unsupported, dead, unticked, skipped.
     Greyed rather than removed: the heading above says why it is here and the
     address still has to be readable. Unticking is how a User declines an
     address on Select, so an unticked row takes the same class.

     DIMMED BY ITS PARTS, NEVER BY THE ROW, and the parts are listed rather
     than inherited. This was `opacity` on the section, which composites its
     whole subtree -- and a child cannot opt back out of that (`opacity: 1` on
     the control does nothing; the parent's value has already been applied to
     the rendered group), so the one exemption below would be impossible.

     THE ACTS ARE DIMMED TOO. A skipped row's Undo at full weight reads as
     this row asking for something, which is the opposite of what the class
     says -- reported live as skipped rows carrying the same weight as live
     ones. It stays pressable: opacity is weight, not a disabled attribute,
     and the act that undoes the state its row is greyed for has to remain
     reachable. The drawer's Details / Close goes with them, for the same
     reason.

     THE TICK IS THE EXEMPTION, and it is the only one. Its OFF state IS the
     message -- an unchecked switch is a grey track, and 55% of that is
     nothing at all -- so on Select, where unticking is how a User declines an
     address, dimming it made the way back out of the row the hardest thing on
     the row to see. Reported live, as a checkbox that looks disabled rather
     than unticked. */
  &.disabled {
    > .row-top > .status-badge-icon,
    > .row-top > .row-text,
    > .row-top > .row-right > .row-pill,
    > .row-top > .row-right > .row-acts > :not(.form-toggle),
    > .row-top > .row-right > .row-edit,
    > :not(.row-top),
    > .row-top::after {
      opacity: 0.55;
    }

    /* An act comes back to full weight under the pointer or the keyboard, so
       a greyed row's Restore reads as a button that works, not a disabled one,
       the moment a User reaches for it (consistency.md C17 — A row nothing
       watches is greyed, and its buttons answer the hand). The caret above
       is the row's own, and stays grey with it. */
    > .row-top > .row-right > .row-acts > :not(.form-toggle):is(:hover, :focus-within) {
      opacity: 1;
    }

    /* AND THE TONE GOES WITH IT. Dimming alone leaves a skipped address
       wearing whatever its state was -- a red ring at 55% still reads as
       red, and shouting about an address the User has finished with is the
       opposite of what this class is for. Grey means over, so a quiet row's
       mark is the grey one whatever the row is quiet FROM. */
    > .row-top > .status-badge-icon {
      --tone: var(--color-unknown);
    }
  }
}

/* ---------- A note ----------

   Muted helper text, one step smaller than a row's sentence (.row-what),
   under that sentence or anywhere else. Italic is what a snoozed line says that
   its size doesn't.

   In this file because it has to follow .row-drawer's reset of its children's
   margins, and above .email-cost and .form-confirm-reason, which sit on one and
   change it. */
.note {
  margin: 0.2rem 0 0;
  color: var(--color-text-muted);
  font-size: 0.8rem;
  line-height: 1.5;
}

.note--snoozed {
  font-style: italic;
}

/* Why a Form offers Look again, or that one is on its way, in place of
   Confirm (ADR 0101, shared/_form_confirm). Its own line in whichever action
   row it sits in, so the button stays beside Discard. */
.form-confirm-reason {
  flex-basis: 100%;
  margin: 0;
}

/* ---------- Results card lines ----------

   The disclosure sentence: what a check on this address costs other people,
   and it has to be read before a probe reaches any of them. WEIGHTED, NEVER
   ALARMING -- a group is a normal answer and this is not a warning. */
.email-cost {
  font-weight: 600;
  color: var(--color-warm-heading);
}

/* An address nothing has looked at yet.

   A TURNING RING AND NOT A GREYED ROW. Pending used to take .email-row--quiet
   -- the same class a skipped row and an unticked row take -- so the three
   states a User must tell apart were drawn identically: the one thing on this
   screen that is actively happening looked exactly like the two that are
   over. Reported from a live run, where every row was greyed the instant the
   popup closed and nothing said work was in flight.

   So grey keeps ONE meaning on this screen (nothing is happening here) and
   motion carries the other. The arc is icons.css's own waiting ring, the
   element itself (.status-badge-icon--loading, emails/_row), so its turning
   and its stillness under reduced motion are that file's alone. What this
   screen changes is its scale and its colour: text scale, off currentColor
   rather than a tone, because it sits beside a sentence rather than in a
   status disc.

   Italic stays: it is what this line looked like before, and it still reads
   as provisional next to the finished cards' lines. */
.email-waiting {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-style: italic;

  /* The font-size is the sentence's, so the em in the size is the
     sentence's too: the base's glyph-scale font-size would shrink it, and
     this ring carries no glyph. */
  .status-badge-icon {
    --tone: currentColor;
    --status-icon-size: 0.8em;
    font-size: inherit;
  }
}

.row-acts {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* ---------- A row's tags ---------- */
.row-tag {
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  background: var(--color-unknown-bg);
  color: var(--color-unknown);
  font-size: 0.7rem;
  font-weight: 700;
  white-space: nowrap;
}

.row-tag--off {
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.row-tag--provider {
  background: var(--color-warm-accent-bg);
  color: var(--color-warm-accent);
}

/* Tier (c). Not a warning: nil is the NORMAL state for a larger customer, whose
   mailboxes are perfectly connectable -- so it reads as the same quiet grey as
   "not yet", never as red. */
.row-tag--unknown,
.row-tag--soon {
  background: var(--color-bg);
  color: var(--color-warm-muted);
}

.row-tag--dead {
  background: var(--color-fail-bg);
  color: var(--color-fail);
}

/* ---------- A Form's picture beside its facts (shared/rows/_form_settings) ----------

   Folded in from the onboarding-form row prototype (variant F, "the expandable
   row"; .scratch/onboarding-form/prototype-form-row, 2026-09-29; its throwaway
   branch is deleted). */
/* The capture is 560px wide whatever the form's height, so width is the
   stable dimension and height is not: the fixtures measured 167px to 1189px.
   Scaled to the column, a tall form meets the cap and is anchored to the top,
   so the part that names a form -- its heading and first fields -- survives.
   width/height are the scanner's own measurement, so the box is reserved at
   the right shape before the bytes decode. */
.row-shot {
  display: block;
  width: 100%;
  height: auto;
  max-height: 28rem;
  object-fit: cover;
  object-position: top center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.row-shot-missing {
  display: grid;
  place-items: center;
  min-height: 6rem;
  padding: 1rem;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-warm-muted);
  font-size: 0.8rem;
  text-align: center;
}

.row-fact {
  margin: 0 0 1rem;
  font-size: 0.85rem;
  overflow-wrap: anywhere;
}

/* A SETTING'S SWITCH BESIDE ITS SENTENCE (Test submissions): the switch keeps
   its size and the sentence wraps in its own column, never under the switch.
   Folded in from the send-choice prototype's switch line. */
.row-switch {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  cursor: pointer;

  > .form-toggle {
    flex: none;
  }
}

/* THE PICTURE TAKES TWO THIRDS, the facts beside it the rest: the picture is
   what tells one form from another (prototype/site-tab-rows, D1). This row's own
   settings, since a row inside its drawer has settings of its own. */
.row.form > .row-drawer > .row-settings {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: 1.25rem 1.5rem;
  align-items: start;

  @media (max-width: 43rem) {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Beside the picture, What it's for is one more labelled fact in a narrow
     column, so its field fills it. */
  .row-fields {
    grid-template-columns: minmax(0, 1fr);
    margin-bottom: 0.9rem;
  }

  .row-select {
    max-width: 100%;
  }
}

/* ---------- The rest ---------- */

.row-zoom {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}

/* A house dialog that is only its picture, which is its one button: pressing
   it closes the dialog. A tall picture scrolls the dialog. */
.picture-zoom {
  --dialog-width: 48rem;
  cursor: zoom-out;

  &[open] {
    display: block;
    overflow-y: auto;
  }

  button {
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: inherit;
  }

  img {
    display: block;
    width: 100%;
    height: auto;
  }
}
