/* RightWrite web app, "Warm Paper".
 *
 * Every color, radius, shadow and family here comes from /tokens.css, which is
 * generated from src/shared/tokens.ts at build time. Do not hard-code a hex:
 * the extension reads the same tokens, and a value typed in twice is a value
 * that will be right in one place and stale in the other.
 *
 * This is the PRODUCT system, not the brand one. Modernist; flat, square, 2px
 * rules on #f5f5f1; is the marketing side now, and the only thing the two
 * share is the wordmark in the app bar, which stays Archivo. Concretely, and
 * contrary to what this stylesheet said a day ago: soft shadows instead of
 * rules, generous radii instead of squares, and no 2px dividers anywhere.
 *
 * Type is split. Figtree sets the interface; Newsreader sets anything the USER
 * wrote. No user-authored text appears on these screens yet, which is why
 * Newsreader is declared in fonts.css but never preloaded; see index.html.
 *
 * Light only, deliberately: the design system is a light-ground system and
 * every mockup is built on it. Bolting on a dark theme would mean inventing a
 * half of the system that does not exist.
 */

:root { color-scheme: light; }

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  font-family: var(--rw-font-ui);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.6;
  color: var(--rw-text);
  background: var(--rw-ground);
  -webkit-font-smoothing: antialiased;
}

.page {
  width: 100%;
  max-width: 620px;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* --- app bar ------------------------------------------------------------- */

/* Not a bar. It was a translucent band running the full width of the shell,
   with a hard bottom edge and its own white, sitting above a card that starts
   24px in, so it read as chrome bolted on top of the page rather than the top
   of the page.
   Now it is transparent, and its padding lines the wordmark up with the card's
   TEXT rather than the card's edge: the mark and the heading beneath it share
   a left edge, which is what makes the two feel like one column. */
.head {
  display: flex;
  align-items: center;
  padding: 26px 56px 0;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}

.mark {
  display: block;
  flex: 0 0 auto;
  border-radius: var(--rw-radius-tile);
  box-shadow: var(--rw-shadow-sm);
}

/* Archivo, and only here. The rest of the interface is Figtree. */
.wordmark {
  font-family: var(--rw-font-brand);
  font-weight: 800;
  font-size: 15px;
  letter-spacing: -0.035em;
  line-height: 1;
  color: var(--rw-brand-ink);
}
.wordmark span { color: var(--rw-brand-accent); }

#app { flex: 1; display: flex; flex-direction: column; }

/* The content card. Warm Paper raises content onto a white surface rather than
   ruling it off from the ground. */
main {
  margin: 22px 24px 30px;
  padding: 30px 32px;
  background: var(--rw-surface);
  border-radius: var(--rw-radius-card);
  box-shadow: var(--rw-shadow-card);
}

.foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  /* One item now that the on-device line is gone. flex-end keeps the links
     where they were rather than letting space-between slide them to the left. */
  justify-content: flex-end;
  gap: 8px 20px;
  /* Same 56px inset as the header, so the page has one column and not three. */
  padding: 8px 56px 26px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--rw-text-soft);
}

.foot-links { display: flex; gap: 16px; }
.foot-links a {
  color: var(--rw-text-soft);
  text-decoration: none;
  border-bottom: 1px solid var(--rw-field-border);
}
.foot-links a:hover { color: var(--rw-text-muted); border-bottom-color: var(--rw-text-faint); }

/* --- type ---------------------------------------------------------------- */

h1 {
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 6px;
}

h2 {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--rw-text-faint);
  margin: 0 0 10px;
}

p { margin: 0; }
.sub { color: var(--rw-text-muted); font-size: 14px; }
.note { font-size: 12px; color: var(--rw-text-soft); }

.kicker {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--rw-text-faint);
}

.stack { display: flex; flex-direction: column; }
.gap-sm { gap: 8px; }
.gap-md { gap: 14px; }
.gap-lg { gap: 22px; }

/* A tinted card, not a rule with a colored edge; nothing on this surface
   uses a hard border. */
.error,
.alert {
  background: var(--rw-spelling-tint);
  color: var(--rw-spelling-text);
  border-radius: var(--rw-radius-small);
  padding: 12px 14px;
  font-size: 13.5px;
}

