/* Counter design system: "Sunset" (docs/DESIGN.md v5).
   Calm, light, and warm. Big light numbers, small mono labels, one sunset
   gradient that always means "the answer." Every color is a token. */

/* Fonts live in the repo (fonts/, license in fonts/OFL.txt): latin only,
   so the page loads fast and works where Google Fonts is blocked. */

@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("fonts/geist-latin-300-normal.woff2") format("woff2");
}

@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/geist-latin-400-normal.woff2") format("woff2");
}

@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/geist-latin-500-normal.woff2") format("woff2");
}

@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/geist-mono-latin-400-normal.woff2") format("woff2");
}

@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/geist-mono-latin-500-normal.woff2") format("woff2");
}

:root {
  --ease: cubic-bezier(.2, .7, .2, 1);  /* every motion (DESIGN.md, Motion) */
  --bg: #ECECEA;      /* page */
  --paper: #F7F7F5;   /* pills, tally panel */
  --ink: #161616;     /* 15:1 */
  --ink-2: #4D4D4A;   /* secondary text, 7:1 */
  --muted: #6B6B67;   /* small labels, 4.5:1 on --bg. Never on the gradient */
  --line: #CFCFCB;    /* hairlines, decorative */
  --error: #B42318;
  --red: #E8432E;     /* the "now" dot on the rate chart, from the sunset */

  /* The answer. Only in four places: the screen 1 corner glow, the button's
     circle, the screen 2 hero panel, and paid hours in the chart. */
  --sunset: radial-gradient(55% 95% at 88% 100%, #E8432E 0%, rgba(232, 67, 46, 0) 70%),
            radial-gradient(50% 80% at 70% 80%, #FF8A3D 0%, rgba(255, 138, 61, 0) 70%),
            radial-gradient(40% 60% at 55% 55%, #F7B98F 0%, rgba(247, 185, 143, 0) 75%),
            linear-gradient(160deg, #C9D6EA 0%, #D9CDE6 40%, #EBC7B5 100%);
  /* The corner glow: the same colors, hottest at the center. */
  --glow: radial-gradient(circle, #E8432E 0%, #FF8A3D 24%, #F7B98F 44%, rgba(247, 185, 143, 0.35) 57%, rgba(235, 199, 181, 0) 71%);
  --paid: linear-gradient(90deg, #C9D6EA 0%, #EBC7B5 30%, #FF8A3D 70%, #E8432E 100%);
  /* Stripes always mean unpaid or forgotten hours. */
  --stripe: repeating-linear-gradient(90deg, var(--ink) 0 1px, transparent 1px 4px);
  /* Light grain over the gradients, about 8%. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");

  --font: "Geist", system-ui, sans-serif;
  --mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
  /* Longest comfortable line: about 75 characters. */
  --measure: 34em;

  /* The layout grid (docs/DESIGN.md, "Layout grid"): 12 columns on desktop,
     8 on tablet, 4 on phone. Content sits between two lines, --edge in from
     each side of the window, at most --frame wide and centered. Blocks span
     whole columns, with --column-gap between them. */
  --columns: 12;
  --column-gap: 32px;
  --edge: 64px;
  --frame: 1312px;
  /* The side margin. Percent is measured from the window, so this works as
     padding or margin on any full-width row. */
  --page-margin: max(var(--edge), calc((100% - var(--frame)) / 2));
}

/* Tablet: 760 to 1023px. */
@media (max-width: 1023px) {
  :root {
    --columns: 8;
    --column-gap: 24px;
    --edge: 40px;
  }
}

/* Phone: under 760px. */
@media (max-width: 759px) {
  :root {
    --columns: 4;
    --column-gap: 16px;
    --edge: 20px;
  }
}

/* Base */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The corner glow reaches past the screen edge; clip keeps the page from
   scrolling sideways. hidden is the fallback for browsers without clip. */
html,
body {
  overflow-x: hidden;
  overflow-x: clip;
}

html {
  -webkit-text-size-adjust: 100%;
}

/* On screen 2 the header row is sticky, so focused fields stay clear of it. */
html:has(body.on-results) {
  scroll-padding-top: 136px;
}

/* While an address like #result is being opened (index.html, head). */
.routing body {
  visibility: hidden;
}

body {
  position: relative;
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
p,
ul,
dl,
table {
  margin: 0;
}

ul {
  padding: 0;
  list-style: none;
}

input,
button,
textarea {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
}

button {
  cursor: pointer;
}

/* No single words left alone on a line, and balanced headings. */
p,
li,
dd,
label,
legend {
  text-wrap: pretty;
}

h1,
h2,
h3 {
  text-wrap: balance;
}

[hidden] {
  display: none !important;
}

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Focus: 2px ink outline, 3px offset. */
:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.skip-link {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 20;
  padding: 12px 16px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: none;
}

/* Data reads like data: units, chart labels, ticks, and small notes in mono. */
.mono-note,
.unit,
.forgotten-note,
.step,
.work-group > legend output {
  font-family: var(--mono);
  font-weight: 400;
}

.mono-note {
  font-size: 12px;
  color: var(--muted);
}

/* Screen 1's corner glow, with two thin circle outlines. Behind everything,
   and never over the form fields. */
.glow {
  position: absolute;
  top: -330px;
  right: -260px;
  z-index: 0;
  width: 820px;
  height: 820px;
  pointer-events: none;
}

.glow-sun {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--glow);
  filter: blur(48px);
  opacity: 0.85;
}

.glow-sun::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--grain);
  opacity: 0.08;
  mix-blend-mode: multiply;
}

.glow-ring {
  position: absolute;
  border: 1px solid rgba(22, 22, 22, 0.14);
  border-radius: 50%;
}

.glow-ring-1 {
  inset: 70px 120px 70px 20px;
}

.glow-ring-2 {
  inset: 140px 150px 120px 100px;
}

/* The glow belongs to screen 1 only. */
.glow {
  display: none;
}

.on-inputs .glow {
  display: block;
}

/* Header (screen 1) */

/* Full-width rows put their content on the grid lines with padding.
   (Percent padding is measured from the window, so --page-margin works here.) */
.topbar {
  position: relative;
  z-index: 1;
  padding: 0 var(--page-margin);
}

.topbar-inner {
  display: flex;
  align-items: center;
  gap: 24px;
  height: 64px;
}

/* The wordmark, then in a saved project "/ name Saved", all on one text
   baseline, 16px apart. (On phones the group falls away: see below.)
   The group fills the 64px row and the wordmark sits a fixed 17px from the
   top, (64 - its 30px line) / 2, as it does alone, so it never moves when a
   project opens: the slash, name, and status line up to it. */
.brand {
  display: flex;
  align-self: stretch;
  align-items: baseline;
  gap: 16px;
  min-width: 0;
  padding-top: 17px;
}

.crumb-slash {
  font-size: 20px;
  font-weight: 300;
  color: var(--muted);
}

.wordmark {
  font-size: 20px;
  font-weight: 400;
  letter-spacing: -0.035em;
  text-transform: lowercase;
}

/* The mark, left of the wordmark, sized from the type: as tall as the "t",
   on the baseline with the round letters' overshoot, and as far from the "c"
   as the ring's thick side. */
.wordmark-mark {
  width: 0.666em;
  height: 0.666em;
  vertical-align: -0.012em;
  margin-right: 0.166em;
}

/* Screen 2: the header is the first of two sticky rows. */
.on-results .topbar {
  position: sticky;
  top: 0;
  z-index: 11;
  background: var(--bg);
}

/* "Projects 3" and the save button, on the right of every header. */
/* Pushed to the right end of the header, with the save button after it. */
.projects-link {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  font-size: 14px;
  color: var(--ink);
  text-decoration: none;
}

.projects-link[aria-current="page"] .projects-word {
  text-decoration: underline;
  text-underline-offset: 4px;
}

.projects-count {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--paper);
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-2);
}

.save-button {
  min-height: 36px;
  padding: 0 16px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font-size: 14px;
}

/* Share: a text button like Projects, between Projects and Save (screen 2).
   "Share" and "Copied" share one grid cell, the inactive one hidden, so the
   button is as wide as the wider label and nothing moves when it changes. */
.share-button {
  display: inline-grid;
  place-items: center;
  min-height: 36px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font-size: 14px;
}

.share-state {
  grid-area: 1 / 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.share-done,
.share-button.copied .share-idle {
  visibility: hidden;
}

.share-button.copied .share-done {
  visibility: visible;
}

/* "Shared result. Change anything to make it yours." Mono, with a small ink dot. */
.shared-note {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-2);
}

.shared-dot {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ink);
  transform: translateY(-1px);
}

.results-body.shared-row {
  padding-bottom: 12px;
}

.inputs-top .shared-note {
  margin-bottom: 16px;
}

.share-field .unit-input {
  display: flex;
  margin-top: 6px;
  border-bottom: 1px solid var(--ink);
}

.share-field input {
  width: 100%;
  padding: 0 0 4px;
  border: 0;
  background: transparent;
  font-family: var(--mono);
  font-size: 14px;
}

.share-field .mono-note {
  margin-top: 6px;
}

/* In a saved project the button just says "Saved", and can't be pressed. */
.save-button:disabled {
  border-color: var(--line);
  background: transparent;
  color: var(--ink-2);
  cursor: default;
}

/* Dialogs: Save as project, Start over?, Open the shared result?, and the
   link to copy. Styled like the image preview: --bg, 28px radius, a dim
   backdrop. Centered on desktop, a bottom sheet on phones. They only fade in. */
.panel-dialog {
  width: min(480px, calc(100vw - 48px));
  max-height: calc(100vh - 48px);
  padding: 32px;
  border: 0;
  border-radius: 28px;
  background: var(--bg);
  color: var(--ink);
}

.panel-dialog[open] {
  display: flex;
  flex-direction: column;
  gap: 28px;
  animation: dialog-fade 160ms ease-out;
}

.panel-dialog::backdrop {
  background: rgba(22, 22, 22, 0.45);
  animation: dialog-fade 160ms ease-out;
}

.save-form {
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.save-form .unit-input {
  display: flex;
  margin-top: 6px;
  border-bottom: 1px solid var(--ink);
}

.save-form .unit-input input {
  width: 100%;
  padding: 0 0 4px;
  border: 0;
  background: transparent;
  font-size: 24px;
  font-weight: 300;
  letter-spacing: -0.02em;
}

.save-form .mono-note {
  margin-top: 6px;
}

.panel-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.start-over-question {
  font-size: 16px;
  line-height: 1.5;
}

/* Screen 1: inputs */

.screen-projects,
.screen-inputs,
.site-footer {
  position: relative;
  z-index: 1;
  padding-left: var(--page-margin);
  padding-right: var(--page-margin);
}

.screen-projects,
.screen-inputs {
  padding-top: 44px;
}

h1 {
  font-size: 84px;
  font-weight: 300;
  letter-spacing: -0.045em;
  line-height: 0.98;
}

h1:focus {
  outline: none;
}

.headline-break {
  display: block;
}

.lede {
  max-width: var(--measure);
  margin-top: 28px;
  font-size: 19px;
  line-height: 1.45;
  color: var(--ink-2);
}

.example-note {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}

/* Two columns: 01 and 02 on the left; the tally, 03, 04, and the button on the right. */
.inputs-columns {
  display: grid;
  row-gap: 0;
  padding-top: 64px;
}

fieldset {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

legend {
  padding: 0;
}

.inputs-column .section + .section,
.tally + .section {
  margin-top: 56px;
}

/* Section titles: a mono number pill, then the title in Geist light. */
.section > legend {
  float: left;
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  margin-bottom: 24px;
  font-size: 26px;
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.section > legend + * {
  clear: both;
}

.step {
  display: inline-grid;
  place-items: center;
  min-width: 46px;
  height: 32px;
  padding: 0 12px;
  border-radius: 999px;
  background: var(--paper);
  font-size: 12px;
  letter-spacing: 0;
  color: var(--ink);
}

.hint {
  max-width: var(--measure);
  margin-top: 8px;
  font-size: 13px;
  color: var(--muted);
}

/* "Example hours…" under 02 The work. */
.section-hint {
  margin: 0 0 24px;
}

/* Under it: "Add at least one hour of work." and the weeks note. */
.work-error,
.weeks-note {
  margin: -12px 0 24px;
}

/* The field: text tabs with an underline, above the job pills. Real radios. */
.field-tabs {
  display: flex;
  gap: 28px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--line);
}

.field-tabs input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
}

.field-tabs label {
  display: flex;
  align-items: center;
  min-height: 44px;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  font-size: 16px;
  color: var(--ink-2);
  white-space: nowrap;
  cursor: pointer;
}

.field-tabs input:checked + label {
  border-bottom-color: var(--ink);
  color: var(--ink);
}

/* .keyboard-nav: Safari drops :focus-visible when arrow keys move between
   radios, so the ring also shows on a focused radio after a key press. */
.field-tabs input:focus-visible + label,
.keyboard-nav .field-tabs input:focus + label {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* Segmented controls: the job and "Did they offer an amount?" Real radios. */
.segmented {
  display: inline-flex;
  flex-wrap: nowrap;
  padding: 4px;
  border-radius: 999px;
  background: var(--paper);
}

/* Desktop: when a field's jobs don't fit the column, the pills wrap onto a
   second line, left-aligned, and the paper becomes a 24px rounded rectangle
   around both lines (app.js adds .wrapped). Phone keeps the scrolling row. */
@media (min-width: 760px) {
  .job-choice {
    flex-wrap: wrap;
    justify-content: flex-start;
    row-gap: 4px;
    max-width: 100%;
  }

  .job-choice label {
    flex: none;
  }

  .job-choice.wrapped {
    border-radius: 24px;
  }
}

.segmented input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
}

.segmented label {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 18px;
  border-radius: 999px;
  font-size: 15px;
  color: var(--ink-2);
  white-space: nowrap;
  cursor: pointer;
}

.segmented input:checked + label {
  background: var(--ink);
  color: var(--paper);
}

.segmented input:focus-visible + label,
.keyboard-nav .segmented input:focus + label {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* "Replace your numbers with the Logo example?" Small rectangles, not pills:
   actions must not look like choices. */
.job-replace {
  margin-top: 16px;
  font-size: 14px;
}

.job-replace-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.action-button {
  min-height: 36px;
  padding: 0 14px;
  border: 1px solid var(--ink);
  border-radius: 6px;
  background: var(--ink);
  color: var(--paper);
  font-size: 14px;
}

.action-button.outline {
  background: transparent;
  color: var(--ink);
}

/* Steppers: 44px circles, minus outlined, plus solid ink. */
.steppers {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 56px;
  margin-top: 32px;
}

.stepper-field > label {
  display: block;
  margin-bottom: 8px;
  font-size: 13px;
  color: var(--muted);
}

.stepper {
  display: flex;
  align-items: center;
  gap: 8px;
}

.stepper button {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--ink);
  border-radius: 50%;
  background: transparent;
  font-size: 16px;
  line-height: 1;
}

.stepper button[data-step="1"] {
  background: var(--ink);
  color: var(--paper);
}

.stepper input {
  width: 2.2ch;
  min-width: 2.2ch;
  padding: 0;
  border: 0;
  border-bottom: 1px solid transparent;
  background: transparent;
  font-size: 34px;
  font-weight: 300;
  line-height: 1.2;
  text-align: center;
}

@supports (field-sizing: content) {
  .stepper input {
    field-sizing: content;
    width: auto;
    padding-inline: 0.2ch;
  }
}

.stepper input[aria-invalid="true"] {
  border-bottom-color: var(--error);
}

#steppers-hint {
  margin-top: 16px;
}

/* 02 The work */

.work-group {
  margin-top: 24px;
}

.work-group:first-of-type {
  margin-top: 0;
}

.work-group > legend {
  float: left;
  display: flex;
  align-items: baseline;
  width: 100%;
  font-size: 13px;
  font-weight: 500;
}

.work-group > legend output {
  margin-left: auto;
  font-size: 13px;
  color: var(--muted);
}

.work-group > legend + * {
  clear: both;
}

/* Label, then a small bar of that row's hours, then the input. */
.work-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 150px 90px;
  column-gap: 20px;
  align-items: center;
  padding: 12px 0 14px;
  border-bottom: 1px solid var(--line);
}

