/* ============================================================
   SILICA WORKS - contact, the brief
   ------------------------------------------------------------
   One sentence, then one form.

   THE PAGE OPENS ON THE BRIEF. No header: the title, a short line
   on how it works, the address to copy, and a hand pointing down
   into the first step - the same opening the work page has.

   THE FORM IS A BRIEF, NOT A MESSAGE BOX. Five numbered steps on
   the footer's dashed rules, each with its label in a column of
   its own, and the answers set large - the inputs are in the
   display face at display size, because what the reader types is
   the most important type on the page.

   THE TICKET WRITES ITSELF. Beside the form, pinned while it
   scrolls, an ink ticket fills in as the reader answers: who it is
   from, what they need, the budget, the timeline, how complete it
   is. When the brief is sent it is stamped. It is the form's
   summary, its progress bar and its confirmation in one object,
   and it is the nav bar's surface, so it reads as part of the
   site's furniture.

   EVERY CONTROL IS A NATIVE ONE. The chips and the budget bar are
   real checkboxes and radios, visually covered but still focused,
   announced and submitted by the browser; the styling is the only
   thing that is custom. With the script absent the form still
   validates (natively) and still sends (to the mail client).
   ============================================================ */

/* ------------------------------------------------------------
   The sheet
   ------------------------------------------------------------ */
.ct-sheet {
  z-index: 2;
  display: block;
  min-height: 0;
  color: var(--sw-ink);
  /* The home page's sheet rhythm (the spacing tokens in
     css/styles.css): its sheet top over the title, and a foot that
     clears the nav once it parks at the end of the page, as
     home.html's last section does. */
  padding: var(--sw-sheet-top) 2.5rem calc(var(--sw-park-off) + var(--sw-bar-h, 60px) + var(--sw-park-air));
  scroll-margin-top: 0;
}

.ct-sheet-head {
  display: block;
}

/* The opening's start state - only while html.ct-anim is set, and
   hidden rather than moved: GSAP would read a CSS offset back as
   pixels and keep it under its own y. */
.ct-anim .ct-sheet-head .sw-featured-title,
.ct-anim .ct-lede {
  visibility: hidden;
}

/* ------------------------------------------------------------
   The way in
   ------------------------------------------------------------
   The lede on the left at the size home's "Who we are" sets its
   lead paragraph, the address under it, and the hand on the right
   above the first step - the work page's opening, word for word in
   its measurements. */
.ct-intro {
  margin-top: var(--sw-title-gap);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 1.5rem;
  align-items: start;
}

/* The paragraph takes the right half; the hand sits in the middle
   of the left half, beside it. */
.ct-lede {
  grid-column: 7 / span 6;
  grid-row: 1;
}

.ct-blurb {
  max-width: 40ch;
  margin: 0;
  font-family: "sohne-normal", "Inter Tight", sans-serif;
  font-size: 1.25rem;
  line-height: 1.55;
  color: var(--pg-body);
  text-wrap: pretty;
}

/* The highlight is the line's one mark - never broken across two. */
.ct-blurb mark {
  white-space: nowrap;
}

.ct-blurb b {
  font-family: "sohne-medium", "Inter Tight", sans-serif;
  font-weight: 500;
  color: var(--sw-ink);
}

.ct-alt {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  margin: 1.5rem 0 0;
}

.ct-k {
  font: 500 0.66rem/1 "Inter Tight", sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pg-soft);
}

/* The address copies itself. A button, not a link: the mailto is in
   the footer and the form is below, so what this adds is the one
   thing neither does - the address on the reader's clipboard. */
.ct-copy {
  all: unset;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  max-width: 100%;
  font-family: "sohne-medium", "Inter Tight", sans-serif;
  font-size: clamp(0.95rem, 0.3vw + 0.75rem, 1.1rem);
  letter-spacing: -0.01em;
  color: var(--sw-ink);
}

.ct-copy:focus-visible {
  outline: 1.5px solid var(--sw-ink);
  outline-offset: 4px;
}

/* "Copy", then "Copied" - the cursor label's chip, cut on two
   corners, turning to the accent when it is used. */
.ct-copy-tag {
  --n: 5px;
  padding: 0.35rem 0.5rem;
  font: 700 0.58rem/1 "Inter Tight", sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: rgba(20, 20, 15, 0.07);
  color: var(--sw-ink);
  clip-path: polygon(var(--n) 0, 100% 0, 100% calc(100% - var(--n)),
    calc(100% - var(--n)) 100%, 0 100%, 0 var(--n));
  transition: background-color 0.2s ease;
}

.ct-copy:hover .ct-copy-tag,
.ct-copy:focus-visible .ct-copy-tag,
.ct-copy.is-copied .ct-copy-tag {
  background: var(--sw-accent);
}

/* The hand, above the first step: its arrow dips once and drops
   onto the form. */