/* --- form ---------------------------------------------------------------- *
 * The Modernist pattern butted the input against its button with no gap and no
 * radius. Warm Paper separates them: a rounded field, then a pill.            */

.field { display: flex; align-items: stretch; gap: 10px; }

input[type="email"],
.text-input,
.select {
  flex: 1;
  min-width: 0;
  font-family: var(--rw-font-ui);
  font-size: 14px;
  color: var(--rw-text);
  background: var(--rw-ground);
  border: 1px solid var(--rw-field-border);
  border-radius: var(--rw-radius-small);
  padding: 11px 14px;
}
input[type="email"]::placeholder,
.text-input::placeholder { color: var(--rw-placeholder); }
input[type="email"]:disabled,
.text-input:disabled,
.select:disabled { opacity: 0.55; }

.btn {
  font-family: var(--rw-font-ui);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--rw-radius-pill);
  padding: 12px 18px;
  cursor: pointer;
  display: block;
  transition: background-color 120ms ease-out, border-color 120ms ease-out;
}

.btn-primary {
  background: var(--rw-brand-accent);
  color: #fff;
  border-color: var(--rw-brand-accent);
}
.btn-primary:hover {
  background: var(--rw-brand-accent-hover);
  border-color: var(--rw-brand-accent-hover);
}
.btn-primary:active {
  background: var(--rw-brand-accent-pressed);
  border-color: var(--rw-brand-accent-pressed);
}
.btn-primary:disabled { opacity: 0.5; cursor: default; }

.btn-secondary {
  background: var(--rw-chip-warm);
  color: var(--rw-text-muted);
  border-color: transparent;
}
.btn-secondary:hover { background: var(--rw-chip); }

/* Sign out, and only sign out. Red because the account screen is otherwise a
   page of gray rows and wanted one piece of color, not because leaving is
   dangerous. The destructive controls elsewhere are deliberately quieter than
   this: they warm to red on hover instead of wearing it. */
.btn-danger {
  background: var(--rw-brand-accent);
  color: #fff;
  border-color: var(--rw-brand-accent);
}
.btn-danger:hover {
  background: var(--rw-brand-accent-hover);
  border-color: var(--rw-brand-accent-hover);
}
.btn-danger:active {
  background: var(--rw-brand-accent-pressed);
  border-color: var(--rw-brand-accent-pressed);
}

.btn-block { width: 100%; }
.btn-attached { flex: 0 0 auto; }

:focus-visible {
  outline: 2px solid var(--rw-brand-accent);
  outline-offset: 2px;
  border-radius: 4px;
}
::selection { background: var(--rw-spelling-tint); }

/* --- rows and stats ------------------------------------------------------ */

.rows { display: flex; flex-direction: column; }
.hair { height: 1px; background: var(--rw-hairline); }

.row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--rw-hairline);
  font-size: 14px;
}
.row:last-child { border-bottom: 0; }
.row-label { color: var(--rw-text-muted); }
.row-value { font-variant-numeric: tabular-nums; text-align: right; }

/* Identifiers; token ids, hosts, timestamps. Tabular figures rather than a
   monospace family, which Warm Paper does not have: JetBrains Mono was part of
   the Modernist set and is gone. */
.row-value.numeric,
.row-value.mono {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  font-size: 13px;
  color: var(--rw-text-muted);
}

.stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  background: var(--rw-surface-warm);
  border-radius: var(--rw-radius-small);
  overflow: hidden;
}
/* One tile, on a plan that has no seats to report. */
.stats-one { grid-template-columns: 1fr; }
.stat { padding: 18px 20px; }
.stat + .stat { box-shadow: inset 1px 0 0 var(--rw-hairline); }
.stat-value {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 6px 0 2px;
}
.stat-value .rest { color: var(--rw-text-faint); }

/* --- the plans ------------------------------------------------------------ *
 * Three side by side on a wide screen, stacked below the same breakpoint the
 * stats use, so the two grids on this page never disagree about when a row
 * becomes a column.
 */