.row-label {
  font-size: 16px;
}

.forgotten-note {
  margin-left: 8px;
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

.work-row > .hint,
.work-row > .error {
  grid-column: 1 / -1;
}

/* Solid ink is design work; stripes are the hours people forget. */
.row-bar {
  height: 12px;
  background: var(--ink);
}

.row-bar.forgotten {
  background: var(--stripe);
  outline: 1px solid var(--ink);
  outline-offset: -1px;
}

.row-bar.empty {
  visibility: hidden;
}

/* Hours inputs: a 1px ink underline, "hrs" in mono after the value. */
.work-row .unit-input {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 6px;
  border-bottom: 1px solid var(--ink);
}

.work-row .unit-input input {
  width: 100%;
  min-width: 0;
  padding: 0 0 4px;
  border: 0;
  background: transparent;
  font-size: 24px;
  font-weight: 300;
  text-align: right;
}

.unit {
  font-size: 12px;
  color: var(--muted);
}

/* The box shows focus, so the field itself doesn't need its own outline. */
.unit-input input:focus-visible {
  outline: none;
}

.unit-input:focus-within {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.unit-input:has([aria-invalid="true"]) {
  border-bottom-color: var(--error);
}

/* The tally panel: big total, then one bar of all groups. */
.tally {
  padding: 32px 28px 28px;
  border-radius: 24px;
  background: var(--paper);
}

.tally-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}

.tally-title {
  font-size: 14px;
  font-weight: 400;
}

.tally-total {
  margin-top: 16px;
  line-height: 1;
}

.tally-total output {
  font-size: 96px;
  font-weight: 300;
  letter-spacing: -0.05em;
  line-height: 0.9;
}

.tally-unit {
  margin-left: 12px;
  font-family: var(--mono);
  font-size: 15px;
  color: var(--muted);
}

.tally-bar {
  margin-top: 28px;
}

.tally-segments {
  display: flex;
  gap: 2px;
}

.tally-segment {
  flex: none;
  height: 14px;
  background: var(--ink);
}

.tally-segment.forgotten {
  background: var(--stripe);
  outline: 1px solid var(--ink);
  outline-offset: -1px;
}

.tally-labels {
  position: relative;
  height: 20px;
  margin-top: 10px;
}

.tally-label {
  position: absolute;
  top: 0;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

.tally-label.second-row {
  top: 18px;
}

.tally-labels:has(.second-row) {
  height: 38px;
}

/* 03 Your numbers and 04 Their offer: big light values in two columns. */

.field-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 28px;
  align-items: start;
}

.offer-row {
  align-items: start;
}

.field > label,
.field-label {
  display: block;
  font-size: 13px;
  color: var(--muted);
}

.field-label + .segmented {
  margin-top: 12px;
}

.field-row .unit-input,
.result-block .unit-input {
  display: flex;
  align-items: baseline;
  gap: 2px;
  margin-top: 8px;
  border-bottom: 1px solid var(--ink);
  cursor: text;
}

.field-row .unit-input input,
.result-block .unit-input input {
  width: 100%;
  min-width: 0;
  padding: 0 0 6px;
  border: 0;
  background: transparent;
  font-size: 40px;
  font-weight: 300;
  letter-spacing: -0.03em;
  line-height: 1.15;
}

.currency {
  font-size: 40px;
  font-weight: 300;
  letter-spacing: -0.03em;
}

.field-row .unit-input .unit {
  margin-left: 6px;
}

@supports (field-sizing: content) {
  .field-row .unit-input input {
    field-sizing: content;
    width: auto;
    min-width: 1ch;
  }
}

/* Errors: icon plus message under the row. */

.error {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 8px;
  font-size: 13px;
  color: var(--error);
}

.error .icon {
  flex: none;
  margin-top: 1px;
}

/* The button: ink, fully rounded, with the gradient circle at the end.
   The circle previews the answer. */
.check-button {
  display: flex;
  align-items: center;
  width: 100%;
  height: 80px;
  margin-top: 44px;
  padding: 0 10px 0 32px;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  text-align: left;
}

.check-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.check-title {
  font-size: 20px;
  line-height: 1.2;
}

.check-preview {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--line);
}

