/* IIPP Builder — visual system.
 *
 * Bootstrap 5.3 stays. This themes it through Bootstrap's own CSS custom
 * properties rather than replacing it, which means every page changes at
 * once and no form control or table has to be rebuilt by hand. The ceiling
 * is slightly lower than hand-written CSS; the floor is very much higher,
 * and the floor is what matters across eighteen templates.
 *
 * Palette and type come from the design canvas: a warm off-white ground
 * rather than the blue-grey Bootstrap default, near-black ink instead of
 * pure black, terracotta for actions, sage for confirmation. Newsreader
 * carries the headings and IBM Plex Sans the interface.
 *
 * Why a serif for a compliance product: the thing being sold is a written
 * program that somebody has to read. A serif says document. It also
 * separates this from every other Bootstrap admin panel a safety director
 * has been shown, which is worth more than it sounds when the competing
 * product is a $99 Word file.
 */

:root {
  /* ---- Ground and ink */
  --ink:            #141413;
  --ink-soft:       #4a4945;
  --ink-faint:      #75736c;
  --page:           #faf9f5;
  --panel:          #ffffff;
  --panel-sunk:     #f0eee6;
  --rule:           #e3ddd1;
  --rule-strong:    #d3ccbc;

  /* ---- Action */
  --accent:         #d97757;
  --accent-dark:    #c6613f;
  --accent-tint:    #fbf1ec;

  /* ---- Status. Sage rather than Bootstrap green: this product says
   *      "recorded" far more often than it says "success", and the louder
   *      green reads as celebration where it should read as noted. */
  --ok:             #788c5d;
  --ok-tint:        #f1f4ec;
  --warn:           #a05c00;
  --warn-tint:      #fdf5e7;
  --danger:         #b42318;
  --danger-tint:    #fdf0ee;

  --radius:         10px;
  --radius-sm:      7px;
  --shadow:         0 1px 2px rgba(20, 20, 19, .04),
                    0 8px 24px -12px rgba(20, 20, 19, .10);

  --serif: 'Newsreader', Georgia, 'Times New Roman', serif;
  --sans:  'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Bootstrap's own variables. Setting these is what makes components we
   * never touch — alerts, badges, tables, pagination — inherit the theme. */
  --bs-body-bg: var(--page);
  --bs-body-color: var(--ink);
  --bs-body-font-family: var(--sans);
  --bs-body-font-size: 0.975rem;
  --bs-body-line-height: 1.6;
  --bs-border-color: var(--rule);
  --bs-border-radius: var(--radius);
  --bs-border-radius-sm: var(--radius-sm);
  /* Bootstrap 5.3 writes `a { color: rgba(var(--bs-link-color-rgb), …) }`,
   * so setting only --bs-link-color leaves every ordinary body link at
   * Bootstrap's default blue. It did: the contact page's "refund policy"
   * and "Cal/OSHA Consultation Services" both rendered #0d6efd against a
   * warm paper palette. The -rgb pair is the one that actually lands. */
  --bs-link-color: var(--accent-dark);
  --bs-link-color-rgb: 198, 97, 63;
  --bs-link-hover-color: var(--accent);
  --bs-link-hover-color-rgb: 217, 119, 87;
  --bs-emphasis-color: var(--ink);
  --bs-secondary-color: var(--ink-faint);
  --bs-primary-rgb: 217, 119, 87;
  --bs-heading-color: var(--ink);
}