.plans {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.plan {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Onboarding makes each card a <button>, which centers its content and
   * inherits neither the page font nor its color. */
  text-align: left;
  font: inherit;
  color: inherit;
  border: 0;
  cursor: pointer;
  padding: 18px 20px;
  background: var(--rw-surface-warm);
  border-radius: var(--rw-radius-small);
  /* Inset rather than a border, so the card the reader is already on can gain
   * a heavier one without every card shifting by a pixel. */
  box-shadow: inset 0 0 0 1px var(--rw-hairline);
}
.plan-on { box-shadow: inset 0 0 0 2px var(--rw-text-faint); }
.plan-name {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.plan-price {
  font-size: 13px;
  color: var(--rw-text-muted);
}
.plan-includes {
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
  font-size: 13px;
  line-height: 1.5;
  color: var(--rw-text-muted);
  /* Pushes the button to the bottom of every card regardless of how many
   * lines each plan includes, so the three buttons line up. */
  flex: 1;
}

/* Markers drawn rather than inherited from list-style, for two reasons: a
 * default disc is too heavy beside 13px text, and a wrapped line has to hang
 * under the text rather than under the dot. Without them the three lines read
 * as one run-on sentence. */
.plan-includes li {
  position: relative;
  padding-left: 15px;
}
.plan-includes li + li { margin-top: 5px; }
.plan-includes li::before {
  content: "";
  position: absolute;
  left: 3px;
  /* Centered on the first line's cap height, so the dot stays put when the
   * text wraps to two lines. */
  top: 0.55em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--rw-text-faint);
}
.plan .btn { margin-top: 4px; }
.plan .state { align-self: flex-start; }

.state {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: var(--rw-radius-pill);
  background: var(--rw-chip);
  color: var(--rw-text-muted);
}
.state-on {
  background: var(--rw-spelling-tint);
  color: var(--rw-spelling-text);
}

@media (max-width: 520px) {
  /* 12px card margin + 20px card padding = the 32px the text sits at. */
  .head { padding: 18px 32px 0; }
  main { margin: 16px 12px 22px; padding: 22px 20px; }
  .foot { padding: 6px 32px 22px; }
  .stats { grid-template-columns: 1fr; }
  .stat + .stat { box-shadow: inset 0 1px 0 var(--rw-hairline); }
  .plans { grid-template-columns: 1fr; }
  .field { flex-direction: column; }
}

/* --- asking something ------------------------------------------------------ *
 * Replaces confirm() and prompt(), which drew Chrome's own dialog: system
 * chrome, system buttons, and "rightwrite.app says" quoting the site back at
 * the reader as though the page were a stranger.
 *
 * <dialog> keeps the top layer, the focus trap and Escape; everything visible
 * is ours. The element itself is stripped bare so that a click landing on it
 * is unambiguously a click on the backdrop rather than on the panel.
 */
.modal {
  border: 0;
  padding: 0;
  background: none;
  color: inherit;
  max-width: 100%;
  max-height: 100%;
}
.modal::backdrop {
  /* Warmed rather than neutral black, so the scrim belongs to the same paper
   * as the page behind it. */
  background: rgb(38 30 26 / 42%);
}

.modal-card {
  width: min(420px, calc(100vw - 32px));
  padding: 24px;
  background: var(--rw-surface);
  border-radius: var(--rw-radius-card);
  box-shadow: var(--rw-shadow-card);
}

/* An h2 in this stylesheet is a SECTION KICKER: 11px, uppercase, faint. That
 * is right for "SUBSCRIPTION" above a row of buttons and wrong for the one
 * sentence a dialog exists to ask, so all four of those are set back here.
 * The element stays an h2 because the dialog needs a real heading. */
.modal-title {
  margin: 0;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.3;
  text-transform: none;
  color: var(--rw-text);
}

.modal-body {
  margin: 10px 0 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--rw-text-muted);
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
}
/* The onboarding rule pins buttons left; inside a dialog they belong right. */
.modal-actions .btn { align-self: auto; }

@media (max-width: 420px) {
  /* Full width and stacked, with the action on top where a thumb reaches. */
  .modal-actions { flex-direction: column-reverse; }
  .modal-actions .btn { width: 100%; }
}