.check-circle {
  flex: none;
  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: var(--sunset);
  color: var(--ink);
}

/* Footer */
.site-footer {
  padding-bottom: 40px;
}

.site-footer p {
  margin-top: 72px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--muted);
}

.on-results .site-footer p {
  margin-top: 0;
}

/* In a saved project: its name, then "Saved", in the header. */
.crumb {
  display: flex;
  align-items: baseline;
  gap: 16px;
  min-width: 0;
  font-size: 14px;
}

.crumb-name {
  max-width: 280px;
  overflow: hidden;
  padding: 4px 0;
  border: 0;
  background: none;
  font-size: 14px;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: text;
}

.crumb-input {
  width: 280px;
  padding: 2px 0;
  border: 0;
  border-bottom: 1px solid var(--ink);
  background: transparent;
  font-size: 14px;
}

.crumb-input:focus-visible {
  outline: none;
}

.save-status {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
}

/* When saving fails: the page keeps working and says so. */
.save-error {
  position: relative;
  z-index: 2;
  /* Its outer edge sits on the layout grid lines, like the hero panel. */
  margin: 8px var(--page-margin) 0;
  padding: 12px 16px;
  border: 1px solid var(--error);
  border-radius: 12px;
  background: var(--paper);
  font-size: 14px;
  color: var(--error);
}

/* Projects home */

/* "Back to calculator" (or the project's name) above the title. */
.back-to-calc {
  max-width: 100%;
  margin-bottom: 28px;
}

.back-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.home-top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
}

.projects-empty {
  margin-top: 40px;
}

.projects-empty p {
  max-width: var(--measure);
  font-size: 19px;
  line-height: 1.45;
  color: var(--ink-2);
}

.projects-empty .round-button {
  margin-top: 28px;
}

.project-table {
  width: 100%;
  margin-top: 56px;
  border-collapse: collapse;
}

.project-table thead th {
  padding: 0 16px 12px 0;
  border-bottom: 1px solid var(--ink);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  color: var(--muted);
  text-align: left;
}

.project-table tbody th,
.project-table td {
  padding: 18px 16px 18px 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: middle;
}

.project-name {
  width: 34%;
  font-weight: 400;
}

.project-open {
  max-width: 100%;
  padding: 4px 0;
  border: 0;
  background: none;
  font-size: 26px;
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.2;
  text-align: left;
  overflow-wrap: anywhere;
}

.row-rename {
  width: 100%;
  padding: 4px 0;
  border: 0;
  border-bottom: 1px solid var(--ink);
  background: transparent;
  font-size: 26px;
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.row-rename:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.project-job,
.project-edited {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-2);
  white-space: nowrap;
}

.project-edited {
  color: var(--muted);
}

.project-estimate {
  font-size: 22px;
  font-weight: 300;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.project-offer {
  font-size: 15px;
  color: var(--ink-2);
  white-space: nowrap;
}

.project-table td.project-actions {
  padding-right: 0;
  text-align: right;
  white-space: nowrap;
}

.row-action {
  min-height: 44px;
  padding: 0 10px;
  border: 0;
  background: none;
  font-size: 13px;
  color: var(--ink-2);
}

.row-action:last-child {
  padding-right: 0;
}

.delete-question {
  margin-right: 12px;
  font-size: 14px;
  white-space: normal;
}

.project-actions .action-button + .action-button {
  margin-left: 8px;
}

.storage-note {
  margin-top: 32px;
}

/* Your pricing so far (docs/DESIGN.md, "Projects dashboard"). Cards on the
   column grid: the hero and the chart card full width, three cards 4 + 4 + 4
   on desktop; on tablet Biggest fix takes its own row; on phones they stack. */

.dashboard-empty {
  max-width: var(--measure);
  margin-top: 40px;
  font-size: 16px;
  color: var(--ink-2);
}

.dashboard {
  display: grid;
  grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
  gap: var(--column-gap);
  margin-top: 40px;
}

.dash-card {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 32px 40px;
  border: 1px solid var(--line);
  border-radius: 24px;
  background: var(--paper);
}

@media (min-width: 760px) {
  .dash-unpaid,
  .dash-met {
    grid-column: span 4;
  }
}

@media (min-width: 1024px) {
  .dash-fix {
    grid-column: span 4;
  }
}

/* The outlined pill every card starts with. */
.dash-pill {
  align-self: flex-start;
  padding: 6px 16px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: 0;
}

.dash-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.table-toggle {
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  font-size: 13px;
  color: var(--ink-2);
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}

.dash-figure {
  margin: 0;
}

.wide-only,
.narrow-only {
  display: inline;
}

@media (min-width: 1024px) {
  .narrow-only {
    display: none;
  }
}

@media (max-width: 1023px) {
  .wide-only {
    display: none;
  }
}

/* The hero: the sentence on the left, the percent on the right. */
.dash-hero-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 32px;
  margin-top: 8px;
}

.dash-hero-text {
  max-width: 34em;
  padding-top: 16px;
}

.dash-lead {
  font-size: 24px;
  font-weight: 300;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

.dash-gapline {
  margin-top: 12px;
  font-size: 15px;
  color: var(--ink-2);
}

.dash-meta {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}

/* The big number repeats the sentence. Its tall glyphs reach over the
   "Show as table" button, so it never takes clicks. */
.dash-percent {
  flex-shrink: 0;
  pointer-events: none;
  font-size: 180px;
  font-weight: 300;
  line-height: 0.85;
  letter-spacing: -0.05em;
}

/* The waterfall: target pay, one floating step per job, you kept. */
.dash-hero .dash-figure {
  margin-top: 32px;
}

.wf-plot {
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--wf-count), minmax(0, 1fr));
  column-gap: 16px;
  height: 220px;
  margin-top: 40px;
}

.wf-labels {
  display: grid;
  grid-template-columns: repeat(var(--wf-count), minmax(0, 1fr));
  column-gap: 16px;
  margin-top: 12px;
}

.wf-col {
  position: relative;
  grid-row: 1;
}

.wf-bar {
  position: absolute;
  left: 0;
  right: 0;
  min-height: 2px;
  border-radius: 4px;
}

.wf-bar.total {
  background: var(--line);
}

.wf-bar.kept,
.wf-bar.gain,
.dash-paid {
  background: var(--paid);
}

.wf-bar.short,
.dash-short {
  background: var(--stripe);
  box-shadow: inset 0 0 0 1px var(--ink);
}

.wf-value {
  position: absolute;
  left: -8px;
  right: -8px;
  margin-bottom: 6px;
  font-size: 16px;
  line-height: 1.2;
  text-align: center;
  color: var(--ink-2);
  white-space: nowrap;
}

.wf-value.total {
  font-size: 20px;
  font-weight: 500;
  color: var(--ink);
}

.wf-link {
  position: absolute;
  left: 100%;
  width: 16px;
  height: 0;
  border-top: 1px dashed var(--ink-2);
}

.wf-baseline {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 1;
  height: 0;
  border-top: 1px solid var(--ink);
}

.wf-label {
  min-width: 0;
  text-align: center;
}

.wf-label .wf-name {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  font-size: 14px;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.wf-note {
  display: block;
  margin-top: 2px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}

.wf-rows {
  display: none;
}

@media (max-width: 1023px) {
  .wf-cols {
    display: none;
  }

  .wf-rows {
    display: block;
  }
}

.wf-row {
  padding: 8px 0;
}

.wf-row.kept {
  margin-top: 8px;
  padding-top: 16px;
  border-top: 1px solid var(--ink);
}

.wf-row-line {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 14px;
}

.wf-row-line .wf-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wf-row-value {
  flex-shrink: 0;
  font-weight: 500;
}

.wf-row:not(.total):not(.kept) .wf-row-value {
  font-weight: 400;
  color: var(--ink-2);
}

.wf-track {
  position: relative;
  height: 12px;
  margin-top: 6px;
}

.wf-track .wf-bar {
  top: 0;
  bottom: 0;
  right: auto;
  min-width: 2px;
  border-radius: 3px;
}

/* Unpaid hours and Jobs at your target. */
.dash-number {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 32px;
}

.dash-big {
  font-size: 72px;
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.04em;
}

.dash-unit {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink-2);
}

.dash-line {
  margin-top: 16px;
  font-size: 15px;
  color: var(--ink-2);
}

.dash-bar {
  display: flex;
  gap: 2px;
  height: 20px;
  margin-top: 24px;
}

.dash-bar > span {
  flex-basis: 0;
  min-width: 0;
}

.dash-bar-labels {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 4px 16px;
  margin-top: 8px;
  font-size: 13px;
  color: var(--ink-2);
}

.dash-strong {
  font-weight: 500;
  color: var(--ink);
}