body {
  background-color: var(--page);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------- type */

h1, h2, h3, h4, .h1, .h2, .h3, .h4, .display-6 {
  font-family: var(--serif);
  font-weight: 600;
  letter-spacing: -0.011em;
  color: var(--ink);
}
h1, .h1 { font-size: 2rem; line-height: 1.18; }
h2, .h2 { font-size: 1.45rem; line-height: 1.25; }
h3, .h3 { font-size: 1.2rem; }
h5, .h5, h6, .h6 { font-family: var(--sans); font-weight: 600; }

.lede {
  font-family: var(--serif);
  font-size: 1.075rem;
  line-height: 1.55;
  color: var(--ink-soft);
}
.text-muted { color: var(--ink-faint) !important; }
.form-text { color: var(--ink-faint); font-size: 0.845rem; line-height: 1.5; }

/* ---------------------------------------------------------------- shell */

.site-header {
  border-bottom: 1px solid var(--rule);
  background: linear-gradient(180deg, #fffefb 0%, var(--page) 100%);
}
.wordmark {
  font-family: var(--serif);
  font-size: 1.32rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
  text-decoration: none;
}
.wordmark:hover { color: var(--accent-dark); }
/* The mark is inline SVG rather than a lettered badge, so it takes a
 * size and an alignment and nothing else -- its colors come from the
 * palette tokens inside the SVG itself and cannot drift from the page. */
.wordmark .mark {
  width: 1.75rem; height: 1.75rem;
  margin-right: .5rem;
  vertical-align: -.36rem;
}
.site-tagline {
  font-size: .82rem;
  color: var(--ink-faint);
}

.site-nav a {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: .875rem;
  font-weight: 500;
  padding: .3rem 0;
  border-bottom: 2px solid transparent;
}
.site-nav a:hover { color: var(--ink); border-bottom-color: var(--rule-strong); }
.site-nav a.active { color: var(--ink); border-bottom-color: var(--accent); }

.site-footer {
  border-top: 1px solid var(--rule);
  font-size: .8rem;
  color: var(--ink-faint);
}
.site-footer a { color: var(--ink-faint); text-decoration: none; }
.site-footer a:hover { color: var(--accent-dark); text-decoration: underline; }

/* ---------------------------------------------------------------- panel */

.card {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--panel);
  box-shadow: var(--shadow);
}

/* ---------------------------------------------------------------- steps */

.step-label {
  font-family: var(--sans);
  font-size: .715rem;
  text-transform: uppercase;
  letter-spacing: .085em;
  color: var(--ink-faint);
  font-weight: 600;
  margin-bottom: .35rem;
}

/* A numbered rail rather than a bare bar. A bar says "you are 60% done";
 * this says which five things are being asked and which one is open, which
 * is what somebody halfway through a compliance form actually wants. */
.steps { display: flex; gap: .4rem; margin-bottom: 1.6rem; }
.steps li {
  flex: 1;
  list-style: none;
  font-size: .715rem;
  font-weight: 500;
  color: var(--ink-faint);
  padding-top: .45rem;
  border-top: 3px solid var(--rule);
  line-height: 1.3;
}
.steps li.done { color: var(--ink-soft); border-top-color: var(--ok); }
.steps li.now  { color: var(--ink); font-weight: 600; border-top-color: var(--accent); }

.progress { background-color: var(--panel-sunk); height: 4px; border-radius: 99px; }
.progress-bar { background-color: var(--accent); }

/* ---------------------------------------------------------------- forms */

.form-label {
  font-weight: 600;
  font-size: .875rem;
  color: var(--ink);
  margin-bottom: .3rem;
}
.form-control, .form-select {
  border-color: var(--rule-strong);
  border-radius: var(--radius-sm);
  padding: .5rem .7rem;
  background-color: var(--panel);
  color: var(--ink);
}
.form-control::placeholder { color: #a9a69c; }
.form-control:focus, .form-select:focus, .form-check-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(217, 119, 87, .16);
}
.form-check-input:checked {
  background-color: var(--accent);
  border-color: var(--accent);
}
.form-check-input { border-color: var(--rule-strong); }
.form-check-label { font-size: .925rem; }

/* ---------------------------------------------------------------- buttons */

.btn { font-weight: 500; border-radius: var(--radius-sm); padding: .48rem 1.05rem; }
.btn-primary {
  background-color: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.btn-primary:hover, .btn-primary:focus, .btn-primary:active {
  background-color: var(--accent-dark) !important;
  border-color: var(--accent-dark) !important;
  color: #fff;
}
.btn-outline-secondary {
  color: var(--ink-soft);
  border-color: var(--rule-strong);
  background: transparent;
}
.btn-outline-secondary:hover, .btn-outline-secondary:focus {
  background-color: var(--panel-sunk);
  color: var(--ink);
  border-color: var(--rule-strong);
}
.btn-outline-primary { color: var(--accent-dark); border-color: var(--accent); }
.btn-outline-primary:hover { background-color: var(--accent); border-color: var(--accent); }
.btn-outline-success { color: #5f7049; border-color: var(--ok); }
.btn-outline-success:hover { background-color: var(--ok); border-color: var(--ok); }
.btn-link { color: var(--accent-dark); }

/* ---------------------------------------------------------------- alerts */

.alert { border-radius: var(--radius); border-width: 1px; font-size: .925rem; }
.alert-info, .alert-primary {
  background-color: var(--accent-tint);
  border-color: #f0d8cd;
  color: #8a4526;
}
.alert-success {
  background-color: var(--ok-tint);
  border-color: #d5e0c6;
  color: #4a5a37;
}
.alert-warning {
  background-color: var(--warn-tint);
  border-color: #ecd9ae;
  color: var(--warn);
}
.alert-danger {
  background-color: var(--danger-tint);
  border-color: #f2cdc8;
  color: var(--danger);
}
.alert-light, .alert-secondary {
  background-color: var(--panel-sunk);
  border-color: var(--rule);
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------- misc */

.badge { font-weight: 500; letter-spacing: .01em; }
.list-group-item { background: transparent; border-color: var(--rule); }
.table { --bs-table-border-color: var(--rule); }
hr { border-color: var(--rule); opacity: 1; }

dl.review dt, ul.review-list .review-label {
  color: var(--ink-faint);
  font-weight: 600;
  font-size: .82rem;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.text-brand { color: var(--accent-dark) !important; }

details > summary { cursor: pointer; }

@media (max-width: 575.98px) {
  h1, .h1 { font-size: 1.6rem; }
  .steps li { font-size: 0; padding-top: .35rem; }
  .steps li.now { font-size: .715rem; }
}

/* ---------------------------------------------------------------- pricing */

.tier {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.35rem 1.4rem;
  margin-bottom: 1.1rem;
  background: var(--panel);
}
.tier-featured {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(217, 119, 87, .10);
}
/* A tier that cannot be sold is shown, not hidden. Its absence would raise
 * the question anyway, and the reason is a better sentence about a
 * compliance product than any feature bullet on the page. */
.tier-unavailable { background: var(--panel-sunk); }
.tier-unavailable .tier-price { color: var(--ink-faint); }

.tier-price {
  font-family: var(--serif);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.tier-badge {
  background: var(--accent-tint);
  color: var(--accent-dark);
  border: 1px solid #f0d8cd;
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: uppercase;
  vertical-align: .18rem;
}
.tier-list { list-style: none; padding-left: 0; margin-bottom: 1.1rem; }
.tier-list li {
  position: relative;
  padding-left: 1.5rem;
  margin-bottom: .38rem;
  font-size: .925rem;
  line-height: 1.5;
}
.tier-list li::before {
  position: absolute;
  left: 0;
  font-weight: 700;
}
/* Literal characters, not "\2713" / "\2013". A CSS hex escape is
 * terminated by a space or by six digits, and these were being read as
 * the escape plus a stray trailing digit -- the pricing page was
 * rendering its ticks as "¹3" and its dashes as "HOP3". Same class
 * of bug as the interpunct in .meta, found the same way: by looking at
 * the rendered page rather than at the stylesheet. */
.tier-list li.yes::before { content: "✓"; color: var(--ok); }
.tier-list li.no::before  { content: "–"; color: var(--ink-faint); }
.tier-list li.no { color: var(--ink-faint); }


/* ---------------------------------------------------------------- home (marketing) */
/* The public homepage at "/" -- everything else in this file themes the
 * logged-in app's narrow boxed-card layout, but a marketing page needs a
 * full-width hero, proof section, benefit grid and pricing teaser. Reuses
 * the same tokens and several existing classes (.wordmark, .site-header,
 * .site-nav, .card, .tier*) so the homepage reads as the same product,
 * just wider. */

.home-hero {
  display: flex;
  align-items: center;
  gap: 56px;
  flex-wrap: wrap;
  padding: 72px 0 88px;
}
.home-hero-copy { flex: 1 1 420px; min-width: 280px; }
.home-hero-kicker {
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--accent-dark);
}
.home-hero-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 2.75rem;
  line-height: 1.14;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin-top: .6rem;
}
.home-hero-sub {
  margin-top: 1rem;
  font-size: 1.1rem;
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 32rem;
}
.home-hero-actions {
  margin-top: 1.6rem;
  display: flex;
  align-items: center;
  gap: 1.2rem;
  flex-wrap: wrap;
}
.home-hero-note { font-size: .875rem; font-weight: 600; color: var(--ink-faint); }
.home-hero-visual { flex: 0 0 320px; display: flex; justify-content: center; }

/* A single, simplified status card rather than the three stacked/rotated
 * sheets in the original mockup -- same illustrative content, but one
 * element instead of three absolutely-positioned ones is what actually
 * survives being squeezed onto a phone screen. */
.home-mock-card {
  width: 100%;
  max-width: 300px;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 22px 24px;
}
.home-mock-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.home-mock-label {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.home-mock-badge {
  padding: 2px 9px;
  background: var(--accent-tint);
  color: var(--accent-dark);
  font-size: .65rem;
  font-weight: 700;
  border-radius: 99px;
  white-space: nowrap;
}
.home-mock-line { margin-top: 12px; height: 8px; border-radius: 99px; background: var(--panel-sunk); }
.home-mock-foot { margin-top: 14px; font-size: .68rem; font-weight: 600; color: var(--ink-faint); }

.home-section { padding: 80px 0; }
.home-section-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.9rem;
  color: var(--ink);
  text-align: center;
}

.home-proof { background: var(--panel-sunk); }
.home-proof-inner { display: flex; gap: 48px; flex-wrap: wrap; align-items: flex-start; }
.home-proof-copy { flex: 1 1 320px; }
.home-proof-quote {
  flex: 1 1 380px;
  background: var(--panel);
  border: 1px solid var(--rule-strong);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  padding: 28px 32px;
}
.home-proof-quote p {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.2rem;
  line-height: 1.55;
  color: var(--ink);
}
.home-proof-cite { margin-top: 14px; font-size: .8rem; font-weight: 600; color: var(--ink-faint); }

.home-benefit-card { height: 100%; padding: 1.75rem; }
.home-benefit-icon { color: var(--accent); }
.home-benefit-title { margin-top: .9rem; font-weight: 700; font-size: 1.05rem; color: var(--ink); }
.home-benefit-body { margin-top: .4rem; font-size: .925rem; line-height: 1.55; color: var(--ink-soft); }

.home-pricing-note { text-align: center; font-size: .85rem; color: var(--ink-faint); margin-top: 1.5rem; }

.home-final-cta {
  background: var(--ink);
  color: #f4f1ea;
  padding: 84px 0;
  text-align: center;
}
.home-final-cta h2 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 2rem;
  line-height: 1.25;
  max-width: 640px;
  margin: 0 auto;
  color: #f4f1ea;
}
.home-final-cta .btn-primary { margin-top: 1.8rem; }

/* A secondary button that survives the dark section.
 *
 * btn-outline-secondary is ink-coloured text on an ink-coloured border,
 * which on var(--ink) is invisible -- it shipped that way and read as a
 * missing button rather than a subtle one. Anything placed on this
 * section has to bring its own light palette. */
.btn-on-dark {
  margin-top: 1.8rem;
  color: #f4f1ea;
  border: 1px solid rgba(244, 241, 234, .45);
  background: transparent;
}
.btn-on-dark:hover,
.btn-on-dark:focus {
  color: var(--ink);
  background: #f4f1ea;
  border-color: #f4f1ea;
}
.btn-on-dark:focus-visible {
  outline: 2px solid #f4f1ea;
  outline-offset: 2px;
}

/* The teaser cards carry a price and a sentence and nothing else, so a
 * short one leaves a hole under it once h-100 levels the row. Three
 * lines of what you get fills it with the thing somebody is actually
 * comparing. */
.home-tier-points {
  list-style: none;
  padding: 0;
  margin: .85rem 0 0;
  font-size: .85rem;
  line-height: 1.5;
  color: var(--ink-soft);
}
.home-tier-points li { position: relative; padding-left: 1.1rem; margin-bottom: .3rem; }
.home-tier-points li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--ok);
  font-weight: 700;
}

@media (max-width: 767.98px) {
  .home-hero-title { font-size: 2rem; }
  .home-hero { padding: 48px 0 56px; }
}

/* ------------------------------------------------------- app interior */
/*
 * The public pages got a design pass and the interior ones did not, so a
 * customer crossed from a considered homepage into stock Bootstrap the
 * moment they signed in. The specific tell was status colour: records and
 * the calendar between them used bg-secondary, bg-warning, bg-info,
 * bg-success-subtle, bg-light and text-bg-danger -- six unrelated palettes
 * on one screen, none of them the warm one everything else is built from.
 *
 * .chip is the single replacement. Semantics pick the variant, the tokens
 * pick the colour, so status reads the same everywhere it appears and a
 * new status cannot introduce a seventh palette.
 */

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: 1.25rem;
}
.page-head h1, .page-head .h1 { margin: 0; }