/* --- legal documents ----------------------------------------------------- *
 * Long-form prose, so the measure is narrowed and the leading opened up. The
 * body is Figtree rather than Newsreader on purpose: Newsreader is reserved
 * for the user's OWN words, and a privacy notice is ours.                    */

.legal { max-width: 62ch; }
.legal h1 { margin-bottom: 2px; }

.legal-heading {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: var(--rw-text);
  margin: 22px 0 2px;
}

.legal-body {
  font-size: 14px;
  line-height: 1.7;
  color: var(--rw-text-muted);
}

.legal-list {
  margin: 2px 0 2px;
  padding-left: 18px;
  font-size: 14px;
  line-height: 1.7;
  color: var(--rw-text-muted);
}
.legal-list li { margin: 3px 0; }
.legal-list li::marker { color: var(--rw-text-faint); }

/* --- the account area ---------------------------------------------------- *
 * A team list and a seat table need more room than a sign-in form, so the
 * shell widens for these screens only. The class goes on <body> rather than on
 * <main> because the app bar and the footer have to widen with it or the page
 * looks hinged down one side.                                                */

body.wide .page { max-width: 880px; }

/* --- tabs ---------------------------------------------------------------- */

.tabs {
  position: relative;
  display: flex;
  gap: 4px;
  padding: 4px;
  background: var(--rw-surface-warm);
  border-radius: var(--rw-radius-pill);
}

/* The white pill, which is ONE element that moves rather than a background
   that switches tabs. Its left and width are written by settleTabs() from the
   active tab's measured geometry, and the slide is a Web Animation between the
   old geometry and the new; CSS alone cannot transition between two different
   elements, and the whole screen is rebuilt on a tab change. */
.tab-bubble {
  position: absolute;
  top: 4px;
  left: 0;
  bottom: 4px;
  width: 0;
  border-radius: var(--rw-radius-pill);
  background: var(--rw-surface);
  box-shadow: var(--rw-shadow-sm);
  pointer-events: none;
}

.tab {
  position: relative;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  color: var(--rw-text-muted);
  padding: 9px 14px;
  border-radius: var(--rw-radius-pill);
  transition: color 160ms ease-out;
}
.tab:hover { color: var(--rw-text); }
/* No background of its own; the bubble is behind it. Giving the active tab a
   fill too would leave a second white pill sitting at the destination while
   the first one was still travelling. */
.tab-on,
.tab-on:hover { color: var(--rw-text); }

/* --- controls ------------------------------------------------------------ */