.met-list {
  margin-top: 20px;
}

.met-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0;
  border-top: 1px solid var(--line);
  font-size: 14px;
}

.met-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.met-status {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-2);
}

.met-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
}

.met-more {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}

/* Biggest fix: the sunset with a 35% paper wash, like the picked gap card. */
.dash-fix {
  border-color: var(--ink);
  background: linear-gradient(rgba(247, 247, 245, 0.35), rgba(247, 247, 245, 0.35)), var(--sunset);
}

.dash-fix .dash-line {
  color: var(--ink);
}

.dash-fix-amount {
  margin-top: 32px;
}

.fix-chart {
  margin-top: 24px;
}

.fix-bar {
  display: flex;
  height: 12px;
}

.fix-bar > span {
  flex: none;
}

.fix-now {
  background: var(--ink);
}

.fix-track {
  background: var(--paper);
}

.fix-labels {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  min-width: max-content;
  max-width: 100%;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 12px;
  /* Ink: over the warm part of the gradient, ink-2 measured under 4.5:1. */
  color: var(--ink);
}

.fix-button {
  align-self: flex-start;
  min-height: 44px;
  margin-top: 24px;
  padding: 0 20px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: var(--ink);
  font-size: 14px;
  color: var(--paper);
  text-align: left;
  transition: background 160ms var(--ease), color 160ms var(--ease);
}

.fix-button:hover {
  background: var(--ink-2);
}

/* Each job vs your target: a bullet chart from 0% to 150%. */
.dash-title {
  margin-top: 24px;
  font-size: 24px;
  font-weight: 300;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

.dash-each .dash-line {
  margin-top: 8px;
}

.dash-each .dash-figure {
  margin-top: 32px;
}

.bullet-rows {
  position: relative;
}

.bullet-grid {
  display: grid;
  grid-template-columns: 22% minmax(0, 1fr) 76px 132px;
  column-gap: 20px;
  align-items: center;
}

.bullet-name {
  grid-column: 1;
  min-width: 0;
  overflow: hidden;
  font-size: 15px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bullet-grid > .bullet-track {
  grid-column: 2;
  position: relative;
  align-self: stretch;
  display: flex;
  align-items: center;
}

/* The target line at 100%, dashed, through every row. */
.bullet-rows .bullet-track::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(100% / 1.5);
  border-left: 1px dashed var(--ink);
}

.bullet-head {
  height: 28px;
}

.bullet-target-label {
  position: absolute;
  bottom: 6px;
  left: calc(100% / 1.5);
  padding-left: 8px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-2);
  white-space: nowrap;
}

.bullet-row {
  min-height: 44px;
}

.bullet-bar {
  display: flex;
  width: 100%;
  height: 20px;
}

.bullet-bar > span {
  flex: none;
}

.bullet-value {
  grid-column: 3;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.2;
}

.bullet-rate {
  grid-column: 4;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-2);
  white-space: nowrap;
}

.bullet-axis {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
}

.bullet-axis .bullet-track {
  height: 16px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}

.bullet-axis span {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
}

.bullet-axis span:nth-child(1) { left: 0; transform: none; }
.bullet-axis span:nth-child(2) { left: calc(100% / 3); }
.bullet-axis span:nth-child(3) { left: calc(200% / 3); }
.bullet-axis span:nth-child(4) { left: 100%; transform: translateX(-100%); }

.bullet-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin-top: 20px;
  font-size: 12px;
  color: var(--ink-2);
}

.bullet-legend li {
  display: flex;
  align-items: center;
  gap: 8px;
}

.legend-key {
  width: 16px;
  height: 10px;
}

.bullet-tip {
  position: absolute;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: max-content;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--ink);
  color: var(--paper);
  font-size: 12px;
  line-height: 1.4;
  pointer-events: none;
}

.bullet-tip[hidden] {
  display: none;
}

.bullet-tip-name {
  font-size: 13px;
  font-weight: 500;
}

.bullet-tip-line {
  font-family: var(--mono);
}

/* Below 1024px: name and percent on one line, the bar under them, the rate under that. */
@media (max-width: 1023px) {
  .bullet-grid {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 16px;
  }

  .bullet-grid > .bullet-track {
    grid-column: 1 / -1;
  }

  .bullet-head {
    height: 24px;
  }

  .bullet-row {
    row-gap: 6px;
    padding: 10px 0;
  }

  .bullet-row .bullet-track {
    grid-row: 2;
  }

  .bullet-value {
    grid-column: 2;
    grid-row: 1;
    text-align: right;
  }

  .bullet-rate {
    grid-column: 1 / -1;
    grid-row: 3;
  }

  .bullet-bar {
    height: 16px;
  }
}

/* The tables behind "Show as table". */
.dash-table-wrap {
  overflow-x: auto;
}

.dash-table {
  width: 100%;
  margin-top: 8px;
  border-collapse: collapse;
  font-size: 14px;
}

.dash-table th,
.dash-table td {
  padding: 10px 16px 10px 0;
  border-bottom: 1px solid var(--line);
  font-weight: 400;
  text-align: left;
  vertical-align: top;
}

.dash-table thead th {
  border-bottom-color: var(--ink);
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
}

.dash-table td {
  white-space: nowrap;
}

.all-projects-title {
  margin-top: 72px;
  font-size: 26px;
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.all-projects-title + .project-table {
  margin-top: 24px;
}

/* The summary card on a saved result. */
.pricing-card {
  max-width: 720px;
  margin-top: 56px;
  padding: 28px;
  border: 1px solid var(--line);
  border-radius: 24px;
  background: var(--paper);
}

.pricing-card .dash-pill {
  display: inline-block;
}

.pricing-card-number {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 16px;
  margin-top: 20px;
}

.pricing-card-percent {
  font-size: 64px;
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.04em;
}

.pricing-card-text {
  font-size: 15px;
  color: var(--ink-2);
}

.pricing-card .dash-bar {
  height: 12px;
  margin-top: 20px;
}

.mono-labels {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}

.pricing-card-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 8px;
  font-size: 15px;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (max-width: 1023px) {
  .dash-percent {
    font-size: 140px;
  }
}

@media (max-width: 759px) {
  .dash-card {
    padding: 20px;
  }

  .dash-hero-top {
    flex-direction: column;
    gap: 8px;
  }

  .dash-percent {
    order: -1;
    font-size: 104px;
  }

  .dash-hero-text {
    padding-top: 0;
  }

  .dash-big {
    font-size: 56px;
  }

  .pricing-card {
    max-width: none;
    padding: 20px;
  }

  .pricing-card-percent {
    font-size: 56px;
  }
}

/* Screen 2: result */

/* Header row: wordmark, Edit details, then the live controls on the right. */
.results-header {
  position: sticky;
  top: 64px;
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 28px;
  min-height: 64px;
  padding: 8px var(--page-margin);
  background: var(--bg);
}

.edit-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 0 16px;
  border: 0;
  border-radius: 999px;
  background: var(--paper);
  font-size: 14px;
  color: var(--ink-2);
}

.control-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 28px;
  margin-left: auto;
}

.bar-stepper,
.bar-field {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 6px;
}

.bar-stepper label,
.bar-field label {
  margin-right: 6px;
  font-size: 13px;
  color: var(--ink-2);
}

/* 30px circles inside 44px touch targets. */
.bar-stepper button {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: 0 -6px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  font-size: 13px;
  line-height: 1;
}

.bar-stepper button::before {
  content: "";
  position: absolute;
  inset: 7px;
  z-index: -1;
  border: 1px solid var(--ink);
  border-radius: 50%;
}

.bar-stepper button[data-step="1"] {
  color: var(--paper);
}

.bar-stepper button[data-step="1"]::before {
  background: var(--ink);
}

.bar-stepper input {
  width: 2.2ch;
  padding: 0 6px;
  border: 0;
  background: transparent;
  font-size: 20px;
  font-weight: 300;
  text-align: center;
}

.bar-input {
  display: inline-flex;
  align-items: baseline;
  border-bottom: 1px solid var(--ink);
  font-size: 20px;
  font-weight: 300;
}

.bar-input .currency {
  font-size: 20px;
}

.bar-input .unit {
  font-family: var(--font);
  font-size: 20px;
  color: var(--ink);
}

.bar-input:focus-within {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.bar-input input {
  width: 4ch;
  padding: 0 0 2px;
  border: 0;
  background: transparent;
}

.bar-input input:focus-visible {
  outline: none;
}

@supports (field-sizing: content) {
  .bar-input input,
  .bar-stepper input {
    field-sizing: content;
    width: auto;
    min-width: 1ch;
  }
}

/* An error under its bar field: icon plus message. */
.bar-error {
  flex-basis: 100%;
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin-top: 2px;
  font-size: 12px;
  color: var(--error);
}

.bar-error .icon {
  flex: none;
  width: 14px;
  height: 14px;
  margin-top: 1px;
}

/* The hero panel: the sunset gradient, about 380px tall. */
.hero-panel {
  position: relative;
  min-height: 380px;
  margin: 0 var(--page-margin);
  padding: 44px 48px 40px;
  border-radius: 28px;
  background: var(--sunset);
  overflow: hidden;
}

.hero-panel::after,
.reveal-orb::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--grain);
  opacity: 0.08;
  mix-blend-mode: multiply;
  pointer-events: none;
}

.hero-content {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 296px;
}

.hero-top {
  display: flex;
  justify-content: space-between;
  gap: 32px;
}

.hero-label {
  font-size: 16px;
  color: var(--ink-2);
}

.hero-label:focus,
.empty-state:focus {
  outline: none;
}

/* Top right, over the cool part of the gradient: ink and ink-2 only. */
.hero-aside {
  max-width: 300px;
  text-align: right;
}