.page-intro {
  font-size: .925rem;
  color: var(--ink-faint);
  line-height: 1.6;
  margin: -.5rem 0 1.5rem;
  max-width: 60ch;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-family: var(--sans);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .02em;
  line-height: 1;
  padding: .3rem .5rem;
  border-radius: 5px;
  border: 1px solid var(--rule-strong);
  background: var(--panel-sunk);
  color: var(--ink-soft);
  white-space: nowrap;
}
.chip-ok      { background: var(--ok-tint);     border-color: #cdd7bd; color: #4d5c39; }
.chip-warn    { background: var(--warn-tint);   border-color: #e6cf9f; color: var(--warn); }
.chip-danger  { background: var(--danger-tint); border-color: #edbdb7; color: var(--danger); }
.chip-accent  { background: var(--accent-tint); border-color: #eec5b4; color: var(--accent-dark); }
.chip-quiet   { background: transparent;        border-color: var(--rule); color: var(--ink-faint); font-weight: 500; }

/* Reads as data rather than as a label: the version of a thing, not a
 * status of it. Same size as a chip so a row of them still lines up. */
.chip-version {
  font-variant-numeric: tabular-nums;
  background: transparent;
  border-color: var(--rule-strong);
  color: var(--ink-faint);
}

.chip-row { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }

/* A list of records, obligations, messages. Replaces .list-group, whose
 * default is a boxed row inside a boxed card -- two borders saying the
 * same thing. One hairline between rows says it once. */
.data-list { border-top: 1px solid var(--rule); }
.data-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.15rem 0;
  border-bottom: 1px solid var(--rule);
}
.data-row-main { flex: 1 1 22rem; min-width: 0; }
.data-row-title {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 1.02rem;
  color: var(--ink);
  line-height: 1.35;
}

/* The metadata line. Interpuncts are drawn by the component rather than
 * typed into every template, so the spacing cannot drift item to item. */
.meta {
  font-size: .82rem;
  color: var(--ink-faint);
  line-height: 1.55;
  margin-top: .3rem;
}
.meta > * + *::before {
  /* The literal character, not "\00b7". A leading-zero escape is read as
   * \00 (which becomes U+FFFD) followed by a stray "b7" in at least one
   * engine, which is exactly how it rendered the first time. */
  content: "·";
  margin: 0 .45rem;
  color: var(--rule-strong);
}

/* One primary action per row and the rest as quiet links. Four buttons of
 * four different colours stacked in a column, which is what this replaces,
 * tells a customer nothing about which one they came here to press. */
.row-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .45rem;
  flex: 0 0 auto;
}
.row-actions-secondary {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: .1rem .85rem;
  font-size: .845rem;
}
.row-actions-secondary a,
.row-actions-secondary button {
  color: var(--ink-faint);
  text-decoration: none;
  border: 0;
  background: none;
  padding: 0;
  font-size: inherit;
  font-family: inherit;
  cursor: pointer;
}
.row-actions-secondary a:hover,
.row-actions-secondary button:hover {
  color: var(--accent-dark);
  text-decoration: underline;
}

/* An empty state is a page in its own right, not a stray sentence. This is
 * the first screen a new customer sees after signing up. */
.empty {
  border: 1px dashed var(--rule-strong);
  border-radius: var(--radius);
  background: var(--panel-sunk);
  padding: 2.25rem 1.75rem;
  text-align: center;
}
.empty-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.2rem;
  color: var(--ink);
}
.empty-body {
  font-size: .9rem;
  color: var(--ink-faint);
  max-width: 46ch;
  margin: .5rem auto 1.15rem;
  line-height: 1.6;
}

/* The calendar's headline number. Its job is to be readable across a room
 * during an inspection, which no Bootstrap utility class does. */
.stat-panel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
}
.stat-figure {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 3rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.stat-figure.is-low  { color: var(--danger); }
.stat-figure.is-mid  { color: var(--warn); }
.stat-figure.is-good { color: #5f7049; }
.stat-label {
  font-size: .715rem;
  text-transform: uppercase;
  letter-spacing: .085em;
  font-weight: 600;
  color: var(--ink-faint);
  text-align: right;
  margin-top: .3rem;
}
.stat-lede {
  font-family: var(--sans);
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--ink);
}

/* The inline record-this-happened form on each calendar row. */
.inline-form {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  align-items: center;
}
.inline-form .form-control { font-size: .85rem; padding: .3rem .55rem; }

.version-history {
  margin-top: .75rem;
  font-size: .845rem;
}
.version-history summary { color: var(--ink-faint); font-size: .82rem; }
.version-history ul { list-style: none; padding: 0; margin: .6rem 0 0; }
.version-history li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: .35rem 0;
  border-top: 1px solid var(--rule);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 575.98px) {
  .row-actions { align-items: stretch; width: 100%; }
  .row-actions-secondary { justify-content: flex-start; }
  .stat-figure { font-size: 2.4rem; }
  .stat-label { text-align: left; }
}