.select {
  flex: 0 0 auto;
  appearance: none;
  padding-right: 34px;
  cursor: pointer;
  /* The chevron is drawn rather than fetched: an <img> here would be the only
     asset request on the page and would flash on first paint. */
  background-image: linear-gradient(45deg, transparent 50%, var(--rw-text-faint) 50%),
                    linear-gradient(135deg, var(--rw-text-faint) 50%, transparent 50%);
  background-position: right 16px center, right 11px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.select-sm { font-size: 13px; padding: 7px 30px 7px 10px; background-position: right 12px center, right 7px center; }

input[type="number"].text-input { width: 100px; flex: 0 0 auto; }

.check {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13.5px;
  color: var(--rw-text-muted);
  cursor: pointer;
}
.check-sm { font-size: 12.5px; }
.check input { accent-color: var(--rw-brand-accent); width: 15px; height: 15px; cursor: pointer; }
.check input:disabled { cursor: default; }
.check input:disabled + span { color: var(--rw-text-faint); }

/* A control that is only an action, no fill, no border, so it recedes until
   it is wanted. Destructive ones warm on hover rather than shouting in red. */
.btn-ghost {
  font-family: var(--rw-font-ui);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1;
  color: var(--rw-text-faint);
  background: transparent;
  border: 0;
  border-radius: var(--rw-radius-pill);
  padding: 7px 10px;
  cursor: pointer;
  transition: background-color 120ms ease-out, color 120ms ease-out;
}
.btn-ghost:hover { background: var(--rw-spelling-tint); color: var(--rw-spelling-text); }
.btn-ghost:disabled { opacity: 0.5; cursor: default; background: transparent; }

.empty {
  padding: 22px;
  text-align: center;
  background: var(--rw-surface-warm);
  border-radius: var(--rw-radius-small);
  font-size: 13.5px;
}

.error[hidden] { display: none; }

/* --- dictionaries -------------------------------------------------------- *
 * A wrapping list of words rather than rows: a dictionary is dozens of short
 * strings, and one per line would be a very long page saying very little.    */

.words {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  list-style: none;
  margin: 2px 0 0;
  padding: 0;
}

.word {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 5px 5px 5px 12px;
  background: var(--rw-surface-warm);
  border-radius: var(--rw-radius-pill);
}
/* The user's own words, set in the family reserved for them. */
.word-term {
  font-family: var(--rw-font-document);
  font-size: 14px;
  color: var(--rw-text);
}
.word .btn-ghost { font-size: 15px; padding: 2px 8px; line-height: 1; }

/* Read-only lists have no remove button, so the padding evens up. */
.word:not(:has(.btn-ghost)) { padding: 5px 12px; }

/* --- the team list ------------------------------------------------------- */

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

.member {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 16px;
  padding: 13px 0;
  border-bottom: 1px solid var(--rw-hairline);
}
.member:last-child { border-bottom: 0; }

.member-main { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1 1 240px; }
.member-who { display: flex; flex-direction: column; min-width: 0; }
.member-name {
  font-size: 14px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.member-email {
  font-size: 12.5px;
  color: var(--rw-text-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.member-marks { display: flex; gap: 6px; flex: 0 0 auto; }
.member-controls { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; }

/* Invited-but-never-arrived. Warm rather than alarming: it is a normal state
   that resolves itself the moment they click the link. */
.state-wait { background: var(--rw-grammar-tint); color: var(--rw-grammar-text); }

.invite { padding: 16px; background: var(--rw-surface-warm); border-radius: var(--rw-radius-small); }
.invite .btn { align-self: flex-start; }

@media (max-width: 620px) {
  .member { align-items: flex-start; }
  .member-controls { width: 100%; justify-content: space-between; }
  /* Scroll the tabs rather than wrap them. The bubble is positioned against
     the bar, so a second row would strand it on the first one. */
  .tabs {
    font-size: 12px;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tab { padding: 8px 11px; }
}

/* --- first run ----------------------------------------------------------- *
 * One question at a time, on the narrow shell. Deliberately unlike the account
 * screens: no tabs, no rows, nothing to explore. There are two things to
 * answer and a way past both.                                                */

.onboarding { max-width: 560px; }
/* The plan step is a comparison rather than a question, and three cards side
 * by side need the room the rest of the flow deliberately does not take. */
.onboarding-wide { max-width: 880px; }
.onboarding h1 { font-size: 26px; }
.onboarding .btn { align-self: flex-start; }

.progress { display: flex; flex-direction: column; gap: 8px; }

.progress-track {
  height: 3px;
  border-radius: var(--rw-radius-pill);
  background: var(--rw-chip-warm);
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  border-radius: var(--rw-radius-pill);
  background: var(--rw-brand-accent);
  transition: width 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* The width is an inline style now: the number of steps depends on the plan,
 * so 50% and 100% were only ever right for the two-step flow. */

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

.invited-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 11px 0;
  border-bottom: 1px solid var(--rw-hairline);
}
.invited-row:last-child { border-bottom: 0; }
.invited-email { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The way on, then the way back, in that order visually, because the primary
   action should not be the one you reach second. */
.actions { display: flex; align-items: center; gap: 12px; }
.actions .btn { align-self: auto; }

/* --- snippets -------------------------------------------------------------
 *
 * The list, and the editor that replaces it. Deliberately reuses the tokens
 * and the shapes the rest of the account screens use rather than introducing a
 * second visual language for one tab; the editor surface is styled to look
 * like .text-input grown tall, because that is what it is. */

.snip-head { display: flex; align-items: center; gap: 12px; }
.snip-buttons { display: flex; align-items: center; gap: 8px; }

.snip-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }

.snip-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--rw-hairline);
}
.snip-row:last-child { border-bottom: 0; }

/* min-width:0 is what lets the ellipsis below actually happen: a flex item
   defaults to min-width:auto and refuses to shrink below its content, so the
   preview would push the buttons off the row instead of truncating. */
.snip-main { min-width: 0; }
.snip-title { font-weight: 600; font-size: 14px; }
.snip-preview {
  color: var(--rw-text-soft);
  font-size: 13px;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.snip-actions { display: flex; gap: 8px; flex-shrink: 0; }

.snip-form { max-width: 640px; }

.snip-editor {
  border: 1px solid var(--rw-field-border);
  border-radius: 6px;
  background: var(--rw-surface);
  overflow: hidden;
}
.snip-loading { padding: 16px; color: var(--rw-text-soft); font-size: 13px; }

.snip-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 6px;
  border-bottom: 1px solid var(--rw-hairline);
  background: var(--rw-surface-warm);
}
.snip-tool {
  min-width: 30px;
  height: 28px;
  padding: 0 7px;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--rw-text-muted);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
}
.snip-tool:hover { background: var(--rw-chip); color: var(--rw-text); }
.snip-tool.on { background: var(--rw-chip); color: var(--rw-text); font-weight: 600; }

/* ProseMirror renders into this. The editor owns its own scrolling so a long
   snippet does not stretch the page out from under the Save button. */
.snip-surface .ProseMirror {
  min-height: 180px;
  max-height: 380px;
  overflow-y: auto;
  padding: 12px;
  outline: none;
  font-size: 14px;
  line-height: 22px;
  color: var(--rw-text);
}
.snip-surface .ProseMirror > :first-child { margin-top: 0; }
.snip-surface .ProseMirror > :last-child { margin-bottom: 0; }
.snip-surface .ProseMirror p { margin: 0 0 8px; }
.snip-surface .ProseMirror h1,
.snip-surface .ProseMirror h2,
.snip-surface .ProseMirror h3 { margin: 12px 0 6px; font-size: 16px; }
.snip-surface .ProseMirror ul,
.snip-surface .ProseMirror ol { margin: 0 0 8px; padding-left: 22px; }
.snip-surface .ProseMirror blockquote {
  margin: 0 0 8px;
  padding-left: 12px;
  border-left: 2px solid var(--rw-field-border);
  color: var(--rw-text-muted);
}
.snip-surface .ProseMirror pre {
  margin: 0 0 8px;
  padding: 8px 10px;
  border-radius: 4px;
  background: var(--rw-chip);
  font-size: 13px;
  overflow-x: auto;
}
.snip-surface .ProseMirror code { font-size: 13px; }
.snip-surface .ProseMirror a { color: var(--rw-replacement); }

/* --- the compliance list -------------------------------------------------- *
 * A policy is read far more often than it is edited, so this is built for
 * scanning rather than for editing: what the rule replaces, with what, and
 * why, in that order, with the controls quiet until they are wanted.          */

/* Chrome's own file control cannot be styled, so the input is taken out of the
   layout and a label is dressed as a drop zone in front of it. Not
   `display:none` and not `hidden`: either would take it out of the tab order
   and off the accessibility tree, and the label would then open a picker no
   keyboard could reach. Clipped to a pixel is the pattern that keeps both. */
.file {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin: 6px 0 8px;
  padding: 26px 20px;
  /* Dashed, which is the one shape everybody reads as "put something here".
     The only dashed border in the product, and it earns the exception by
     being the only control that accepts something from outside the page. */
  border: 1.5px dashed var(--rw-field-border);
  border-radius: var(--rw-radius-card);
  background: var(--rw-surface-warm);
  cursor: pointer;
  text-align: center;
  transition: border-color 120ms ease, background 120ms ease;
}
.file:hover { border-color: var(--rw-placeholder); background: var(--rw-surface-active); }

/* While a file is over it. Set from script, because :hover does not fire
   during a drag and there is no CSS state for "something is being dragged
   onto this". */
.file-over {
  border-color: var(--rw-brand-accent);
  border-style: solid;
  background: var(--rw-surface-active);
}

.file input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.file-lead { font-size: 14px; color: var(--rw-text); font-weight: 600; }
.file-lead em { font-style: normal; color: var(--rw-brand-accent); }
.file-hint { font-size: 12.5px; color: var(--rw-text-soft); }

/* The focus ring has to follow the input, which is the thing actually focused,
   onto the box standing in for it. */
.file:focus-within {
  outline: 2px solid var(--rw-brand-accent);
  outline-offset: 2px;
}

.file-name { color: var(--rw-text-soft); font-size: 13px; }

.rule-group {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 22px 0 0;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--rw-text-soft);
}
.rule-group:first-child { margin-top: 0; }
.rule-count { font-weight: 500; color: var(--rw-text-faint); letter-spacing: 0; }

.rules {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Warm Paper has no hard rules, so a rule is separated by its own ground and a
   gap rather than by a line. Every row, not alternate ones: zebra striping
   here read as though half the list were selected, which on a screen with a
   Remove button on each row is the wrong thing to suggest. */
.rule {
  padding: 11px 14px;
  border-radius: var(--rw-radius-small);
  background: var(--rw-surface-warm);
}
.rule:hover { background: var(--rw-surface-active); }

.rule-head { display: flex; align-items: baseline; gap: 8px; }

/* The term and its replacement in the family reserved for the customer's own
   words, the same one the dictionary uses. These are their words, not ours. */
.rule-term,
.rule-instead {
  font-family: var(--rw-font-document);
  font-size: 14.5px;
}
.rule-term { color: var(--rw-text); font-weight: 600; }
.rule-instead { color: var(--rw-replacement); }
.rule-arrow { color: var(--rw-text-faint); font-size: 13px; }
/* A rule with nothing to put in its place. The word is simply not to be used,
   and saying so is better than an empty column. */
.rule-none { color: var(--rw-text-faint); font-size: 13px; font-style: italic; }

.rule-flag {
  padding: 2px 8px;
  border-radius: var(--rw-radius-pill);
  background: var(--rw-chip);
  color: var(--rw-text-muted);
  font-size: 11px;
  font-weight: 600;
}

/* Pushed right, and quiet until the row is under the pointer. A policy screen
   with a column of Remove buttons down it reads as a list of things to delete
   rather than a list of rules. */
.rule-remove { margin-left: auto; opacity: 0; transition: opacity 90ms ease; }
.rule:hover .rule-remove,
.rule-remove:focus-visible { opacity: 1; }

/* Where there is no pointer there is no hover, and a control that only appears
   on a state the device cannot produce is a control that does not exist. */
@media (hover: none) {
  .rule-remove { opacity: 1; }
}

.rule-why {
  margin: 4px 0 0;
  color: var(--rw-text-muted);
  font-size: 13px;
  line-height: 1.5;
}

/* The forms the product worked out from the rule above. Quieter than the rule
   itself, because it is not a second policy: it is the same one, spelled out
   so somebody can audit what is actually being enforced. */
.rule-also {
  margin: 5px 0 0;
  font-size: 12px;
  color: var(--rw-text-soft);
}
.rule-also-label {
  margin-right: 6px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--rw-text-faint);
}
.rule-also-term { font-family: var(--rw-font-document); }

/* --- selecting rules ------------------------------------------------------ */

.rule-tools {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 32px;
  margin: 18px 0 0;
}

.rule-all {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--rw-text-muted);
  cursor: pointer;
  user-select: none;
}