.hero-job {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-2);
}

.hero-sentence {
  margin-top: 12px;
  font-size: 20px;
  line-height: 1.4;
}

.results-body.hero-after {
  padding-bottom: 0;
}

.hero-weeks {
  margin-top: 16px;
  color: var(--ink-2);
}

.warning {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
  font-size: 20px;
  line-height: 1.4;
}

.warning .icon {
  flex: none;
  margin-top: 6px;
}

.hero-number {
  margin-top: 0;
}

.hero-digits {
  display: inline-flex;
  align-items: flex-start;
  font-size: 220px;
  font-weight: 300;
  letter-spacing: -0.06em;
  line-height: 0.8;
}

/* "$" at 32% size, raised. */
.hero-currency {
  margin-right: 0.08em;
  font-size: 32%;
  letter-spacing: 0;
  line-height: 1;
  transform: translateY(-0.08em);
}

.hero-unit {
  align-self: flex-end;
  margin-left: 0.12em;
  font-family: var(--mono);
  font-size: 22px;
  letter-spacing: 0;
  line-height: 1;
  color: var(--ink);
}

.empty-state {
  max-width: var(--measure);
  font-size: 20px;
}

/* Below the panel: content lines up with the panel's outside edge. */
.results-body {
  padding: 0 var(--page-margin) 72px;
}

/* Stats: 4 columns, a hairline above each. */
.stats {
  display: grid;
  row-gap: 28px;
  margin-top: 8px;
}

/* The hairline is drawn, so it can draw left to right when the stats play. */
.stats > div {
  position: relative;
  padding-top: 28px;
}

.stats > div::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--line);
  transform-origin: left;
}

@keyframes line-draw {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

.stats.play > div::before {
  animation: line-draw 500ms var(--ease) both;
}

.stats dt {
  font-size: 14px;
  color: var(--ink-2);
}

.stats dd {
  margin: 8px 0 0;
  white-space: nowrap;
  font-size: 46px;
  font-weight: 300;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.stat-unit {
  margin-left: 6px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0;
  color: var(--ink-2);
}

.stat-note {
  display: block;
  white-space: normal;
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0;
  line-height: 1.4;
  color: var(--muted);
}

/* The two charts side by side. */
.charts-row {
  display: grid;
  row-gap: 56px;
  margin-top: 52px;
}

.chart h2,
.result-block > legend {
  font-size: 22px;
  font-weight: 300;
  letter-spacing: -0.02em;
}

.chart-sub {
  margin-top: 6px;
  font-size: 14px;
  color: var(--ink-2);
}

.chart-summary {
  max-width: var(--measure);
  margin-top: 12px;
  font-size: 14px;
  color: var(--ink-2);
}

.chart-summary strong {
  font-weight: 400;
  color: var(--ink);
}

/* Chart 1: the bracket at the top, the runs-out label at 48px, bars from 76px. */
.bars {
  position: relative;
  margin-top: 24px;
  padding-top: 76px;
}

.bracket {
  position: absolute;
  top: 26px;
  height: 10px;
  border: 1px solid var(--ink);
  border-bottom: 0;
}

.bracket-label {
  position: absolute;
  bottom: 16px;
  left: 0;
  font-family: var(--mono);
  font-size: 12px;
  white-space: nowrap;
}

/* A dashed line from the label row down through the bars. */
.runs-out {
  position: absolute;
  top: 48px;
  z-index: 1;
  width: 0;
  height: calc(28px + 96px);
  border-left: 1px dashed var(--ink);
}

/* app.js places it beside the line, or centered above it when tight. */
.runs-out-label {
  position: absolute;
  top: -2px;
  left: 8px;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.2;
  white-space: nowrap;
}

/* With no line, the label row says why: "covers all", "doesn't cover your expenses". */
.runs-out.flag {
  border-left: 0;
}

.runs-out.flag .runs-out-label {
  left: 0;
}

.bar-row {
  display: flex;
  gap: 4px;
  height: 96px;
}

.bar-group {
  display: flex;
  flex: none;
  height: 100%;
}

.bar-paid {
  height: 100%;
  background: var(--paid);
  background-repeat: no-repeat;
}

.bar-unpaid {
  height: 100%;
  background: var(--stripe);
  outline: 1px solid var(--ink);
  outline-offset: -1px;
}

/* No offer: solid is design work, stripes are the hours people forget. */
.bar-group.no-offer .bar-paid {
  background: var(--ink);
}

.bar-labels {
  position: relative;
  height: 52px;
  margin-top: 14px;
}

.bar-labels.two-rows {
  height: 104px;
}

.bar-label {
  position: absolute;
  top: 0;
  white-space: nowrap;
}

.bar-label.second-row {
  top: 52px;
}

.bar-hours b {
  font-size: 24px;
  font-weight: 300;
  letter-spacing: -0.02em;
}

.bar-hours .unit {
  margin-left: 4px;
  font-size: 11px;
}

.bar-name {
  display: block;
  font-size: 13px;
  color: var(--ink-2);
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin-top: 20px;
  font-size: 13px;
}

.legend li {
  display: flex;
  align-items: center;
  gap: 8px;
}

.legend-swatch {
  width: 22px;
  height: 10px;
}

.legend-swatch.paid {
  background: var(--paid);
}

.legend-swatch.solid {
  background: var(--ink);
}

.legend-swatch.striped {
  background: var(--stripe);
  outline: 1px solid var(--ink);
  outline-offset: -1px;
}

/* Chart 2: the rate curve. Mono labels, dashed grid, solid target. */
.rate-plot {
  margin-top: 20px;
}

.rate-plot svg {
  display: block;
  overflow: visible;
}

.rate-grid {
  stroke: var(--muted);
  stroke-width: 1;
  stroke-dasharray: 3 4;
  opacity: 0.6;
}

.rate-zero {
  stroke: var(--line);
  stroke-width: 1;
}

.rate-target {
  stroke: var(--ink);
  stroke-width: 1;
}

.rate-curve {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.5;
}

.rate-tick,
.rate-label {
  font-family: var(--mono);
  font-size: 11px;
}

/* A halo in the page color, so gridlines and the curve stop just short of the text. */
#rate-plot text {
  stroke: var(--bg);
  stroke-width: 4px;
  stroke-linejoin: round;
  paint-order: stroke;
}

.rate-tick {
  fill: var(--muted);
}

.rate-label {
  fill: var(--ink);
}

.rate-cross {
  fill: var(--ink);
}

.rate-dot {
  fill: var(--red);
}

.rate-halo {
  fill: var(--red);
  opacity: 0.25;
}

/* Show the math, ways to close the gap, then your price and your reply. */
.results-more > .receipt,
.gap-section,
.results-pair {
  margin-top: 56px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

.results-pair {
  display: grid;
  row-gap: 40px;
  align-items: start;
  padding-top: 40px;
}

.math summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 44px;
  list-style: none;
  cursor: pointer;
  font-size: 16px;
}

.math summary::-webkit-details-marker {
  display: none;
}

.math-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.math-estimate {
  font-size: 22px;
  font-weight: 300;
}

.chevron {
  transition: transform 120ms ease-out;
}

.math[open] .chevron {
  transform: rotate(90deg);
}

.math .when-open,
.math[open] .when-closed {
  display: none;
}

.math[open] .when-open {
  display: inline;
}

.math table {
  margin-top: 12px;
}

.receipt table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.receipt th,
.receipt td {
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: baseline;
}

.receipt thead th {
  padding: 0;
  border: 0;
}

.receipt tbody th {
  font-weight: 400;
  color: var(--ink-2);
}

/* The math column, in mono. Not in the final row, where the second cell is the amount. */
.receipt td:nth-child(2):not(:last-child) {
  padding-left: 16px;
  padding-right: 16px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  text-align: right;
  white-space: nowrap;
}

.receipt td:last-child {
  text-align: right;
  white-space: nowrap;
}

.receipt tr.sum > * {
  border-top: 1px solid var(--ink);
}

.receipt tr.total > * {
  padding-top: 16px;
  border-bottom: 0;
  font-size: 28px;
  font-weight: 300;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.receipt-note {
  max-width: var(--measure);
  margin-top: 16px;
  font-size: 12px;
  color: var(--muted);
}

/* Your price and your reply */

.result-block > legend {
  float: left;
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  margin-bottom: 24px;
}

.result-block .unit-input {
  max-width: 240px;
}

.result-block .unit-input input::placeholder {
  color: var(--muted);
  opacity: 1;
}

.link-button {
  min-height: 44px;
  margin-top: 4px;
  padding: 0;
  border: 0;
  background: none;
  font-size: 14px;
  text-decoration: underline;
  text-underline-offset: 3px;
}

#quote-result,
.notice p {
  max-width: var(--measure);
}

#quote-result {
  margin-top: 16px;
  font-size: 14px;
  color: var(--ink-2);
}

/* Extra rounds of changes, under the price. */
.extra-rounds {
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.extra-rounds-label {
  font-size: 13px;
  color: var(--muted);
}

.extra-rounds-value {
  margin-top: 4px;
  font-size: 24px;
  font-weight: 300;
  letter-spacing: -0.02em;
}

.extra-rounds .mono-note {
  margin-top: 4px;
}

/* 05 Ways to close the gap: up to three cards on the column grid, one per 4
   columns on desktop, stacked below. They're a radio group; the picked one
   gets the sunset with a 35% --paper wash, which fades in over 250ms. */
.gap-heading {
  display: flex;
  align-items: center;
  gap: 16px;
  font-size: 22px;
  font-weight: 300;
  letter-spacing: -0.02em;
}

/* The intro, and the note under the cards when there's no middle ground. */
.gap-intro,
.gap-note {
  max-width: var(--measure);
  margin-top: 16px;
  font-size: 14px;
  color: var(--ink-2);
}

.gap-options {
  display: grid;
  grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
  gap: var(--column-gap);
  margin-top: 24px;
}

.gap-card {
  position: relative;
  z-index: 0;
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  padding: 24px;
  border-radius: 24px;
  background: var(--paper);
  cursor: pointer;
}

.gap-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(rgba(247, 247, 245, 0.35), rgba(247, 247, 245, 0.35)), var(--sunset);
  opacity: 0;
  transition: opacity 250ms var(--ease);
}

.gap-card[aria-checked="true"]::before {
  opacity: 1;
}

.gap-card:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

.gap-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.gap-tag {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
}

.gap-chip {
  padding: 3px 10px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 11px;
  white-space: nowrap;
  color: var(--ink);
}

.gap-chip.meets {
  background: var(--ink);
  color: var(--paper);
}

.gap-name {
  margin-top: 20px;
  font-size: 20px;
  letter-spacing: -0.01em;
}

.gap-price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin-top: 4px;
}