/* ------------------------------------------------------------- contact */
/*
 * Two columns for the fields that pair naturally. Not decoration: a form
 * that stacks seven single-column boxes reads as seven questions, and this
 * one is really three -- who you are, how to reach you, what you need.
 * Collapses to one column below the point where two boxes stop being
 * comfortably typeable side by side.
 */
.field-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1rem;
  margin-bottom: 1rem;
}
.field-grid > * { margin-bottom: 0; }

@media (max-width: 575.98px) {
  .field-grid { grid-template-columns: 1fr; gap: 0; }
  .field-grid > * { margin-bottom: 1rem; }
}

/* The required marker. Bootstrap has no convention for this and an
 * asterisk in body colour reads as a footnote rather than a rule. */
.req { color: var(--accent-dark); font-weight: 600; }

.contact-form .form-control.is-invalid {
  border-color: var(--danger);
  background-image: none;  /* Bootstrap's inline warning icon is off-palette */
}
.contact-form .form-control.is-invalid:focus {
  box-shadow: 0 0 0 .2rem rgba(180, 35, 24, .12);
}

/* -------------------------------------------------- centred form pages */
/*
 * A form as the page's whole purpose, rather than a form inside a page.
 * The panel is sunk rather than raised: it sits inside the card that
 * already carries the elevation, and two stacked shadows read as a bug.
 */