.rule-check {
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: var(--rw-brand-accent);
  cursor: pointer;
  /* The row aligns on the baseline of its text, which puts a box drawn from
     its own top edge slightly high. */
  align-self: center;
}

/* Appears only once something is selected, so the resting state of the screen
   is a policy to read rather than a toolbar to operate. */
.rule-bar {
  display: flex;
  align-items: center;
  gap: 10px;
}
.rule-bar[hidden] { display: none; }
.rule-bar-count {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--rw-text);
  font-variant-numeric: tabular-nums;
}

/* --- a labeled field, and the help bubble on a heading ------------------- */

/*
 * Fields carry visible labels rather than placeholders.
 *
 * A placeholder is not a label: it disappears the moment somebody types, so
 * the one time you most need to know which box you are in is the one time it
 * is gone. The compliance form had five controls and no labels, and reading
 * "Only when written this way" told nobody what it did.
 */
.labeled { display: flex; flex-direction: column; gap: 5px; flex: 1; min-width: 0; }

.labeled > span {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--rw-text-muted);
}

/*
 * A question mark beside a heading, holding the part that cannot be shown.
 *
 * A button rather than a span with a title attribute: the native tooltip is
 * slow, unstyleable, and never appears for anybody navigating by keyboard.
 * This opens on hover AND on focus, which is the whole reason it is a button.
 */