.ct-note {
  grid-row: 1;
  justify-self: center;
  align-self: center;
  grid-column: 1 / span 6;
  width: 12rem;
  margin-top: 0.5rem;
  transform: rotate(-3deg);
}

.ct-arrow {
  --aw: clamp(5rem, 6.2vw, 7rem);
  left: 4%;
  top: 100%;
  width: var(--aw);
  margin-top: 0.35rem;
}

/* Below the hand's arrow, not under it: room for its full drop
   (its box is 1.1 times its width) and a little air. */
.ct-grid {
  margin-top: calc(clamp(5rem, 6.2vw, 7rem) * 1.1 + 2rem);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 1.5rem;
  align-items: start;
}

.ct-form,
.ct-done {
  grid-column: 1 / span 7;
  grid-row: 1;
  min-width: 0;
}

.ct-side {
  grid-column: 9 / -1;
  grid-row: 1;
  position: sticky;
  top: clamp(1.5rem, 6vh, 4rem);
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  min-width: 0;
}

/* ------------------------------------------------------------
   A step
   ------------------------------------------------------------ */
.ct-step {
  min-width: 0;
  border: 0;
  border-top: 2px dashed var(--sw-ink);
  padding: clamp(2rem, 5vh, 3rem) 0 clamp(2.25rem, 5vh, 3.25rem);
}

/* The number and the name are one heading, set on one line over the
   step's fields - the same on a phone as on a desktop. */
.ct-step-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.75rem;
}

.ct-step-label {
  display: flex;
  align-items: center;
  gap: 1rem;
}

/* The number: a bevelled chip that fills with the accent once the
   step has what it needs - the thread index's tick, at step size. */
.ct-num {
  --n: 7px;
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  font-family: "sohne-bold", "Inter Tight", sans-serif;
  font-weight: 800;
  font-size: 0.95rem;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--sw-paper);
  background: var(--sw-ink);
  clip-path: polygon(var(--n) 0, 100% 0, 100% calc(100% - var(--n)),
    calc(100% - var(--n)) 100%, 0 100%, 0 var(--n));
  transition: background-color 0.35s ease, color 0.35s ease;
}

.ct-step.is-done .ct-num {
  background: var(--sw-accent);
  color: var(--sw-ink);
}

/* The step name, on home's type scale: a showcase title
   (.sw-sc-title). No hint under it - the name and the controls say
   enough, and the hand is kept for the one note over the form. */
.ct-name {
  font-family: "sohne-bold", "Inter Tight", sans-serif;
  font-weight: 800;
  font-size: clamp(1.15rem, 1.6vw, 1.5rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: #14140f;
}

.ct-optional {
  font: 500 0.64rem/1 "Inter Tight", sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pg-soft);
}

.ct-body {
  display: grid;
  gap: 1.75rem;
  min-width: 0;
}

.ct-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.75rem clamp(1.25rem, 2.5vw, 2.25rem);
}

/* ------------------------------------------------------------
   Text fields
   ------------------------------------------------------------ */
.ct-field {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.ct-label {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font: 500 0.7rem/1.2 "Inter Tight", sans-serif;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--pg-soft);
  transition: color 0.25s ease;
}

.ct-field:focus-within .ct-label {
  color: var(--sw-ink);
}

.ct-req {
  color: var(--sw-ink);
}

.ct-input {
  position: relative;
}

.ct-input input,
.ct-input textarea {
  display: block;
  width: 100%;
  padding: 0.6rem 0 0.65rem;
  border: 0;
  border-bottom: 1.5px solid rgba(20, 20, 15, 0.22);
  border-radius: 0;
  outline: 0;
  background: transparent;
  font-family: "sohne-medium", "Inter Tight", sans-serif;
  /* Set to sit with the step names beside them and the chips below,
     not over them - large enough to read as the answer, small enough
     that the column stays one weight across. */
  font-size: 1.0625rem;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--sw-ink);
  caret-color: var(--sw-ink);
  transition: border-color 0.25s ease;
}

.ct-input textarea {
  min-height: 7.5rem;
  resize: none;
  overflow: hidden;
  font-family: "sohne-normal", "Inter Tight", sans-serif;
  font-size: 1.0625rem;
  line-height: 1.55;
  letter-spacing: 0;
}

.ct-input input::placeholder,
.ct-input textarea::placeholder {
  color: #a3a39b;
  opacity: 1;
}

/* A browser's autofill paints its own pale fill under the text. The
   inset shadow is the only paint that sits over it. */
.ct-input input:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 100px var(--sw-paper) inset;
  -webkit-text-fill-color: var(--sw-ink);
}

/* The focus line, drawn in ink from the left - the rule under the
   hero's captions, doing the focus ring's job. A clipped box could
   not carry an outline, and an underline field wants none. */
.ct-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--sw-ink);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.6s var(--pg-ease), background-color 0.25s ease;
  pointer-events: none;
}

.ct-input :focus + .ct-bar {
  transform: scaleX(1);
}