.form-page-head { text-align: center; margin-bottom: 1.75rem; }
.form-page-head h1 { margin-bottom: .5rem; }
.form-page-head p {
  color: var(--ink-faint);
  font-size: .975rem;
  line-height: 1.6;
  max-width: 52ch;
  margin: 0 auto;
}

.form-panel {
  background: var(--panel-sunk);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.5rem;
}

@media (min-width: 576px) {
  .form-panel { padding: 2rem; }
}

/* Bootstrap's floating labels, in our palette. The label is a real label
 * that moves, not a placeholder pressed into service -- a placeholder-only
 * field loses its name the moment somebody types in it, and screen readers
 * were never told the name at all. */
.form-floating > .form-control,
.form-floating > .form-control:focus {
  background: var(--panel);
  border-color: var(--rule-strong);
}
.form-floating > label { color: var(--ink-faint); font-weight: 500; }
.form-floating > .form-control:focus ~ label,
.form-floating > .form-control:not(:placeholder-shown) ~ label {
  color: var(--ink-faint);
}
/* Bootstrap paints the shrunk label's backdrop with an ::after block; left
 * at its default white it shows as a white notch on our off-white panel. */
.form-floating > .form-control:focus ~ label::after,
.form-floating > .form-control:not(:placeholder-shown) ~ label::after {
  background-color: var(--panel) !important;
}
.form-floating > textarea.form-control { min-height: 9.5rem; }