.help-wrap { position: relative; display: inline-flex; align-items: center; }

.help {
  width: 17px;
  height: 17px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--rw-surface-sunken, #eee7dd);
  color: var(--rw-text-muted);
  font-size: 11px;
  font-weight: 700;
  line-height: 17px;
  cursor: help;
}

.help:hover, .help:focus-visible { color: var(--rw-text); }

.help-bubble {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: 290px;
  padding: 9px 11px;
  border-radius: 9px;
  background: var(--rw-text);
  color: var(--rw-surface, #fff);
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: 0;
  text-align: left;
  /* Hidden from the pointer as well as the eye, so it cannot sit between the
     reader and whatever is underneath it. */
  opacity: 0;
  pointer-events: none;
  transition: opacity 90ms ease;
  z-index: 20;
}

.help-wrap:hover .help-bubble,
.help-wrap:focus-within .help-bubble { opacity: 1; }

/*
 * A heading with its help bubble beside it.
 *
 * The h2's own bottom margin moves here. align-items:center centers the BOX,
 * and an h2 carrying 10px underneath is a box whose text sits 5px above the
 * middle, so the question mark lined up with nothing.
 */
.section-head { display: flex; align-items: center; gap: 7px; margin-bottom: 10px; }
.section-head h2 { margin-bottom: 0; }

/*
 * A field that should be exactly as wide as what is in it.
 *
 * .labeled grows to fill the row, which is right for a text input and wrong
 * for a two-button choice: the pill stretched the whole width of the form with
 * Prefer marooned in the middle of it. flex-start stops the control itself
 * stretching too, which is the second half of the same bug.
 */
.labeled-auto { flex: 0 0 auto; align-items: flex-start; }

/*
 * A two-button choice, for a decision with exactly two answers.
 *
 * The level was a <select>, which hides one of two options behind a click and
 * gives a binary choice the same shape as a list of twenty. Both answers are
 * visible here, and which one is selected is readable without opening
 * anything, which matters because it is the decision this whole feature turns
 * on: a writer can wave away a preference and cannot wave away a must-not.
 */
.seg {
  display: inline-flex;
  border: 1px solid var(--rw-hairline);
  border-radius: 999px;
  overflow: hidden;
  background: var(--rw-input-bg);
}

.seg button {
  border: 0;
  background: none;
  font-size: 13.5px;
  font-weight: 500;
  font-family: inherit;
  color: var(--rw-text-muted);
  padding: 10px 16px;
  cursor: pointer;
  white-space: nowrap;
}

.seg button:hover { color: var(--rw-text); }

.seg button[aria-pressed='true'] {
  background: var(--rw-brand-accent);
  color: #fff;
}

.seg button[aria-pressed='true']:hover { color: #fff; }

/* Sits on the same line as the level and the button rather than owning one. */
.field .check { flex: 0 0 auto; align-self: center; }

/* "optional", beside a label. */
.opt { font-weight: 400; color: var(--rw-text-faint); }

/*
 * The pencil on a rule row.
 *
 * Sits at the end of the head line, quiet until the row is under the pointer.
 * Always present for a keyboard, which is why the visibility is opacity rather
 * than display: a control that does not exist until a mouse arrives is a
 * control some people never get.
 */
.rule-edit {
  margin-left: auto;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--rw-text-faint);
  cursor: pointer;
  opacity: 0;
  transition: opacity 90ms ease, color 90ms ease;
}

.rule:hover .rule-edit,
.rule-edit:focus-visible { opacity: 1; }

.rule-edit:hover { color: var(--rw-text); background: var(--rw-chip); }

/*
 * The hidden attribute, honored.
 *
 * Its default is display:none, and any rule that sets a display beats it,
 * because both are unlayered author styles and ours is more specific. Every
 * button in here sets one, so `button.hidden = true` did nothing at all and a
 * Cancel that should only appear mid-edit was on screen the whole time.
 */
[hidden] { display: none !important; }