.ct-count {
  position: absolute;
  right: 0;
  bottom: 0.8rem;
  font: 500 0.64rem/1 "Inter Tight", sans-serif;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  color: var(--pg-soft);
  pointer-events: none;
}

/* The error line. Space is held for it whether it is showing or not,
   so a message appearing never shoves the rest of the form down. */
.ct-err {
  min-height: 1.2rem;
  margin-top: 0.5rem;
  font: 500 0.8rem/1.4 "Inter Tight", sans-serif;
  color: var(--pg-error);
}

.ct-field.is-invalid .ct-input input,
.ct-field.is-invalid .ct-input textarea {
  border-bottom-color: var(--pg-error);
}

.ct-field.is-invalid .ct-bar {
  background: var(--pg-error);
  transform: scaleX(1);
}

/* ------------------------------------------------------------
   Chips - the needs and the timeline
   ------------------------------------------------------------
   The input sits over its chip at zero opacity rather than being
   hidden: it keeps the click target, the focus and the announcement
   to itself, and the chip only draws its state. The edge and the
   face are two clipped layers - see .fq-win in css/faq-page.css for
   why a bevelled box cannot carry a border.
   ------------------------------------------------------------ */
.ct-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  border: 0;
}

.ct-chip {
  position: relative;
  display: inline-flex;
}

.ct-chip input {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.ct-chip-face {
  --n: 10px;
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.85rem 1.2rem 0.85rem 0.95rem;
  font-family: "sohne-medium", "Inter Tight", sans-serif;
  font-size: 1.0625rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--sw-ink);
  user-select: none;
}

/* The face's cut is pulled in by --pg-bevel-k, so the edge is one
   thickness on the cuts and the sides alike (css/pages.css). The
   width is a property so focus can thicken it and the cut follows. */
.ct-chip-face::before,
.ct-chip-face::after {
  content: "";
  position: absolute;
  z-index: -1;
  clip-path: polygon(var(--c) 0, 100% 0, 100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%, 0 100%, 0 var(--c));
  transition: background-color 0.25s ease;
}

.ct-chip-face::before { --c: var(--n); inset: 0; background: rgba(20, 20, 15, 0.26); }
.ct-chip-face::after {
  --bw: 1.5px;
  --c: calc(var(--n) - var(--bw) * var(--pg-bevel-k));
  inset: var(--bw);
  background: #fff;
}

/* The box: bevelled, the chip's own shape, for every choice on the
   form - checkbox or radio, one look. Drawn as an edge and a face,
   like the chip around it, so the bevel keeps one line weight on
   the cut. */
.ct-box {
  --n: 5px;
  --bw: 1.5px;
  position: relative;
  flex: none;
  width: 1rem;
  height: 1rem;
  background: rgba(20, 20, 15, 0.38);
  clip-path: polygon(var(--n) 0, 100% 0, 100% calc(100% - var(--n)),
    calc(100% - var(--n)) 100%, 0 100%, 0 var(--n));
  transition: background-color 0.25s ease;
}

.ct-box::before {
  content: "";
  position: absolute;
  inset: var(--bw);
  background: #fff;
  --c: calc(var(--n) - var(--bw) * var(--pg-bevel-k));
  clip-path: polygon(var(--c) 0, 100% 0, 100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%, 0 100%, 0 var(--c));
  transition: background-color 0.25s ease;
}

/* The mark: a small bevelled block, the box's own shape set inside
   it, pressed in from the centre. No tick. */
.ct-box::after {
  --d: 3px;
  content: "";
  position: absolute;
  inset: 4px;
  background: var(--sw-accent);
  clip-path: polygon(var(--d) 0, 100% 0, 100% calc(100% - var(--d)),
    calc(100% - var(--d)) 100%, 0 100%, 0 var(--d));
  transform: scale(0);
  transition: transform 0.35s var(--pg-ease);
}

.ct-chip:hover .ct-box { background: var(--sw-ink); }

.ct-chip:hover .ct-chip-face::before { background: var(--sw-ink); }

.ct-chip input:checked + .ct-chip-face::before { background: var(--sw-ink); }
.ct-chip input:checked + .ct-chip-face::after { background: var(--sw-accent); }
.ct-chip input:checked + .ct-chip-face .ct-box,
.ct-chip input:checked + .ct-chip-face .ct-box::before { background: var(--sw-ink); }
.ct-chip input:checked + .ct-chip-face .ct-box::after { transform: scale(1); }

/* Focus: the edge goes to full ink and thickens - the ring a clipped
   box cannot draw with an outline. */
.ct-chip input:focus-visible + .ct-chip-face::before { background: var(--sw-ink); }
.ct-chip input:focus-visible + .ct-chip-face::after { --bw: 3px; }

.ct-group.is-invalid .ct-chip-face::before { background: var(--pg-error); }