.gap-amount {
  font-size: 48px;
  font-weight: 300;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.gap-rate {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink-2);
}

.gap-scope {
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-2);
}

.gap-levers {
  margin-top: 20px;
}

.gap-lever {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
  font-size: 14px;
}

.gap-lever:last-child {
  border-bottom: 1px solid var(--line);
}

.gap-lever dt {
  color: var(--ink-2);
}

.gap-lever dd {
  color: var(--muted);
}

.gap-lever dd.changed {
  font-weight: 500;
  color: var(--ink);
}

/* The option's work on one scale for all cards: paid, unpaid, saved. */
.gap-bar {
  display: flex;
  gap: 2px;
  height: 16px;
  margin-top: 20px;
}

.gap-bar span {
  flex-basis: 0;
  min-width: 0;
}

.gap-paid {
  background: var(--paid);
}

.gap-unpaid {
  background: var(--stripe);
  box-shadow: inset 0 0 0 1px var(--ink);
}

.gap-saved {
  border: 1px dashed var(--ink);
}

.gap-bar-labels {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 4px 12px;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
}

.gap-use {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 6px;
  min-height: 40px;
  padding: 0 16px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  font-size: 14px;
  color: var(--ink);
}

.gap-use-wrap {
  display: flex;
  flex-grow: 1;
  align-items: flex-end;
  margin-top: 24px;
}

/* The picked card: everything ink or ink-2 on the gradient, ink hairlines.
   The lever values and bar labels sit over the warm part, where ink-2
   measured under 4.5:1, so they're ink; changed values stay heavier. */
.gap-card[aria-checked="true"] .gap-tag {
  color: var(--ink-2);
}

.gap-card[aria-checked="true"] .gap-lever dd,
.gap-card[aria-checked="true"] .gap-bar-labels {
  color: var(--ink);
}

.gap-card[aria-checked="true"] .gap-lever dd.changed {
  color: var(--ink);
}

.gap-card[aria-checked="true"] .gap-lever {
  border-color: rgba(22, 22, 22, 0.25);
}

.gap-card[aria-checked="true"] .gap-paid {
  box-shadow: inset 0 0 0 1px var(--ink);
}

.gap-card[aria-checked="true"] .gap-use {
  background: var(--ink);
  color: var(--paper);
}

@media (min-width: 1024px) {
  .gap-card {
    grid-column: span 4;
  }
}

textarea {
  display: block;
  width: 100%;
  max-width: var(--measure);
  margin-top: 8px;
  padding: 16px 18px;
  border: 1px solid var(--muted);
  border-radius: 16px;
  background: var(--paper);
  font-size: 16px;
  line-height: 1.5;
  resize: vertical;
}

.result-block textarea {
  max-width: none;
}

.reply-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  margin-top: 16px;
}

.notice {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  font-size: 14px;
  color: var(--ink-2);
}

/* "Copy reply": fully rounded ink. */
.round-button {
  min-height: 48px;
  padding: 0 24px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font-size: 15px;
}

.round-button.outline {
  background: transparent;
  color: var(--ink);
}

#copy-status {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-2);
}

/* Hover: subtle, 120ms. Only on controls. */

.stepper button,
.bar-stepper button::before,
.segmented label,
.action-button,
.round-button,
.edit-button,
.check-button {
  transition: background-color 160ms var(--ease), color 160ms var(--ease);
}

/* "Check the offer": on hover the circle grows 6% and the arrow nudges 3px
   forward (240ms); pressing sinks the button to 98%. */
.check-button {
  transition: transform 160ms var(--ease), background-color 160ms var(--ease), color 160ms var(--ease);
}

.check-circle,
.check-circle svg {
  transition: transform 240ms var(--ease);
}

.check-button:active {
  transform: scale(0.98);
}

@media (hover: hover) {
  .check-button:hover .check-circle {
    transform: scale(1.06);
  }

  .check-button:hover .check-circle svg {
    transform: translateX(3px);
  }
}

@media (hover: hover) {
  .stepper button:not([data-step="1"]):hover,
  .bar-stepper button:not([data-step="1"]):hover::before,
  .segmented input:not(:checked) + label:hover,
  .action-button.outline:hover,
  .round-button.outline:hover {
    background: rgba(22, 22, 22, 0.06);
  }

  .stepper button[data-step="1"]:hover,
  .bar-stepper button[data-step="1"]:hover::before,
  .action-button:not(.outline):hover,
  .save-button:not(:disabled):hover,
  .round-button:not(.outline):hover {
    background: var(--ink-2);
  }

  .field-tabs input:not(:checked) + label:hover,
  .edit-button:hover,
  .row-action:hover {
    color: var(--ink);
  }

  .project-open:hover,
  .crumb-name:hover,
  .projects-link:hover .projects-word,
  .row-action:hover {
    text-decoration: underline;
    text-underline-offset: 4px;
  }

  .link-button:hover {
    text-decoration-thickness: 2px;
  }
}

/* Live changes morph in 250ms, only after the first render. Off for reduced motion (below). */
.charts-ready .bar-group,
.charts-ready .bar-paid,
.charts-ready .bar-unpaid,
.charts-ready .row-bar,
.charts-ready .tally-segment {
  transition: width 250ms var(--ease);
}

.charts-ready .runs-out,
.charts-ready .bracket,
.charts-ready .bar-label,
.charts-ready .tally-label {
  transition: left 250ms var(--ease), width 250ms var(--ease);
}

/* Armed: a block's starting state, set by script while it's still below the
   screen, so it never shows finished and then resets. Without scripts these
   classes never appear and everything is final. */
.stats.armed > div::before {
  transform: scaleX(0);
}

/* Hours chart: no bars yet; the stripes wipe in when it plays. */
#hours-chart.armed .bar-row {
  clip-path: inset(0 100% 0 0);
}

#hours-chart.armed .runs-out,
#hours-chart.armed .bracket,
#hours-chart.armed .bar-label,
#hours-chart.armed .group-legend li {
  opacity: 0;
}

/* Rate chart: nothing yet; the grid fades in when it plays. */
#offer-chart.armed .rate-grid,
#offer-chart.armed .rate-tick,
#offer-chart.armed .rate-zero,
#offer-chart.armed .rate-target,
#offer-chart.armed .rate-target-label,
#offer-chart.armed .rate-curve,
#offer-chart.armed .rate-cross,
#offer-chart.armed .rate-cross-label,
#offer-chart.armed .rate-now,
#offer-chart.armed .rate-now-label {
  opacity: 0;
}

/* The hours chart playing: every hour is stripes, under the paid fill. */
.hours-playing .bar-group {
  position: relative;
  isolation: isolate;
}

.hours-playing .bar-group::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--stripe);
  box-shadow: inset 0 0 0 1px var(--ink);
}

/* Rate chart dots scale from their centers. */
.rate-cross,
.rate-dot,
.rate-halo {
  transform-box: fill-box;
  transform-origin: center;
}

/* Scrubbing: a vertical line, a dot on the curve, and its label. */
.rate-plot {
  touch-action: pan-y;
}

.rate-scrub-line {
  stroke: var(--ink);
  stroke-width: 1;
}

.rate-scrub-dot {
  fill: var(--paper);
  stroke: var(--ink);
  stroke-width: 1.5;
}

/* The column grid. These blocks lay out on the page's columns and span whole
   ones. Phone (4 columns): everything spans all 4, the stats 2 each. */
.inputs-columns,
.stats,
.charts-row,
.results-pair {
  grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
  column-gap: var(--column-gap);
}

.inputs-columns > *,
.charts-row > *,
.results-pair > * {
  grid-column: 1 / -1;
}

.stats > div {
  grid-column: span 2;
}

/* Tablet (8 columns): the inputs and charts stack; stats 2 by 2; price and
   reply side by side, 4 + 4. */
@media (min-width: 760px) {
  .stats > div,
  .results-pair > * {
    grid-column: span 4;
  }
}

/* Desktop (12 columns): inputs 7 + 5, stats 3 each, charts 6 + 6, price and
   reply 6 + 6. */
@media (min-width: 1024px) {
  .inputs-columns > .inputs-column:first-child {
    grid-column: span 7;
  }

  /* The right column (tally, 03, 04, and the button) stays in view while you
     edit hours on the left. */
  .inputs-columns > .inputs-column:last-child {
    grid-column: span 5;
    position: sticky;
    top: 24px;
    align-self: start;
  }

  .stats > div {
    grid-column: span 3;
  }

  .charts-row > *,
  .results-pair > * {
    grid-column: span 6;
  }

  /* No offer, or one at or below expenses: the hours chart takes the full row. */
  .charts-row.single > * {
    grid-column: 1 / -1;
  }
}