.legal-note {
  text-align: center;
  font-size: .82rem;
  color: var(--ink-faint);
  line-height: 1.55;
  margin: 1rem auto 0;
  max-width: 54ch;
}

/* Three doors out of a page somebody landed on with a question. Cheaper
 * for them than waiting two days for a reply, and cheaper for us than
 * answering the same three questions by hand. */
.resource-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  margin-top: 1rem;
}
.resource-card {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--panel);
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
}
.resource-card h3 {
  font-family: var(--sans);
  font-size: .975rem;
  font-weight: 600;
  margin: 0 0 .4rem;
}
.resource-card p {
  font-size: .855rem;
  color: var(--ink-faint);
  line-height: 1.55;
  flex: 1 1 auto;
  margin: 0 0 1rem;
}

@media (max-width: 767.98px) {
  .resource-cards { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------- pricing, across */
/*
 * Four tiers stacked down a page cannot be compared -- by the time you
 * reach Pro you are remembering Starter rather than reading it, and the
 * question a pricing page exists to answer is a comparison. Across, the
 * eye does the work instead.
 *
 * The grid steps rather than shrinking: four abreast only where each
 * column still has room for a feature line without hyphenating, two on a
 * tablet, one on a phone. A four-column grid squeezed onto 900px is worse
 * than two comfortable columns.
 */
.tier-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  align-items: stretch;
  margin-bottom: 1rem;
}
@media (min-width: 768px) {
  .tier-grid { grid-template-columns: repeat(2, 1fr); gap: 1.1rem; }
}
@media (min-width: 1200px) {
  .tier-grid { grid-template-columns: repeat(4, 1fr); }
}

/* In a row, the cards have to end level and the buttons have to line up,
 * or the comparison reads as a ranking of card heights. */
.tier-grid .tier {
  display: flex;
  flex-direction: column;
  margin-bottom: 0;
}
.tier-grid .tier-body { flex: 1 1 auto; }
.tier-grid .tier-cta { margin-top: auto; padding-top: .9rem; }
.tier-grid .tier-cta .btn { width: 100%; }

.tier-grid .tier-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .35rem;
}
.tier-grid .tier-head h2 { font-size: 1.1rem; margin: 0; }
.tier-grid .tier-price { font-size: 1.5rem; }
.tier-grid .tier-summary {
  font-size: .875rem;
  line-height: 1.55;
  color: var(--ink-soft);
}
.tier-grid .tier-list li { font-size: .82rem; line-height: 1.5; }