/* ------------------------------------------------------------
   The budget bar
   ------------------------------------------------------------
   Five ranges on one bar, with an ink block that slides to the one
   chosen. Without the script (no .is-live) the chosen segment is
   simply filled; with it the block travels between them and the
   fill is left to the block.
   ------------------------------------------------------------ */
.ct-seg {
  --n: 12px;
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  padding: 5px;
}

.ct-seg::before,
.ct-seg::after {
  content: "";
  position: absolute;
  z-index: -2;
  clip-path: polygon(var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c),
    100% calc(100% - var(--c)), calc(100% - var(--c)) 100%,
    var(--c) 100%, 0 calc(100% - var(--c)), 0 var(--c));
  transition: background-color 0.25s ease;
}

.ct-seg::before { --c: var(--n); inset: 0; background: rgba(20, 20, 15, 0.26); }
.ct-seg::after { --c: calc(var(--n) - 1.5px * var(--pg-bevel-k)); inset: 1.5px; background: #fff; }

.ct-seg:focus-within::before { background: var(--sw-ink); }
.ct-group.is-invalid .ct-seg::before { background: var(--pg-error); }

.ct-seg-opt {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 3.5rem;
  padding: 0.5rem 0.2rem;
  text-align: center;
  font-family: "sohne-medium", "Inter Tight", sans-serif;
  /* Five ranges share the form's column, so on a narrower desktop
     they step down rather than wrap. */
  font-size: min(1.0625rem, 1.15vw);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--sw-ink);
  transition: color 0.3s ease;
}

/* Hairlines between the ranges, not around them. */
.ct-seg-opt + .ct-seg-opt::before {
  content: "";
  position: absolute;
  left: 0;
  top: 25%;
  bottom: 25%;
  width: 1px;
  background: rgba(20, 20, 15, 0.12);
}

.ct-seg-opt input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.ct-seg-opt span {
  position: relative;
  white-space: nowrap;
  pointer-events: none;
}

.ct-seg-opt:has(input:focus-visible) span {
  text-decoration: underline;
  text-underline-offset: 0.3em;
  text-decoration-thickness: 1.5px;
}

/* No script: the chosen range fills itself. */
.ct-seg:not(.is-live) .ct-seg-opt:has(input:checked) {
  background: var(--sw-ink);
  color: var(--sw-accent);
  clip-path: polygon(8px 0, calc(100% - 8px) 0, 100% 8px,
    100% calc(100% - 8px), calc(100% - 8px) 100%,
    8px 100%, 0 calc(100% - 8px), 0 8px);
}

.ct-seg.is-live .ct-seg-opt.is-on {
  color: var(--sw-accent);
}

.ct-seg-ind {
  --n: 8px;
  position: absolute;
  z-index: -1;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  background: var(--sw-ink);
  /* Cut on all four corners, the bar's own shape, so the block reads
     as the bar's piece. */
  clip-path: polygon(var(--n) 0, calc(100% - var(--n)) 0, 100% var(--n),
    100% calc(100% - var(--n)), calc(100% - var(--n)) 100%,
    var(--n) 100%, 0 calc(100% - var(--n)), 0 var(--n));
  opacity: 0;
  pointer-events: none;
}

/* Hover: a faint block in the same shape shows where the choice
   would land. Hidden on the range already chosen. */
.ct-seg-opt::after {
  --n: 8px;
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(20, 20, 15, 0.08);
  clip-path: polygon(var(--n) 0, calc(100% - var(--n)) 0, 100% var(--n),
    100% calc(100% - var(--n)), calc(100% - var(--n)) 100%,
    var(--n) 100%, 0 calc(100% - var(--n)), 0 var(--n));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

@media (hover: hover) {
  .ct-seg-opt:hover::after { opacity: 1; }
}

.ct-seg-opt.is-on::after,
.ct-seg-opt:has(input:checked)::after { opacity: 0; }

.ct-seg-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  margin-top: 0.9rem;
}

/* ------------------------------------------------------------
   The honeypot
   ------------------------------------------------------------
   A field no person sees or reaches and most bots fill in. Moved
   off screen rather than display:none, which the better bots know
   to skip. aria-hidden and tabindex -1 in the markup keep it off
   the keyboard and out of the accessibility tree.
   ------------------------------------------------------------ */
.ct-hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.ct-status {
  margin: 0;
  font: 500 0.85rem/1.5 "Inter Tight", sans-serif;
  color: var(--pg-error);
}

.ct-status:empty {
  display: none;
}

.ct-status a {
  color: inherit;
}