/* ?grid: the columns as faint bands over everything, for checking alignment.
   app.js adds it only when the address has ?grid. */
.grid-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
  column-gap: var(--column-gap);
  padding: 0 var(--page-margin);
  pointer-events: none;
}

.grid-overlay > span {
  background: rgba(232, 67, 46, 0.06);
}

.grid-overlay > span:nth-child(n + 13) {
  display: none;
}

@media (max-width: 1023px) {
  .grid-overlay > span:nth-child(n + 9) {
    display: none;
  }
}

@media (max-width: 759px) {
  .grid-overlay > span:nth-child(n + 5) {
    display: none;
  }
}

/* Phone-only pieces, hidden on larger screens. */
.preview-short,
.check-hours,
.save-short,
.edit-short,
.group-legend {
  display: none;
}

/* Phone: below 760px (docs/DESIGN.md, "Phone layout"). Same tokens, fonts,
   and colors; only the layout and sizes change. */

@media (max-width: 759px) {
  html {
    /* Focused fields stay clear of the sticky header and the bottom bar. */
    scroll-padding-top: 112px;
  }

  html:has(body.on-inputs) {
    scroll-padding-bottom: calc(120px + env(safe-area-inset-bottom));
  }

  html:has(body.on-results) {
    scroll-padding-top: 112px;
  }

  /* Header: 56px, sticky on both screens. Clear at the top of screen 1 so the
     glow shows, then a background and a hairline once you scroll. */
  .topbar,
  .on-results .topbar {
    position: sticky;
    top: 0;
    z-index: 11;
    padding: 0 var(--page-margin);
    background: transparent;
    border-bottom: 1px solid transparent;
  }

  body.scrolled .topbar,
  .on-results .topbar,
  .on-projects .topbar {
    background: var(--bg);
    border-bottom-color: var(--line);
  }

  /* First row: 6px + 44px buttons + 6px = 56px. The project name line wraps under it. */
  .topbar-inner {
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 0 8px;
    height: auto;
    min-height: 56px;
    padding: 6px 0;
  }

  /* The wordmark and the project line stay separate rows, as before. */
  .brand {
    display: contents;
  }

  .crumb-slash {
    display: none;
  }

  .wordmark {
    margin-right: auto;
  }

  /* The project name and "Saved": one mono line under the header. */
  .crumb {
    order: 3;
    flex-basis: 100%;
    gap: 8px;
    margin-top: -6px;
    font-family: var(--mono);
    font-size: 12px;
  }

  .save-status {
    margin-left: 4px;
  }

  .crumb-name,
  .crumb-input {
    min-height: 44px;
    max-width: calc(100% - 64px);
    font-family: var(--mono);
    font-size: 12px;
  }

  .projects-link {
    margin-left: 0;
    min-height: 44px;
    padding: 0 14px;
    border-radius: 999px;
    background: var(--paper);
  }

  .projects-count {
    min-width: 0;
    padding: 0;
    background: none;
  }

  .save-button {
    min-height: 44px;
    padding: 0 18px;
  }

  /* Share: a 44px icon button on paper. Its name stays "Share" for screen readers. */
  .share-button {
    justify-content: center;
    width: 44px;
    min-height: 44px;
    border-radius: 50%;
    background: var(--paper);
  }

  .share-icon,
  .share-check {
    width: 16px;
    height: 16px;
  }

  .share-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .results-body.shared-row {
    padding-top: 8px;
  }

  .save-long,
  .edit-long,
  .preview-long {
    display: none;
  }

  .save-short,
  .edit-short,
  .preview-short {
    display: inline;
  }

  /* Screen 2: "Edit" sits where the wordmark is. */
  .on-results .topbar .wordmark {
    visibility: hidden;
  }

  /* The hidden wordmark still holds its space; without the mark it holds
     only the word's, so the buttons on the right fit as before. */
  .on-results .topbar .wordmark-mark {
    display: none;
  }

  #edit-details {
    position: fixed;
    top: 6px;
    left: 20px;
    z-index: 12;
    min-height: 44px;
  }

  .results-header {
    position: static;
    min-height: 0;
    padding: 0;
    background: none;
  }

  /* The smaller glow sits behind the header buttons only, never the headline.
     Clipped to its own corner box, so it can't make the page scroll sideways. */
  .glow {
    top: 0;
    right: 0;
    width: 240px;
    height: 150px;
    overflow: hidden;
  }

  .glow-sun {
    inset: auto;
    top: -170px;
    right: -130px;
    width: 300px;
    height: 300px;
    filter: blur(28px);
  }

  .glow-ring {
    display: none;
  }

  /* Screen 1 */

  .screen-projects,
  .screen-inputs {
    padding-top: 12px;
  }

  h1 {
    font-size: clamp(40px, 12vw, 84px);
  }

  .lede {
    margin-top: 16px;
    font-size: 16px;
  }

  .inputs-columns {
    padding-top: 40px;
  }

  .inputs-column + .inputs-column,
  .inputs-column .section + .section {
    margin-top: 44px;
  }

  .section > legend {
    gap: 12px;
    font-size: 22px;
  }

  .field-tabs {
    gap: 16px;
  }

  .field-tabs label {
    font-size: 15px;
  }

  /* Job pills: one row that scrolls sideways and runs off the right edge, so
     the cut-off pill shows there's more. The page itself never scrolls sideways. */
  .segmented {
    position: relative;
  }

  .segmented label {
    min-height: 44px;
  }

  .job-choice {
    display: flex;
    width: calc(100% + 20px);
    margin-right: -20px;
    overflow-x: auto;
    border-radius: 999px 0 0 999px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .job-choice::-webkit-scrollbar,
  .field-tabs::-webkit-scrollbar {
    display: none;
  }

  /* Four field tabs don't fit, so the row scrolls sideways like the job pills.
     The hairline is a shadow, so the scrolling row doesn't clip the underline. */
  .field-tabs {
    width: calc(100% + 20px);
    margin-right: -20px;
    padding-right: 20px;
    overflow-x: auto;
    border-bottom: 0;
    box-shadow: inset 0 -1px var(--line);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .field-tabs label {
    flex: none;
    margin-bottom: 0;
  }

  .job-choice label {
    flex: none;
  }

  .steppers {
    flex-wrap: nowrap;
    gap: 24px;
    margin-top: 28px;
  }

  .stepper {
    gap: 4px;
  }

  .stepper input {
    font-size: 28px;
  }

  /* Tap areas of at least 44 by 44: padding grows the input's hit box and an
     equal negative margin gives the space back, so nothing looks different. */
  .stepper input {
    min-width: calc(2.2ch + 4px);
    padding-block: 6px;
    margin: -6px -2px;
  }

  .work-row .unit-input input {
    padding-top: 4px;
    margin-top: -4px;
  }

  .field-row .unit-input input {
    padding-inline: 8px;
    margin-inline: -8px;
  }

  /* Chromium draws these 42.8px tall (WebKit 47px), so 2px more on top. */
  .field-row .unit-input input,
  .result-block .unit-input input {
    padding-top: 2px;
    margin-top: -2px;
  }

  /* "Edit" is narrower than 44px; an invisible tap area centered on it makes
     up the difference without moving anything. */
  .row-action {
    position: relative;
  }

  .row-action::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 50%;
    width: max(100%, 44px);
    transform: translateX(-50%);
  }

  .bar-input input {
    padding: 6px 16px 8px;
    margin: -6px -16px;
  }

  /* The bar steppers have no spare room between their buttons, so the input
     itself is 44 by 44; its digits stay the same size. */
  .bar-stepper input {
    box-sizing: border-box;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
  }

  /* Work rows: the label on top, then the bar and the hours input on one line. */
  .work-row {
    grid-template-columns: minmax(0, 1fr) 90px;
    row-gap: 8px;
  }

  .row-label {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0 8px;
    grid-column: 1 / -1;
  }

  .forgotten-note {
    margin-left: 0;
  }

  .row-bar {
    justify-self: start;
    max-width: 100%;
  }

  .unit-input,
  .bar-input {
    min-height: 44px;
  }

  .field-row {
    gap: 20px;
  }

  .field-row .unit-input input,
  .result-block .unit-input input,
  .currency {
    font-size: 32px;
  }

  /* Amount offered: half width, under Yes / Not yet. */
  .offer-row {
    grid-template-columns: minmax(0, 1fr);
  }

  #offer-field {
    max-width: calc(50% - 10px);
  }

  /* The bottom bar replaces the tally panel and the button: always under your
     thumb, clear of the iPhone's home bar. */
  .tally {
    display: none;
  }

  .tally + .section {
    margin-top: 0;
  }

  /* The bar sits inside screen 1, so screen 1 stacks above the footer;
     otherwise the footer text shows on top of the bar. */
  .screen-inputs {
    z-index: 2;
  }

  .check-button {
    position: fixed;
    left: var(--edge);
    right: var(--edge);
    bottom: calc(14px + env(safe-area-inset-bottom));
    z-index: 9;
    width: auto;
    height: 76px;
    margin: 0;
    padding: 0 12px 0 20px;
    border-radius: 28px;
  }

  /* Title and the mono line share a row; on the narrowest phones the mono
     line wraps under the title instead of colliding with it. */
  .check-main {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 12px;
    min-width: 0;
  }

  .check-title {
    font-size: 17px;
    white-space: nowrap;
  }

  .check-preview {
    margin-left: auto;
    font-size: 11px;
    white-space: nowrap;
  }

  /* A thin live bar of the hours: solid, then stripes, light on ink. */
  .check-hours {
    display: flex;
    flex-basis: 100%;
    gap: 2px;
    height: 6px;
    margin-top: 8px;
  }

  .check-hours[hidden] {
    display: none;
  }

  .check-segment {
    flex-basis: 0;
    background: var(--paper);
  }

  .check-segment.forgotten {
    background: repeating-linear-gradient(90deg, var(--paper) 0 1px, transparent 1px 3px);
    outline: 1px solid var(--paper);
    outline-offset: -1px;
  }

  .check-circle {
    width: 52px;
    height: 52px;
    margin-left: 12px;
  }

  /* Room at the bottom so the bar never covers the last field or the footer. */
  body.on-inputs {
    padding-bottom: calc(104px + env(safe-area-inset-bottom));
  }

  /* Screen 2 */

  .hero-panel {
    min-height: 0;
    padding: 20px;
  }

  /* "This offer pays" and the job summary on top, the number, then the sentence. */
  .hero-content {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 12px;
    min-height: 0;
  }

  .hero-top,
  .hero-aside {
    display: contents;
  }

  .hero-label {
    grid-row: 1;
    grid-column: 1;
    font-size: 14px;
  }

  .hero-job {
    grid-row: 1;
    grid-column: 2;
    align-self: center;
    font-size: 11px;
  }

  .hero-number {
    grid-row: 2;
    grid-column: 1 / -1;
    margin-top: 20px;
    white-space: nowrap;
  }

  .hero-digits {
    font-size: clamp(80px, 27vw, 220px);
  }

  .hero-unit {
    font-size: 16px;
  }

  .hero-sentence,
  .warning {
    grid-row: 3;
    grid-column: 1 / -1;
    margin-top: 16px;
    font-size: 16px;
    text-align: left;
    justify-content: flex-start;
  }

  /* The live controls: a panel right under the hero, not sticky. */
  .control-bar {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 4px 12px;
    margin: 12px var(--edge) 0;
    padding: 8px 16px 12px 20px;
    border-radius: 20px;
    background: var(--paper);
  }

  .bar-stepper {
    grid-column: 1 / -1;
    flex-wrap: wrap;
  }

  .bar-stepper label {
    flex: 1;
    min-width: 0;
  }

  .bar-stepper button {
    margin: 0;
  }

  .bar-stepper button::before {
    inset: 2px;
  }

  .bar-field:last-child {
    justify-self: end;
  }

  .results-body {
    padding-bottom: 56px;
  }

  .stats {
    row-gap: 20px;
    margin-top: 12px;
  }

  .stats > div {
    padding-top: 20px;
  }

  .stats dt {
    font-size: 13px;
  }

  .stats dd {
    font-size: 32px;
  }

  /* "of 11.5 hrs" on its own line under the number. */
  .stat-unit-line {
    display: block;
    margin: 4px 0 0;
  }

  .charts-row {
    row-gap: 48px;
    margin-top: 44px;
  }

  .chart h2,
  .result-block > legend {
    font-size: 20px;
  }

  /* Hours chart: 64px bars; group names move into a legend under the bar. */
  .bars {
    margin-top: 16px;
    padding-top: 28px;
  }

  .bracket,
  .bar-labels {
    display: none;
  }

  .bar-row {
    height: 64px;
  }

  .runs-out {
    top: 0;
    height: calc(28px + 64px);
  }

  .group-legend {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 16px;
    margin-top: 16px;
    font-size: 13px;
  }

  .group-legend li {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
  }

  .group-legend .legend-swatch {
    flex: none;
    width: 14px;
  }

  .group-hours {
    font-family: var(--mono);
    font-size: 12px;
    color: var(--ink-2);
  }

  .rate-plot {
    margin-top: 16px;
  }

  .results-more > .receipt,
  .gap-section,
  .results-pair {
    margin-top: 44px;
  }

  .gap-heading {
    font-size: 20px;
  }

  #copy-reply {
    width: 100%;
  }

  /* Show the math: the math sits on its own line under each item, so it
     never wraps and the table fits. */
  .receipt table,
  .receipt tbody {
    display: block;
  }

  .receipt thead {
    display: none;
  }

  .receipt tbody tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid var(--line);
  }

  .receipt tbody tr.sum {
    border-top: 1px solid var(--ink);
  }

  .receipt th,
  .receipt td,
  .receipt tr.sum > * {
    padding: 0;
    border: 0;
  }

  .receipt tbody th {
    grid-row: 1;
    grid-column: 1;
  }

  .receipt td:last-child {
    grid-row: 1;
    grid-column: 2;
  }

  .receipt td:nth-child(2):not(:last-child) {
    grid-row: 2;
    grid-column: 1 / -1;
    padding: 2px 0 0;
    text-align: left;
  }

  .receipt td:nth-child(2):not(:last-child):empty {
    display: none;
  }

  .receipt tr.total {
    border-bottom: 0;
    padding-top: 16px;
  }

  /* Projects: one column, a full-width row per project. */
  .home-top {
    align-items: center;
  }

  .back-to-calc {
    min-height: 44px;
  }

  .project-table,
  .project-table tbody {
    display: block;
  }

  .project-table {
    margin-top: 32px;
  }

  .project-table thead {
    display: none;
  }

  .project-table tr {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: baseline;
    gap: 2px 12px;
    min-height: 56px;
    padding: 10px 0;
    border-bottom: 1px solid var(--line);
  }

  .project-table tbody th,
  .project-table td {
    padding: 0;
    border: 0;
  }

  .project-name {
    grid-column: 1 / -1;
    width: auto;
  }

  .project-open,
  .row-rename {
    min-height: 44px;
    font-size: 22px;
  }

  .project-estimate,
  .project-offer {
    display: none;
  }

  .project-table td.project-actions {
    grid-column: 1 / -1;
    text-align: left;
    white-space: normal;
  }

  .row-action:first-child {
    padding-left: 0;
  }
}