/* The featured card lifts out of the row rather than only changing colour,
 * which is the difference between "this one is recommended" and "this one
 * is a slightly different shade". */
@media (min-width: 1200px) {
  .tier-grid .tier-featured { transform: translateY(-10px); }
  .tier-grid .tier-featured .tier-cta { padding-bottom: 10px; }
}

/* --------------------------------------------------- form page, modern */
/*
 * A form page that looks like a form page rather than a document with
 * inputs in it. Three things, all cheap and all CSS:
 *
 *   1. A terracotta wash behind the panel, so the page has a subject.
 *   2. A panel that arrives rather than simply being there.
 *   3. Fields that stagger in behind it, which is the thing modern form
 *      templates do and the reason they feel considered.
 *
 * All of it is decoration and none of it is load-bearing: with animation
 * off, or CSS unloaded entirely, the form is identical and fully usable.
 * That ordering matters more than the effect -- an intake form is how
 * somebody buys, and it must not depend on a keyframe having run.
 */

.form-stage {
  position: relative;
  isolation: isolate;
}

/* The wash. Two soft radial pools rather than a flat tint: a flat
 * terracotta panel fights the text sitting on it, while pools at the
 * corners read as light in the room and leave the middle clean. Pinned
 * behind everything and pointer-events:none so it can never eat a click
 * on a field. */