/* ------------------------------------------------------------
   The ticket
   ------------------------------------------------------------
   Two pieces on one perforation, as a real ticket is printed: the
   body, on the nav bar's surface (#141414 face, #3a3a36 edge, the
   plates' 16px bevel on its top corners), and the stub under it in
   the accent, which is the send. Half-circle bites are cut out of
   both where they meet, and a row of slits is punched through the
   fold - half of each slit in the body, half in the stub, so the cut
   reads through both - showing the page, as the form's dashed rules
   do.
   When the brief goes the stub is torn off, and the body is left
   ending on its two bites, as a used ticket does.

   Flat faces, no texture, and the whole ticket sits a little off the
   sheet on a soft shadow.

   KEPT CHEAP, BECAUSE IT IS PINNED AND LIVE. The ticket rides beside
   the form and rewrites itself on every keystroke, so nothing on it
   may cost a repaint of anything else: the shadow is a blurred block
   on a layer of its own behind the ticket (not a drop-shadow filter,
   which would re-run over the whole ticket each time a value
   changed). Everything that moves - the peel, the tear, the stamp -
   moves by transform and opacity.

   THE STUB SHEARS, IT DOES NOT TURN. Its barcode is drawn one module
   to a pixel, and a 1px bar turned by even a degree breaks into
   stair-steps. A skewY droops the stub off its hinge just the same
   to the eye, but every bar stays upright on its own pixel column.
   Only the fall, fast and fading, turns.
   ------------------------------------------------------------ */
.ct-ticket {
  --n: 16px;
  --bite: 0.75rem;
  --dash: 6px;
  --dash-h: 2px;
  --gap: 12px;
  --tk-cut: 0px;
  position: relative;
  isolation: isolate;
  display: grid;
  color: var(--sw-paper);
}

/* The shadow: a soft, filled block under the ticket, blurred once on
   a layer of its own. Filled, not a box-shadow - a box-shadow is
   hollow under its own box, so a stub lifting off would uncover a
   pale patch where its shadow should be. Held in from the sides past
   the bites, so they show clean page. --tk-cut pulls its foot up as
   the stub is torn away, so the shadow leaves with it. */
.ct-ticket::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 1.5rem 1rem var(--tk-cut);
  background: rgba(20, 20, 15, 0.2);
  filter: blur(1rem);
  transform: translateY(0.85rem);
  will-change: transform;
  pointer-events: none;
}

/* Both pieces: their paint is clipped pseudo layers, each cut to the
   piece's own shape. */
.ct-tk-main,
.ct-stub-paper {
  position: relative;
  isolation: isolate;
}

.ct-tk-main::before,
.ct-tk-main::after,
.ct-stub-paper::before {
  content: "";
  position: absolute;
  z-index: -1;
}

/* The body: bevelled at the top, square at the foot, where the
   bites come out of it and the slits run between them - on the ink
   side of the fold, where they read. */