/* Phones: the dialogs are bottom sheets, full width, clear of the home bar. */
@media (max-width: 759px) {
  .panel-dialog {
    width: 100%;
    max-width: 100%;
    max-height: 100%;
    margin: auto 0 0;
    padding: 24px 20px calc(20px + env(safe-area-inset-bottom));
    border-radius: 28px 28px 0 0;
  }

  .panel-dialog[open],
  .save-form {
    gap: 24px;
  }

  .panel-actions .action-button {
    flex: 1;
    min-height: 44px;
  }
}

/* Small phones: the Projects title on top, then "New calculation" at full
   width, so both edges sit on the grid lines. */
@media (max-width: 419px) {
  .home-top {
    flex-direction: column;
    align-items: stretch;
  }

  .home-top .round-button {
    width: 100%;
  }
}

/* The narrowest phones: Edit, Projects, Share, and Save still fit on one line
   on screen 2, with a little less padding. Tap targets stay 44px tall. */
@media (max-width: 359px) {
  .on-results .topbar-inner {
    column-gap: 4px;
  }

  .on-results .projects-link {
    padding: 0 10px;
  }

  .on-results .save-button {
    padding: 0 14px;
  }

  .on-results .edit-button {
    padding: 0 12px;
  }

  /* The hours chart legend in one column, so "Communication 1h" fits
     inside the grid lines. */
  .group-legend {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Save image preview: a centered panel on desktop, a bottom sheet on phones.
   It only fades in. */
.image-dialog {
  max-width: min(1040px, calc(100vw - 48px));
  max-height: calc(100vh - 48px);
  padding: 32px;
  border: 0;
  border-radius: 28px;
  background: var(--bg);
  color: var(--ink);
}

.image-dialog[open] {
  display: grid;
  grid-template-columns: auto minmax(260px, 320px);
  gap: 40px;
  animation: dialog-fade 160ms ease-out;
}

.image-dialog::backdrop {
  background: rgba(22, 22, 22, 0.45);
  animation: dialog-fade 160ms ease-out;
}

@keyframes dialog-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

.image-preview {
  display: block;
  width: auto;
  height: min(640px, calc(100vh - 112px));
  aspect-ratio: 4 / 5;
  border: 1px solid var(--line);
}

.image-dialog-side {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.image-dialog-title {
  font-size: 32px;
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.image-dialog-text {
  margin-top: 12px;
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink-2);
}

.image-dialog-size {
  margin-top: 12px;
}

.image-dialog-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 28px;
}

@media (max-width: 759px) {
  .image-dialog {
    width: 100%;
    max-width: 100%;
    max-height: 100%;
    margin: auto 0 0;
    padding: 20px 20px calc(20px + env(safe-area-inset-bottom));
    border-radius: 28px 28px 0 0;
  }

  .image-dialog[open] {
    grid-template-columns: minmax(0, 1fr);
    gap: 20px;
  }

  .image-preview {
    justify-self: center;
    height: auto;
    max-width: 100%;
    max-height: 54vh;
  }

  .image-dialog-title {
    font-size: 24px;
  }

  .image-dialog-text {
    margin-top: 8px;
  }

  .image-dialog-size {
    display: none;
  }

  .image-dialog-actions {
    flex-wrap: nowrap;
    margin-top: 20px;
  }

  .image-dialog-actions .round-button {
    flex: 1;
    padding: 0 12px;
  }
}

/* The reveal: plays once when "Check the offer" is pressed. app.js runs the
   fades as Web Animations, each step after the last one finishes. Never under
   reduced motion. */

/* The button's circle grows into the hero panel (app.js moves the orb). */
.reveal-orb {
  position: fixed;
  z-index: 30;
  overflow: hidden;
  background: var(--sunset);
  pointer-events: none;
}

/* Between screen 1 fading out and screen 2 fading in, nothing shows but the orb. */
body.reveal-hidden .screen-results,
body.reveal-hidden .site-footer,
body.reveal-hidden .topbar,
body.reveal-hidden .glow {
  opacity: 0;
}

/* Then the blocks in view play one after another (app.js, "Plays once"). */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after,
  ::backdrop {
    transition: none !important;
    animation: none !important;
  }
}