.form-stage::before {
  content: "";
  position: absolute;
  /* Top pinned to main's own edge, not above it. A negative top inset
   * pushed the wash up behind the site header and tinted the nav, which
   * looked like a rendering bug rather than a design. */
  inset: 0 -18% auto -18%;
  height: 420px;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(42% 60% at 18% 0%,
                    rgba(217, 119, 87, .17) 0%, rgba(217, 119, 87, 0) 70%),
    radial-gradient(38% 55% at 88% 12%,
                    rgba(217, 119, 87, .11) 0%, rgba(217, 119, 87, 0) 72%);
}

@keyframes form-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

@keyframes form-field-rise {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: none; }
}

.form-stage .form-panel,
.form-stage > .card {
  animation: form-rise .5s cubic-bezier(.22, .68, .36, 1) both;
}

/* A hairline of accent along the top edge, on the OUTERMOST surface only.
 * The contact form is a panel inside a card, and putting the line on both
 * drew two parallel accent rules a centimetre apart, which reads as a
 * mistake rather than as emphasis. */
.form-stage > .card { border-top: 2px solid var(--accent); }
.form-stage > .card .form-panel { border-top-color: var(--rule); }

/* The stagger. One selector -- every direct child of the form -- rather
 * than a list of the classes fields happen to carry.
 *
 * Two bugs came out of the list version. It aimed at .form-panel > * and
 * silently did nothing, because the panel's only child is the <form>. And
 * once fixed to `form > .mb-3` it outranked the reduced-motion override
 * below on specificity (0,2,1 against 0,2,0), so a visitor who had asked
 * their system for less motion still got the animation. Matching
 * selectors on both sides is what makes the override actually override.
 *
 * Capped at eight: past that the last field waits long enough to feel
 * like the page is slow rather than smooth. */
.form-stage form > * {
  animation: form-field-rise .42s cubic-bezier(.22, .68, .36, 1) both;
}
.form-stage form > *:nth-child(1) { animation-delay: .06s; }
.form-stage form > *:nth-child(2) { animation-delay: .10s; }
.form-stage form > *:nth-child(3) { animation-delay: .14s; }
.form-stage form > *:nth-child(4) { animation-delay: .18s; }
.form-stage form > *:nth-child(5) { animation-delay: .22s; }
.form-stage form > *:nth-child(6) { animation-delay: .26s; }
.form-stage form > *:nth-child(7) { animation-delay: .30s; }
.form-stage form > *:nth-child(n+8) { animation-delay: .34s; }

/* Inputs that respond to being used. Transform on focus rather than only
 * a ring, which is what makes a field feel like a control rather than a
 * box. */
.form-stage .form-control,
.form-stage .form-select {
  transition: border-color .18s ease, box-shadow .18s ease,
              transform .18s ease;
}
.form-stage .form-control:focus,
.form-stage .form-select:focus {
  transform: translateY(-1px);
  box-shadow: 0 0 0 .22rem rgba(217, 119, 87, .14),
              0 2px 10px rgba(20, 20, 19, .05);
}

.form-stage .btn-primary { transition: transform .16s ease, filter .16s ease; }
.form-stage .btn-primary:hover { transform: translateY(-1px); }
.form-stage .btn-primary:active { transform: translateY(0); }

/* The step rail, on the intake. A filled marker for where you are reads
 * faster than a colour change on a word. */
.form-stage .steps li { transition: color .2s ease, border-color .2s ease; }

/*
 * NOT OPTIONAL. Vestibular disorders make motion a genuine accessibility
 * problem, not a taste one, and the whole effect above is decoration. A
 * visitor who has asked their operating system for less motion gets a
 * page that is finished the instant it paints -- no entrance, no
 * stagger, no lift on focus. Everything else, including the wash, stays.
 */
@media (prefers-reduced-motion: reduce) {
  /* Selectors deliberately identical to the ones above, so these win on
   * source order rather than by luck of specificity. */
  .form-stage .form-panel,
  .form-stage > .card,
  .form-stage form > * {
    animation: none;
  }
  .form-stage .form-control,
  .form-stage .form-select,
  .form-stage .btn-primary { transition: none; }
  .form-stage .form-control:focus,
  .form-stage .form-select:focus,
  .form-stage .btn-primary:hover { transform: none; }
}