.ct-tk-main {
  padding: 1.5rem 1.6rem 1.35rem;
  -webkit-mask:
    radial-gradient(circle var(--bite) at 0 100%, transparent 96%, #000 100%),
    radial-gradient(circle var(--bite) at 100% 100%, transparent 96%, #000 100%),
    linear-gradient(90deg, #000 var(--dash), transparent 0) left calc(var(--bite) + 6px) bottom 0 / var(--gap) var(--dash-h) repeat-x,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: source-in, source-in, xor;
  mask:
    radial-gradient(circle var(--bite) at 0 100%, transparent 96%, #000 100%),
    radial-gradient(circle var(--bite) at 100% 100%, transparent 96%, #000 100%),
    linear-gradient(90deg, #000 var(--dash), transparent 0) left calc(var(--bite) + 6px) bottom 0 / var(--gap) var(--dash-h) repeat-x,
    linear-gradient(#000 0 0);
  mask-composite: intersect, intersect, exclude;
}

.ct-tk-main::before,
.ct-tk-main::after {
  clip-path: polygon(var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c),
    100% 100%, 0 100%, 0 var(--c));
}

.ct-tk-main::before { --c: var(--n); inset: 0; background: #3a3a36; }

/* The face runs to the foot - no edge along the perforation, so the
   body and the stub meet as one card. */
.ct-tk-main::after {
  --c: calc(var(--n) - 1.5px * var(--pg-bevel-k));
  inset: 1.5px 1.5px 0;
  background: #141414;
}

.ct-tk-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font: 600 0.62rem/1 "Inter Tight", sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #8f8f88;
}

.ct-tk-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--sw-paper);
}

.ct-tk-brand img {
  height: 1rem;
  width: auto;
}

.ct-tk-title {
  margin-top: 1.4rem;
  font-family: "sohne-bold", "Inter Tight", sans-serif;
  font-weight: 800;
  font-size: clamp(1.8rem, 2.2vw, 2.4rem);
  line-height: 0.9;
  letter-spacing: -0.04em;
  text-transform: uppercase;
}

.ct-tk-rows {
  margin-top: 1.25rem;
}

.ct-tk-rows > div {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr);
  gap: 0.75rem;
  align-items: baseline;
  padding: 0.7rem 0;
  border-top: 1px solid #2e2e2a;
}

.ct-tk-rows dt {
  font: 500 0.62rem/1.3 "Inter Tight", sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #8f8f88;
}

/* Each value has its own clip, so a new one can rise into place. */
.ct-tk-rows dd {
  overflow: hidden;
  font-family: "sohne-medium", "Inter Tight", sans-serif;
  font-size: 0.95rem;
  line-height: 1.35;
  color: var(--sw-paper);
}

.ct-tk-rows dd > span {
  display: block;
}

.ct-tk-rows dd.is-empty {
  color: #6f6f68;
}

/* How far along, on one line at the body's foot. */
.ct-tk-state {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-top: 1rem;
  border-top: 1px solid #2e2e2a;
}

.ct-tk-state b {
  flex: none;
  font-family: "sohne-bold", "Inter Tight", sans-serif;
  font-weight: 800;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Five cells for the five things the brief needs. The fill still
   runs as one bar underneath; the cells are cut over it. */
.ct-tk-meter {
  flex: 1;
  height: 4px;
  background: #2e2e2a;
  overflow: hidden;
  -webkit-mask: linear-gradient(90deg, #000 calc(100% - 3px), transparent 0) 0 0 / 20% 100% repeat-x;
  mask: linear-gradient(90deg, #000 calc(100% - 3px), transparent 0) 0 0 / 20% 100% repeat-x;
}

.ct-tk-meter > span {
  display: block;
  height: 100%;
  background: var(--sw-accent);
  transform-origin: 0 50%;
  transform: scaleX(var(--p, 0));
  transition: transform 0.7s var(--pg-ease);
}

/* ------------------------------------------------------------
   The stub - the send
   ------------------------------------------------------------ */
.ct-send[hidden] {
  display: none;
}

/* The button: the hit area, the full width of the ticket, and never
   moved by its own hover - the paper inside it is what peels. */
.ct-tk-stub {
  all: unset;
  box-sizing: border-box;
  display: block;
  width: 100%;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* The paper: bites at the top corners, the lower half of each slit
   along its top edge (on the body's pitch, so the two halves meet as
   one cut), and the bevel on the foot. Pressing it is tearing it off,
   so on hover it starts to peel - a degree off the perforation,
   hinged on the left. */
.ct-stub-paper {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 1.25rem;
  padding: 1.3rem 1.6rem 1.25rem;
  color: var(--sw-ink);
  transform-origin: 0 0;
  transition: transform 0.6s var(--pg-ease);
  /* No will-change: a masked layer promoted for good, inside a stub
     that is itself being sheared, is a path Chromium's compositor
     can crash on. The transition gets its own layer while it runs. */
  -webkit-mask:
    radial-gradient(circle var(--bite) at 0 0, transparent 96%, #000 100%),
    radial-gradient(circle var(--bite) at 100% 0, transparent 96%, #000 100%),
    linear-gradient(90deg, #000 var(--dash), transparent 0) left calc(var(--bite) + 6px) top 0 / var(--gap) var(--dash-h) repeat-x,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: source-in, source-in, xor;
  mask:
    radial-gradient(circle var(--bite) at 0 0, transparent 96%, #000 100%),
    radial-gradient(circle var(--bite) at 100% 0, transparent 96%, #000 100%),
    linear-gradient(90deg, #000 var(--dash), transparent 0) left calc(var(--bite) + 6px) top 0 / var(--gap) var(--dash-h) repeat-x,
    linear-gradient(#000 0 0);
  mask-composite: intersect, intersect, exclude;
}

.ct-stub-paper::before {
  --c: var(--n);
  inset: 0;
  background: var(--sw-accent);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%, var(--c) 100%, 0 calc(100% - var(--c)));
  transition: background-color 0.25s ease;
}

/* Hover only where there is a pointer to hover with, so a tap never
   leaves the stub stuck half-peeled. */
@media (hover: hover) {
  .ct-tk-stub:hover .ct-stub-paper {
    transform: skewY(1deg);
  }

  .ct-tk-stub:hover .footer-btn-arrow svg:first-child {
    transform: translate(110%, -110%);
  }

  .ct-tk-stub:hover .footer-btn-arrow svg + svg {
    transform: none;
  }
}

/* Focus: the same peel, and the paper turns white - the ring a masked
   shape cannot draw with an outline. */
.ct-tk-stub:focus-visible .ct-stub-paper {
  transform: skewY(1deg);
}

.ct-tk-stub:focus-visible .ct-stub-paper::before {
  background: var(--sw-paper);
}

.ct-tk-stub:focus-visible .footer-btn-arrow svg:first-child {
  transform: translate(110%, -110%);
}

.ct-tk-stub:focus-visible .footer-btn-arrow svg + svg {
  transform: none;
}

/* Pressed: the paper gives a little under the finger. */
.ct-tk-stub:active .ct-stub-paper {
  transform: skewY(1.6deg) translateY(1px);
  transition-duration: 0.15s;
}

.ct-tk-stub[disabled] {
  cursor: progress;
}

.ct-tk-stub[disabled] .ct-stub-act {
  opacity: 0.55;
}

.ct-stub-act {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  font-family: "sohne-bold", "Inter Tight", sans-serif;
  font-weight: 800;
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: opacity 0.25s ease;
}

/* The code: a real Code 128 of the ticket's ref, drawn by the page
   script one module to a pixel - ink bars on the stub, the way a
   stub carries the serial, with the ref under them tracked out to
   the bars' width. Squeezed only when a narrow ticket cannot hold
   it at its own width. */
.ct-tk-code {
  justify-self: end;
  display: grid;
  gap: 0.4rem;
  min-width: 0;
}

.ct-tk-code svg {
  display: block;
  max-width: 100%;
  height: 1.75rem;
}

.ct-tk-code svg rect {
  fill: currentColor;
}

.ct-tk-code > span {
  display: flex;
  justify-content: space-between;
  font: 600 0.56rem/1 "Inter Tight", sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: rgba(20, 20, 15, 0.62);
}

/* The stamp, pressed onto the ticket when the brief goes: a rubber
   stamp in the accent, set at the angle a hand leaves it. A frame
   inside its edge, the word, and the ref under it. The ink did not
   take everywhere - a fine mask of voids - so it reads as pressed,
   not printed. It has a layer of its own, so its arrival is a
   transform and an opacity and nothing more. */
.ct-stamp {
  --n: 9px;
  position: absolute;
  right: 1.1rem;
  top: 34%;
  padding: 4px;
  color: var(--sw-ink);
  background: var(--sw-accent);
  clip-path: polygon(var(--n) 0, calc(100% - var(--n)) 0, 100% var(--n),
    100% calc(100% - var(--n)), calc(100% - var(--n)) 100%,
    var(--n) 100%, 0 calc(100% - var(--n)), 0 var(--n));
  -webkit-mask: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAABWElEQVR42s2XiW7CMAyG+/4vAOMW4hJIUE0MGDcCTSswQKxsMB4GtNFqbbGbOGlK9EtEddx8tXGd1DAuBL2QvG8SuEUaYKsGyKrGC2jpGoGrrjigypgvwhGcEfc2E+gvi0RUKVox5qd+QE8Y9InmnyOChaoqqhCX+fZdWQ9uFf9ag9YEaO3xAr6En/UjcG3hEcyZi021btcicqtuSAUMnPEU4lP/+03xRuDP/6uKFCVDb5iJAcxH/sklxvw2tNlzdnyKlrJlOgJsR2fMOOMeA/R1fdGC2mnXKn7QE2pdu2bXYGwsUEP71SHOCN5ogA5iz3tqxd3RTNURrJ3G4QFkIkaksQhyoPskyirKcpyj03ce74yDGuFZLA6fSZwvWkcdYCP6lfnEtfwguhQ1Am3QqzEMKBu28cxcuAnYTCRWqRxv4tzR5nKAMwlWCAJs4LgRw5aZJ31uILoCl5PdHIp5tf8AAAAASUVORK5CYII=") 0 0 / 48px 48px;
  mask: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAABWElEQVR42s2XiW7CMAyG+/4vAOMW4hJIUE0MGDcCTSswQKxsMB4GtNFqbbGbOGlK9EtEddx8tXGd1DAuBL2QvG8SuEUaYKsGyKrGC2jpGoGrrjigypgvwhGcEfc2E+gvi0RUKVox5qd+QE8Y9InmnyOChaoqqhCX+fZdWQ9uFf9ag9YEaO3xAr6En/UjcG3hEcyZi021btcicqtuSAUMnPEU4lP/+03xRuDP/6uKFCVDb5iJAcxH/sklxvw2tNlzdnyKlrJlOgJsR2fMOOMeA/R1fdGC2mnXKn7QE2pdu2bXYGwsUEP71SHOCN5ogA5iz3tqxd3RTNURrJ3G4QFkIkaksQhyoPskyirKcpyj03ce74yDGuFZLA6fSZwvWkcdYCP6lfnEtfwguhQ1Am3QqzEMKBu28cxcuAnYTCRWqRxv4tzR5nKAMwlWCAJs4LgRw5aZJ31uILoCl5PdHIp5tf8AAAAASUVORK5CYII=") 0 0 / 48px 48px;
  transform: rotate(-11deg);
  opacity: 0;
  pointer-events: none;
  will-change: transform, opacity;
}

/* The frame: an ink edge and an accent face, each bevelled, so the
   line keeps one weight on the cuts. */
.ct-stamp-in {
  --n: 6px;
  position: relative;
  isolation: isolate;
  display: grid;
  justify-items: center;
  gap: 0.3rem;
  padding: 0.5rem 0.85rem 0.45rem;
}

.ct-stamp-in::before,
.ct-stamp-in::after {
  content: "";
  position: absolute;
  z-index: -1;
  clip-path: polygon(var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c),
    100% calc(100% - var(--c)), calc(100% - var(--c)) 100%,
    var(--c) 100%, 0 calc(100% - var(--c)), 0 var(--c));
}

.ct-stamp-in::before { --c: var(--n); inset: 0; background: var(--sw-ink); }
.ct-stamp-in::after {
  --c: calc(var(--n) - 1.5px * var(--pg-bevel-k));
  inset: 1.5px;
  background: var(--sw-accent);
}

.ct-stamp b {
  font-family: "sohne-bold", "Inter Tight", sans-serif;
  font-weight: 800;
  font-size: 1.35rem;
  line-height: 0.9;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.ct-stamp small {
  font: 700 0.52rem/1 "Inter Tight", sans-serif;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------
   Sent
   ------------------------------------------------------------ */
/* Takes the form's cell once the form has collapsed, stretched to
   the row - which the ticket beside it sets - with the blurb and its
   buttons centred in it both ways. */
.ct-done {
  align-self: stretch;
  display: flex;
  outline: none;
  border-top: 2px dashed var(--sw-ink);
}

.ct-done[hidden] {
  display: none;
}

.ct-done-in {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  min-height: clamp(22rem, 50vh, 30rem);
  padding: clamp(2.5rem, 6vh, 4rem) 0;
  text-align: center;
}

/* The blurb, in the site's hand and at the angle a hand leaves it. */
.ct-done-note {
  max-width: min(100%, 34rem);
  margin: 0 0 clamp(1.75rem, 4vh, 3rem);
  font-size: clamp(1.5rem, 1.1vw + 0.95rem, 2.2rem);
  line-height: 1.25;
  color: var(--sw-ink);
  transform: rotate(-4deg);
  transform-origin: 50% 50%;
}

.ct-done-note [data-ct-done-ref] {
  white-space: nowrap;
}

.ct-done-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 1.25rem 2rem;
  margin-top: 1rem;
}

/* The back arrow: the footer CTA's drawn arrow turned to point back
   (up and to the left), leading the label. Mirrored, so on hover it
   leaves and returns the other way too. */
.footer-btn-arrow.is-back {
  transform: scaleX(-1);
}

/* ------------------------------------------------------------
   Narrow
   ------------------------------------------------------------ */
@media (max-width: 1000px) {
  .ct-intro {
    grid-template-columns: minmax(0, 1fr);
  }

  .ct-lede {
    grid-column: 1;
  }

  /* The hand drops out on a phone, as it does on home. */
  .ct-note {
    display: none;
  }

  .ct-grid {
    margin-top: clamp(2.5rem, 6vh, 4rem);
  }

  .ct-sheet {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
    padding-top: var(--sw-sheet-top);
  }

  .ct-grid {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 1.75rem;
  }

  .ct-form,
  .ct-done,
  .ct-side {
    grid-column: 1;
    grid-row: auto;
  }

  .ct-side {
    position: relative;
    top: 0;
    margin-top: 2.5rem;
  }

  .ct-step {
    padding: 1.75rem 0 1.5rem;
  }

  .ct-step-grid {
    row-gap: 1.25rem;
  }

  .ct-name {
    font-size: 1.05rem;
  }

  .ct-body {
    gap: 1.25rem;
  }

  .ct-step-label {
    gap: 0.75rem;
  }

  /* One size for every answer on a phone - 16px, so iOS does not
     zoom the page when a field takes focus. */
  .ct-input input,
  .ct-input textarea,
  .ct-chip-face,
  .ct-seg-opt {
    font-size: 1rem;
  }

  /* The chips go to an even two-up grid rather than a ragged wrap:
     every choice the same width, the same height and a full thumb's
     reach, with a long name wrapping inside its own chip. */
  .ct-chips {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
  }

  .ct-chip {
    display: flex;
  }

  .ct-chip-face {
    flex: 1;
    min-height: 3.25rem;
    padding: 0.7rem 0.8rem;
    gap: 0.6rem;
  }

  .ct-row {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Five ranges will not share a phone's width, so the bar breaks
     into a grid of three and two. The sliding block still finds the
     chosen cell, because it is placed from the cell's own box. */
  .ct-seg {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 4px;
  }

  .ct-seg-opt {
    min-height: 3.25rem;
  }

  /* The top range takes the whole last row, so the bar ends square
     instead of on a lone cell. */
  .ct-seg-opt:last-child {
    grid-column: 1 / -1;
  }

  /* Children 2, 4 and 6 open their rows (the block is child 1), so
     they lose the hairline on their left. */
  .ct-seg-opt:nth-child(2n)::before {
    display: none;
  }

  /* "Not sure yet" the width of the bar above it. */
  .ct-seg-foot {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
  }

  .ct-seg-foot .ct-chip-face {
    min-height: 3.25rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ct-bar,
  .ct-box::after,
  .ct-tk-meter > span,
  .ct-stub-paper {
    transition: none;
  }

  .ct-tk-stub:hover .ct-stub-paper,
  .ct-tk-stub:focus-visible .ct-stub-paper,
  .ct-tk-stub:active .ct-stub-paper {
    transform: none;
  }
}
