/*
 * giftlift.com — the whole site's styling.
 *
 * READ THIS FIRST: reproducing WordPress is no longer the goal.
 *
 * The file began as a pixel-faithful reproduction of the WordPress page, every value measured off
 * the live site at 1440px with a headless browser rather than read out of Bridge/Qode's 2 MB of
 * competing !important rules. That was the right way to migrate, and the structure it produced —
 * the 1300px grid, the two brand colors, the three families — is still what holds the site up.
 *
 * It was the wrong thing to keep once the site grew to seven pages. The theme was a 2021
 * multipurpose template: 16px gray body text, 24px headings, 10px uppercase buttons, cold blue-gray
 * bands, a 150px-tall empty header and a magenta stock hero that fought the purple brand. Faithful
 * to it meant dated.
 *
 * So there are two layers here, and the boundary is the "palette" block immediately below:
 *
 *   - Measurements of the WordPress page, kept where they were load-bearing (the grid, the brand
 *     colors, the header behavior, the accordion, the widget spacing). Each still says what it
 *     measured and why.
 *   - Design decisions taken since, which override those measurements where the measurement was
 *     only ever a record of a template. Each says what it replaced.
 *
 * Watch the ordering when editing. A second :root block further down used to redeclare --rule and
 * --ink with the old cold values and won purely by being later in the file, so every hairline on
 * the site was gray and nothing above explained it. Tokens are defined once, at the top.
 *
 * Fonts: the two Adobe Fonts (Typekit) kits the WordPress site loads, neither domain-restricted —
 * they serve on any hostname, which is why a preview on the distribution's own domain looks
 * exactly like production. See README, "Fonts". Plus Caveat, self-hosted, which is the actual
 * file the printer sets a customer's message in — see the @font-face note below.
 */

/* ---------------------------------------------------------------- palette --
 *
 * The product is a printed card, so the page is paper.
 *
 * Every surface here is warm — ivory ground, cream and plum bands — and pure
 * white is spent on one thing only: the cards, so a card reads as a whiter
 * sheet lying on a warmer one. That is the whole idea, and it is why the cold
 * blue-grays the WordPress theme used (#f3f5fb, #ecf0fb) appear nowhere below.
 *
 * The two brand colors are unchanged and still measured off the original. What
 * changed is what surrounds them: mid-purple on cold white gave the brand
 * nothing to sit against, and #676767 body text at 16px was thin under
 * sofia-pro's light stems.
 */
:root {
  /* Measured: rgb(102, 45, 145). Brand purple — headings and marks. */
  --purple: #662d91;
  /* Measured: rgb(92, 0, 176). A different purple from the heading color above.
     Not a rounding error; keep them separate. */
  --purple-button: #5c00b0;
  --orange: #f7941d;

  /* Paper. --paper is the page; --card is reserved for card-like surfaces. */
  --paper: #fbf7f1;
  --card: #ffffff;

  /* Ink, not gray. #676767 on white measured 5.2:1 and read washed out; this is
     over 11:1 on --paper and still not black. */
  --ink: #241b2e;
  --body-text: #3a2e44;
  --muted-ink: #6b5f74;
  --footer-text: rgba(255, 255, 255, .62);

  /* Deep plum for the dark bands. The flat mid-purple slab the interior pages
     opened on was the brand color used as furniture — at that area it stopped
     reading as a brand and started reading as a placeholder. */
  --plum: #2a1140;
  --plum-deep: #1c0a2e;

  /* Section grounds, warm. */
  --bg-code-section: #f4eee6;
  --bg-stats: #faf1e4;
  --bg-footer: #2a1140;

  /* Warm hairlines. A cool gray rule on ivory reads as a smudge. */
  --rule: #e8dfd4;
  --accordion-border: #ded2c4;

  /* qode_grid_1300: the content column is 1300px, centered. Kept — it is a good
     measure and every page is built to it. */
  --grid: 1300px;
  --header-height: 104px;

  --radius: 10px;
  --shadow-card: 0 1px 2px rgba(36, 27, 46, .05), 0 10px 30px rgba(36, 27, 46, .07);
  --shadow-lift: 0 2px 8px rgba(36, 27, 46, .10), 0 30px 70px rgba(36, 27, 46, .20);
}

/* The handwriting the product actually prints with.
 *
 * Not a lookalike: this is Caveat-VariableFont_wght.ttf, the exact file
 * api.undigital.com hands the widget and the exact face that gets set into a
 * customer's message on the printed card. Subset to Latin and converted to
 * woff2 (391 KB -> 61 KB). It is used on this site for message text and
 * nothing else — the moment it decorates a heading it stops meaning anything.
 */
@font-face {
  font-family: "Caveat";
  src: url("../fonts/caveat.woff2") format("woff2-variations"),
       url("../fonts/caveat.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--body-text);
  font-family: "sofia-pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* 17.5/1.62 rather than the measured 16/24. The original set one page of copy;
     these pages carry four thousand words, and 16px at a 1.5 ratio is where long
     reading stops being comfortable. */
  font-size: 17.5px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; border: 0; }

a { color: var(--purple); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 700;
  color: var(--ink);
  /* Futura is a geometric face drawn for display sizes. Left at default tracking
     it looks loose above about 30px, which is most of the headings here. */
  letter-spacing: -.015em;
}

/* Handwriting, for message text only. Set a size or two larger than the copy
   around it — Caveat's x-height is small, and matched on paper size it reads as
   a mistake rather than as handwriting. */
.hand {
  font-family: "Caveat", "Segoe Script", "Bradley Hand", cursive;
  font-weight: 600;
  letter-spacing: 0;
}

p { margin: 0 0 20px; }

.inner {
  /* Flush to the 1300px grid on wide screens; a 20px gutter appears only once the viewport is
     narrower than the grid itself. `max-width` plus padding would inset the grid by the padding
     at every width and shift the whole page 20px right of the original. */
  width: min(100% - 40px, var(--grid));
  margin-inline: auto;
}

/* Visible only to screen readers — used for the skip link and the section landmarks. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: 20px;
  top: -60px;
  z-index: 100;
  padding: 10px 18px;
  background: var(--purple);
  color: #fff;
  transition: top .15s ease;
}
.skip-link:focus { top: 12px; }

/* ---------------------------------------------------------------- header --
 *
 * Scrolls away with the page. The theme's markup carries a `fixed` class and a
 * `scroll_header_top_area` wrapper, which reads as a pinned header — but the computed position on
 * the live site is `relative`, and scrolling confirms it: the header leaves the viewport and does
 * not come back. `position: relative` here is deliberate, not an omission.
 *
 * It still needs to be a positioned element, because the mobile nav panel below is absolutely
 * positioned against it.
 */
.site-header {
  position: relative;
  z-index: 50;
  height: var(--header-height);
  background: var(--paper);
  /* 150px of empty white was a third of a laptop viewport spent on a logo. */
  border-bottom: 1px solid var(--rule);
}

.site-header .inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
}

.site-logo { display: block; line-height: 0; }
.site-logo img { width: 147px; height: 44px; }

.main-nav ul {
  display: flex;
  align-items: center;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.main-nav a {
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 15px;
  font-weight: 700;
  color: var(--purple);
  white-space: nowrap;
  /* Not a gap: the theme pads each link, which puts the last link's TEXT on the grid edge and
     gives every link a 34px-wide hit area between labels. */
  padding: 0 17px;
}

/* The nav collapses to a disclosure button below the 1000px breakpoint the theme uses. The
   checkbox drives it so the menu works with CSS alone — see README on why there is no JS here. */
.nav-toggle, .nav-toggle-label { display: none; }

/* ------------------------------------------------------------------ hero --
 *
 * WAS giftlift-main-image.jpg: a 1920x554 magenta-to-orange gradient composite with a stock
 * photograph of a woman holding a phone, the headline set over the busiest part of it. Two
 * problems, and the first is fatal. It is hot pink; the brand is purple. Putting them together
 * made the brand color look like an accident on its own home page. And the artwork already
 * contained a picture of the product, at postage-stamp size, behind a face.
 *
 * So the product IS the hero now, at full size and rendered rather than photographed: a real
 * card from the library, carrying a real message set in the real Caveat file the printer uses.
 * See .card-hero below. That is the whole pitch in one object — somebody wrote this, and it came
 * out of a printer.
 *
 * The band is plum rather than an image: the card is the only thing that should be competing for
 * attention, and a photograph behind it would win.
 */
.hero {
  position: relative;
  padding: 84px 0 92px;
  overflow: hidden;
  background: var(--plum-deep);
  color: #fff;
}

/* Two lamps, warm then magenta, both very soft. They exist so the plum is not a flat fill and so
   the card has something to sit in. The magenta is the one thing kept from the old artwork — it
   belongs to the brand, it just cannot be the whole background. */
.hero::before {
  content: "";
  position: absolute;
  inset: -30% -10% auto -10%;
  height: 150%;
  background:
    radial-gradient(58% 60% at 78% 30%, rgba(236, 28, 142, .30) 0%, rgba(236, 28, 142, 0) 62%),
    radial-gradient(50% 55% at 12% 12%, rgba(247, 148, 29, .16) 0%, rgba(247, 148, 29, 0) 60%);
  pointer-events: none;
}

.hero .inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: 72px;
  align-items: center;
}

.hero-copy {
  max-width: none;
  margin-left: 0;
  color: #fff;
}

.hero .eyebrow { color: #ffb765; }

.hero h1 {
  margin: 0 0 22px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  /* Fluid, and finally at a display size. 48px in a 1300px column read as a large
     paragraph rather than as a headline. */
  font-size: clamp(38px, 4.6vw, 62px);
  line-height: 1.04;
  letter-spacing: -.022em;
  font-weight: 700;
  color: #fff;
  text-wrap: balance;
}

.hero p {
  max-width: 46ch;
  margin: 0;
  font-size: 19px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .82);
}

/* A quiet line of proof under the buttons. The numbers are already on the page further down;
   here they are the reason to keep reading rather than a feature list. */
.hero-proof {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  margin: 34px 0 0;
  padding: 22px 0 0;
  border-top: 1px solid rgba(255, 255, 255, .16);
  font-size: 15px;
  line-height: 1.35;
  color: rgba(255, 255, 255, .62);
}
.hero-proof b {
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 17px;
  font-weight: 700;
  color: #fff;
}
.hero-proof span { display: inline-flex; align-items: baseline; gap: 7px; }

/* ------------------------------------------------------------- card-hero --
 *
 * The signature. A card from the shared library with a message set into it, tilted and lit like
 * a physical object.
 *
 * The message is positioned in the same terms the product uses: every template in the API
 * carries a message box as percentage insets plus a point size, and the printer sets the
 * customer's text into that box. The insets below are thank-you-02's, read off the artwork —
 * so this is not a caption laid over a picture of a card, it is the same operation the press
 * performs, done in CSS.
 */
.card-hero {
  position: relative;
  width: 100%;
  max-width: 400px;
  margin: 0 auto;
  aspect-ratio: 5 / 7;
  /* Just off square to the page. A card someone has put down, not a product shot. */
  transform: rotate(-3.2deg);
  border-radius: 6px;
  background: var(--card);
  box-shadow: var(--shadow-lift);
}

.card-hero img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 6px;
}

/* thank-you-02's message panel, measured off the artwork: the gold rule sits at 29% from the
   left, 25% from the right and 32% down. The text is clamped to the panel rather than merely
   placed near it — overflowing a printed frame is the one mistake that would give the whole
   conceit away. */
.card-hero .hand {
  position: absolute;
  /* The gold rule, measured off the artwork at 1440px: 33% down, 33% in from the left, 26% in
     from the right, 35% up from the bottom. Inset a little further so the writing sits inside
     the frame with air rather than against it, and centered vertically so the message reads as
     placed on the panel rather than dropped at the top of it. */
  top: 35%;
  bottom: 37%;
  left: 35%;
  right: 28%;
  display: flex;
  align-items: center;
  margin: 0;
  font-size: clamp(12px, 1.22vw, 17px);
  line-height: 1.34;
  color: #4a3a2e;
  transform: rotate(-.6deg);
}

.card-hero figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -46px;
  transform: rotate(3.2deg);
  font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  text-align: center;
  color: rgba(255, 255, 255, .5);
}

/* --------------------------------------------------------------- sections */

.section { padding: 96px 0 32px; }

/* WPBakery's rule for this row was `background: #f3f5fb url(diagonal-bkgrd.png)` sized cover.
   The PNG is gone: it is a near-white BLUE-gray diagonal wash, and laid over the warm ivory it
   canceled exactly the thing the palette is built on — the band came out the same cold gray as
   the theme it replaced. The flat color underneath was always what carried the section. */
.section--code {
  background: var(--bg-code-section);
}

.section--widget { padding-bottom: 15px; }

.section--stats {
  padding: 72px 0;
  background: var(--bg-stats);
}

.section--cta {
  padding: 0;
  background: var(--bg-stats);
}

/* Two-column split. 8/4 and 6/6 are the WPBakery column widths the original uses. */
.cols {
  display: grid;
  /* 40px reproduces WPBakery's 12-column gutter closely enough that no element lands more than
     7px off its position on the live site. */
  gap: 40px;
  align-items: start;
}
.cols--8-4 { grid-template-columns: minmax(0, 8fr) minmax(0, 4fr); }
.cols--6-6 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }

/* The theme pads the text column away from the artwork beside it. Only the widget section is
   still laid out this way — the code section it was measured alongside is now a full-width
   .codeblock under a .section-intro, because a real <pre> needs the room a 599px screenshot
   did not. */
.col-text--widget { padding-right: 8%; }

.section h2 {
  margin: 0 0 25px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 24px;
  line-height: 28px;
  font-weight: 700;
  color: var(--purple);
}

/* The lead line under each heading. Bold body text, not a heading — matching the original,
   where it is a <strong> inside a paragraph. */
.lead { font-weight: 700; }

/* ---------------------------------------------------------------- buttons */

/* 10px uppercase Lato with 2px tracking was the theme's button, and at that size the label is
   doing more work as texture than as a word. These are set in the brand's own display face at a
   size you can read, which also makes the primary action visible from across the page. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 52px;
  padding: 0 28px;
  border: 0;
  border-radius: 30px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: .01em;
  text-transform: none;
  color: #fff;
  cursor: pointer;
  transition: transform .16s ease, box-shadow .16s ease, background-color .16s ease;
}
.button:hover {
  text-decoration: none;
  transform: translateY(-1px);
  box-shadow: 0 8px 20px rgba(36, 27, 46, .18);
}
.button:active { transform: translateY(0); }
.button:focus-visible {
  outline: 3px solid var(--orange);
  outline-offset: 3px;
}

.button--orange { background: var(--orange); color: #33210a; }
.button--orange:hover { background: #ffa63c; }
.button--purple { background: var(--purple-button); }
.button--purple:hover { background: #6d0dc9; }

/* Reproduces the spacing WPBakery puts around the widget — a nested row's own offsets plus the
   two 32px spacer elements below it — folded into one margin.
   NOTE this is tuned against the widget's PRODUCTION height (108px). Locally the widget renders
   a short stub, because api.undigital.com refuses the cross-origin call from localhost — so this
   section measures ~20px shorter in local preview than it does deployed. That gap is expected. */
#giftlift-widget { margin: 18px 0 80px; }

/* -------------------------------------------------------------- accordion --
 *
 * <details>/<summary> rather than the theme's JavaScript toggle. Same behavior — each panel
 * opens independently, none open on load — with none of the script, and it still works if the
 * page's JS never runs.
 *
 * The default disclosure triangle is removed with both the standard `::details-marker` and the
 * WebKit pseudo-element; Safari still needs the latter.
 */
.accordion { display: block; }

.accordion details {
  margin-bottom: 10px;
  border: 0;
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-card);
}
.accordion details[open] { box-shadow: var(--shadow-card), 0 0 0 1px var(--rule); }

.accordion summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 66px;
  padding: 5px 20px;
  cursor: pointer;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 15px;
  font-weight: 700;
  color: var(--purple);
  list-style: none;
}
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary::marker { content: ""; }

/* The +/− is drawn rather than shipped as the theme's icon font, which costs a 60 KB webfont to
   render two glyphs. */
.accordion summary::after {
  content: "+";
  flex: none;
  font-size: 22px;
  font-weight: 400;
  line-height: 1;
  color: var(--orange);
}
.accordion details[open] summary::after { content: "\2013"; }

.accordion .panel { padding: 0 20px 20px; }
.accordion .panel p { margin: 0; }

/* The .video-band rules are gone with video.jpg. It was a 317px background image and nothing
   else, with an orange play button painted dead center that had never been a link. The half of
   the photograph to the right of the button is now site/assets/img/gift-box.jpg, used beside
   copy rather than under a control that does nothing. The original is in git history at
   ae72c91 if it is ever wanted back. */

/* ------------------------------------------------------------------ stats */

.stats {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 30px;
  text-align: center;
}

.stat img {
  display: block;
  width: 212px;
  max-width: 100%;
  margin: 0 auto 25px;
}

.stat h3 {
  margin: 0;
  font-size: 20px;
  line-height: 26px;
  font-weight: 300;
  color: var(--purple);
}

/* The .cta-banner rules are gone with contact.png — a 1170x150 flat image with the sentence and
   the button painted into it, neither of which was a link, and neither of which was legible
   below about 700px. See .cta-band further down, which is the same band set as text.

   The measured detail that went with it is worth keeping written down in case anyone rebuilds
   the original spacing: the theme's row was 25px taller than the banner and then pulled itself
   30px into the footer, so the footer's background started flush with the banner's bottom edge.
   Net zero, which is why the rule said zero rather than +25 and -30. */

/* ----------------------------------------------------------------- footer */

.site-footer {
  padding: 90px 0 28px;
  background: var(--bg-footer);
  text-align: center;
}

.site-footer img {
  display: block;
  width: 123px;
  height: 37px;
  margin: 0 auto 10px;
}

.site-footer p {
  margin: 0;
  font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 11px;
  line-height: 26px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--footer-text);
}

/* The .error-page rules that used to sit here are gone. The 404 was a centered
   headline and a button; it is now a .page-hero and a grid of .tile links to
   the four pages a lost visitor was most likely after, so it needs nothing of
   its own. */

/* ----------------------------------------------------------- breakpoints --
 *
 * The WordPress site is responsive down to 1000px and then degrades: below that the hero layer
 * keeps its desktop type scale while the artwork shrinks, so the headline overflows the pink
 * band and lands on the section beneath it, and the hamburger the theme renders is invisible
 * against the white header. Neither is reproduced — see README.
 */

@media (max-width: 1200px) {
  .hero-copy { margin-left: 0; }
  .col-text--code, .col-text--widget { padding-right: 0; }
}

@media (max-width: 1000px) {
  :root { --header-height: 100px; }

  .site-logo img { width: 120px; height: 36px; }

  .nav-toggle-label {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 34px;
    height: 34px;
    cursor: pointer;
  }
  .nav-toggle-label span {
    display: block;
    height: 3px;
    border-radius: 2px;
    background: var(--purple);
  }

  .main-nav {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    display: none;
    padding: 8px 0 16px;
    background: var(--paper);
    box-shadow: 0 14px 26px rgba(36, 27, 46, .12);
  }
  /* The nav now sits inside .nav-cluster, alongside the CTA, so the sibling
     combinator has to reach through it. The checkbox itself stays a direct
     child of .inner — a general sibling selector only looks forwards. */
  .nav-toggle:checked ~ .nav-cluster .main-nav { display: block; }

  .main-nav ul {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    max-width: var(--grid);
    margin: 0 auto;
    padding: 0 20px;
  }
  .main-nav a { display: block; padding: 14px 0; font-size: 17px; }

  /* The pink gradient that used to be here is gone with the artwork it was sampled from — it
     was two thirds magenta on a purple-branded site, and it made the phone view look like a
     different company's. The hero is one band at every width now: plum, copy, then the card. */
  .hero {
    height: auto;
    padding: 52px 0 60px;
  }
  .hero .inner { grid-template-columns: minmax(0, 1fr); gap: 44px; }
  .hero-copy { max-width: none; }

  /* The card follows the copy rather than sitting beside it, and stops growing — at 400px wide
     on a 390px screen it filled the fold on its own. */
  .card-hero { max-width: 268px; }
  .card-hero figcaption { bottom: -38px; }

  .hero-proof { margin-top: 30px; gap: 8px 16px; }

  .cols--8-4, .cols--6-6 { grid-template-columns: minmax(0, 1fr); gap: 40px; }

  .section { padding: 60px 0 24px; }
  .section--plain,
  .section--tint,
  .section--cream { padding: 60px 0; }
  .section--stats { padding: 60px 0; }

  .site-footer { padding: 56px 0 32px; }
}

@media (max-width: 620px) {
  .stats { grid-template-columns: minmax(0, 1fr); gap: 40px; }

  /* Buttons stack full-width rather than wrapping their own labels mid-phrase. */
  .hero-actions { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .hero-actions .button { width: 100%; }
  .button { padding: 0 22px; }

  .cta-band { flex-direction: column; align-items: flex-start; padding: 34px 26px; }
  .cta-band p { max-width: none; }
}

/* Honor a reader's reduced-motion preference for the only transition on the page. */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ==========================================================================
 * Everything below this line was written for the multi-page site. It was not
 * measured off WordPress, because there was nothing to measure: the original
 * was one page whose four nav links all pointed at "#".
 *
 * The split is kept so it stays obvious which numbers are measurements of a
 * site that existed and which are decisions taken since. The palette, the
 * 1300px grid and the three families are unchanged — nothing below introduces
 * a color or a typeface the original did not already use.
 * ========================================================================== */

:root {
  /* Neutrals the original had no use for: it carried no rules, no form controls
     and no tables.
     --rule and --ink used to be redeclared here as #dfe3ee and #3d3d46, which
     silently beat the warm values in the palette block above simply by coming
     later in the file. Every hairline on the site was cold gray and every
     heading was slate, and nothing in the palette block explained why. They are
     defined once now, at the top. */
  --muted: var(--muted-ink);
  --surface: #f6f0e8;
}

/* --------------------------------------------------------- header (cont.) --
 *
 * The header gained a CTA. It sits outside .main-nav so that it stays visible
 * when the nav collapses into the hamburger below 1000px: the one thing a
 * visitor on a phone is most likely to want should not be behind a disclosure
 * they have to discover first.
 */
.site-header .inner { gap: 16px; }

.nav-cluster {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-left: auto;
}

.nav-cta {
  flex: none;
  height: 40px;
  padding: 0 20px;
  border-radius: 36px;
  background: var(--purple-button);
  font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 10px;
  font-weight: 900;
  line-height: 40px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
}
.nav-cta:hover { text-decoration: none; opacity: .88; }

/* The current page is marked rather than merely styled: aria-current does the
   announcing, and the underline is drawn off that same attribute, so the two
   cannot drift apart. */
.main-nav a[aria-current="page"] {
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-thickness: 2px;
}

/* ------------------------------------------------------- section headings --
 *
 * 38px, from a measured 24px. On a single page with two headings 24px passes;
 * across seven pages with twenty of them, a section heading barely larger than
 * its own lead line is not a heading, it is bold text.
 */
.section h2 {
  font-size: clamp(27px, 2.7vw, 38px);
  line-height: 1.12;
  letter-spacing: -.018em;
  color: var(--ink);
  text-wrap: balance;
}

.section-intro { max-width: 46ch; }
.section-intro .lead { font-size: 19px; }

/* The eyebrow is a label, so it is set in the utility face and kept small. The
   rule to its left is what makes it read as a section marker rather than as a
   short orange sentence — it is doing the job the theme gave to nothing. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 16px;
  font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 2.2px;
  text-transform: uppercase;
  color: var(--orange);
}
.eyebrow::before {
  content: "";
  width: 26px;
  height: 2px;
  flex: none;
  background: currentColor;
}

/* The three .section rules above carry `padding: 72px 0 15px` — a 15px bottom,
   because on the WordPress page the element inside each section supplied the
   rest of the gap through its own margin. Sections written since do not have
   that element, so they set their own symmetrical padding. */
.section--plain,
.section--tint,
.section--cream { padding: 96px 0; }

.section--plain { background: var(--paper); }
.section--tint { background: var(--bg-code-section); }
.section--cream { background: var(--bg-stats); }

/* The CTA band closes the stats section on every page that has one, and both are painted the
   same cream. Two lots of 72px between them reads as a gap in one section rather than the join
   between two. */
.section--stats + .section--cream { padding-top: 0; }

/* Two classes, to out-specify the `.hero p { margin: 0 }` measured above
   without reaching for !important. */
.hero .hero-actions { margin-top: 28px; }

/* --------------------------------------------------------- interior pages --
 *
 * Interior pages open on a flat purple band rather than the home page's 450px
 * hero. The hero artwork is the home page's — repeating it five more times
 * would make every page look like the same page.
 */
/* Plum, not the brand purple. A full-bleed band of #662d91 with a headline in the
   left third and nothing in the right two thirds was the single flattest thing on
   the site — the brand color used as furniture, at an area where it stops reading
   as a brand. Same lamps as the hero, so the two bands belong to one page. */
.page-hero {
  position: relative;
  overflow: hidden;
  padding: 76px 0 72px;
  background: var(--plum);
  color: #fff;
}
.page-hero::before {
  content: "";
  position: absolute;
  inset: -40% -10% auto -10%;
  height: 170%;
  background:
    radial-gradient(52% 58% at 82% 24%, rgba(236, 28, 142, .24) 0%, rgba(236, 28, 142, 0) 62%),
    radial-gradient(46% 52% at 8% 6%, rgba(247, 148, 29, .13) 0%, rgba(247, 148, 29, 0) 60%);
  pointer-events: none;
}
.page-hero .inner { position: relative; z-index: 1; }

.page-hero h1 {
  /* em, so it scales with the heading rather than staying fixed while the type
     shrinks at the breakpoints below. */
  max-width: 15em;
  margin: 0 0 22px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: clamp(34px, 4.2vw, 56px);
  line-height: 1.05;
  letter-spacing: -.022em;
  color: #fff;
  text-wrap: balance;
}

.page-hero p {
  max-width: 58ch;
  margin: 0;
  font-size: 19px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .78);
}

.page-hero .eyebrow { color: #ffc978; }

/* The default link color is the same purple this band is painted in. */
.page-hero p a { color: #fff; text-decoration: underline; text-underline-offset: 3px; }

/* Breadcrumbs, for the reader as much as for the crawler: every page is one
   click from home, and the trail is what says so. */
.crumbs {
  margin: 0 0 18px;
  font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.crumbs ol { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.crumbs li + li::before { content: "/"; margin-right: 8px; color: rgba(255, 255, 255, .45); }
.crumbs a { color: rgba(255, 255, 255, .82); }
.crumbs [aria-current="page"] { color: #fff; }

/* ------------------------------------------------------------------ prose */

.prose { max-width: 68ch; }
.prose h2 { margin-top: 44px; }
.prose > h2:first-child { margin-top: 0; }

.prose h3 {
  margin: 32px 0 12px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 19px;
  line-height: 25px;
  color: var(--ink);
}

.prose ul, .prose ol { margin: 0 0 20px; padding-left: 22px; }
.prose li { margin-bottom: 10px; }
.prose li::marker { color: var(--orange); }

/* ------------------------------------------------------------------ split --
 *
 * Copy beside artwork. Roomier on the text side than .cols--8-4 above, because
 * these sections carry two or three paragraphs rather than a caption.
 */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 56px;
  align-items: center;
}
.split--wide-text { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }

/* Columns of very different lengths — a long form beside a short aside — read
   better aligned at the top than centered against each other. */
.split--top { align-items: start; }

/* Artwork on the left at desktop, but still second in the source, so the
   heading is what a screen reader reaches first. */
.split--art-first > :first-child { order: 2; }

.split img {
  display: block;
  width: 100%;
  border-radius: 6px;
}

/* ------------------------------------------------------------- code block --
 *
 * Replaces javascript-1.png, a 114 KB screenshot of a code editor. That
 * screenshot was a developer's local capture: it loaded app.bundle.js from
 * http://localhost:8080, passed a client_id of 12354 and called
 * mw('message', 'Hello world!'), none of which is the snippet a customer
 * pastes. Text also selects, copies, scales, translates and reads aloud.
 */
.codeblock {
  margin: 0 0 14px;
  padding: 26px 28px;
  overflow-x: auto;
  border-radius: var(--radius);
  /* The same plum as the dark bands rather than a generic editor navy, so the one place the
     site shows code still belongs to the site. */
  background: var(--plum-deep);
  color: #ece5f5;
  box-shadow: var(--shadow-card);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: 22px;
}
.codeblock code { font: inherit; white-space: pre; background: none; padding: 0; color: inherit; }
.codeblock .c { color: #9b93b4; }   /* comment */
.codeblock .s { color: #ffb26b; }   /* string  */
.codeblock .k { color: #c6a0f6; }   /* keyword */

.code-caption {
  margin: 0 0 24px;
  font-size: 14px;
  line-height: 21px;
  color: var(--muted);
}

/* -------------------------------------------------------------- card grid --
 *
 * The real card library, the same images the widget shows a shopper. Each file
 * is 300x420 — the largest size the product's CDN serves publicly — displayed
 * about 150px wide so it lands at roughly 2x on the screens most likely to see
 * it.
 *
 * aspect-ratio holds the 5:7 shape before the images arrive, so the grid does
 * not reflow under a reader who has already started scrolling.
 */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 20px;
  margin: 0 0 28px;
  padding: 0;
  list-style: none;
}

/* Cards lift slightly on hover — they are objects, and the grid is the one place on the site
   where you are meant to browse rather than read. Kept to a 2px rise and a shadow; anything
   more and 27 of them at once becomes a fairground. */
.card-grid img {
  display: block;
  width: 100%;
  aspect-ratio: 5 / 7;
  object-fit: cover;
  border: 0;
  border-radius: 5px;
  background: var(--card);
  box-shadow: var(--shadow-card);
  transition: transform .18s ease, box-shadow .18s ease;
}
.card-grid li:hover img {
  transform: translateY(-3px);
  box-shadow: 0 4px 10px rgba(36, 27, 46, .10), 0 18px 40px rgba(36, 27, 46, .16);
}

/* A single card standing on its own beside copy, rather than in the grid. */
.card-single {
  display: block;
  width: 100%;
  max-width: 320px;
  margin: 0 auto;
  aspect-ratio: 5 / 7;
  object-fit: cover;
  border: 1px solid var(--rule);
  border-radius: 4px;
  box-shadow: 0 6px 24px rgba(38, 20, 60, .12);
}

/* Ten occasions, two to four cards each. Stacked full-width, every group but Wedding leaves
   two thirds of the row empty and the page reads as a column of stragglers. Two columns at
   desktop gives each group a track roughly four cards wide, which is the widest group there is. */
.occasion-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(520px, 1fr));
  gap: 40px 56px;
}

.occasion-group { margin-bottom: 0; }
.occasion-group h3 {
  margin: 0 0 16px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 17px;
  color: var(--purple);
}

/* Occasion chips. Deliberately not links: there is no per-occasion page, and
   something that looks clickable but is not is exactly what this rebuild set
   out to get rid of. */
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 28px; padding: 0; list-style: none; }
.chips li {
  padding: 7px 16px;
  border: 1px solid var(--rule);
  border-radius: 20px;
  background: var(--card);
  font-size: 14.5px;
  line-height: 1.3;
  color: var(--ink);
}

/* ------------------------------------------------------------------ steps */

.steps { counter-reset: step; margin: 0; padding: 0; list-style: none; }

.steps > li {
  position: relative;
  margin-bottom: 30px;
  padding-left: 60px;
}
.steps > li:last-child { margin-bottom: 0; }

.steps > li::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: 0;
  top: -2px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--orange);
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 18px;
  line-height: 40px;
  text-align: center;
  color: #fff;
}

.steps h3 { margin: 0 0 8px; }
.steps > li > :last-child { margin-bottom: 0; }

/* ------------------------------------------------------------------ table */

.table-wrap { overflow-x: auto; margin: 0 0 28px; }

table.data {
  width: 100%;
  min-width: 520px;
  border-collapse: collapse;
  font-size: 15px;
}
table.data th, table.data td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--rule);
  text-align: left;
  vertical-align: top;
}
table.data th {
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 14px;
  letter-spacing: .4px;
  color: var(--purple);
}

code {
  padding: 1px 5px;
  border-radius: 3px;
  background: var(--surface);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: .92em;
  color: var(--ink);
}

/* ------------------------------------------------------------------ tiles */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 24px;
  margin: 0 0 28px;
  padding: 0;
  list-style: none;
}

/* Card-like surfaces: white paper on the ivory ground, held by a shadow rather
   than outlined by a 1px box. The outline was what made these read as a table of
   divs — the shadow is what makes them read as something lying on the page. */
.tile {
  padding: 30px 30px 26px;
  border: 0;
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-card);
}
.tile h3 { margin: 0 0 10px; font-size: 20px; }
.tile > :last-child { margin-bottom: 0; }
.tile p { color: var(--body-text); }

/* On the cream and tinted bands a plain white tile still separates, but it needs
   a hairline to stop the shadow doing all the work at low contrast. */
.section--stats .tile,
.section--cream .tile,
.section--tint .tile { box-shadow: var(--shadow-card), 0 0 0 1px var(--rule); }

/* A figure that has to out-weigh the label above it. */
.tile .figure {
  display: block;
  margin: 0 0 6px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 38px;
  line-height: 42px;
  color: var(--purple);
}

/* -------------------------------------------------------------- callout -- */

.callout {
  margin: 0 0 24px;
  padding: 24px 28px;
  border: 0;
  border-left: 3px solid var(--orange);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--card);
  box-shadow: var(--shadow-card);
}
.callout > :last-child { margin-bottom: 0; }

/* --------------------------------------------------------------- cta band --
 *
 * Replaces contact.png — a 1170x150 flat image with the sentence and the
 * button painted into it. A 1170px-wide picture of a sentence does not
 * reflow, so below about 700px the WordPress banner was unreadable, and the
 * "Contact Us" button it depicted was never a link. Set as text it wraps,
 * scales, translates, and goes somewhere.
 */
.cta-band {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  padding: 48px 52px;
  border-radius: var(--radius);
  background: var(--plum);
  text-align: left;
}
/* The same two lamps as the hero and the page bands, so the closing block reads as part of the
   same page rather than as a colored box someone dropped in. */
.cta-band::before {
  content: "";
  position: absolute;
  inset: -60% -10% auto -10%;
  height: 220%;
  background: radial-gradient(50% 55% at 88% 30%, rgba(236, 28, 142, .28) 0%, rgba(236, 28, 142, 0) 62%);
  pointer-events: none;
}
.cta-band > * { position: relative; z-index: 1; }

.cta-band p {
  max-width: 24ch;
  margin: 0;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: clamp(23px, 2.2vw, 31px);
  line-height: 1.12;
  letter-spacing: -.018em;
  color: #fff;
  text-wrap: balance;
}

.button--on-purple { background: var(--orange); }

.button--ghost {
  border: 2px solid rgba(255, 255, 255, .85);
  background: transparent;
  line-height: 42px;
}

.button-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.button-row--spaced { margin-top: 32px; }

/* ------------------------------------------------------------------- form --
 *
 * Posts to /api/form, which CloudFront routes to the SendGrid Lambda.
 *
 * Validation is native — the browser's own required and type checks. Submission
 * is not: the origin is a Lambda function URL behind an origin access control
 * and rejects a POST without an x-amz-content-sha256 header, which no HTML form
 * can set, so site/js/form-submit.js reissues it with fetch.
 *
 * That is the reverse of what this comment said when the page was first built,
 * and the .form-noscript rule below is the consequence: with scripting off the
 * form is hidden and the email address shown, because a form that cannot submit
 * takes someone's time and tells them nothing.
 */
.form { max-width: 560px; }

/* Shown only by the <noscript> rule in /contact/'s <head>, which also hides .form. */
.form-noscript { display: none; }

.form-error {
  margin: 14px 0 0;
  color: #b3261e;
}

.field { margin-bottom: 20px; }

.field label {
  display: block;
  margin-bottom: 6px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 14px;
  letter-spacing: .3px;
  color: var(--ink);
}

.field .req { color: var(--orange); }

.field input,
.field select,
.field textarea {
  display: block;
  width: 100%;
  padding: 14px 16px;
  /* Warm, to match every other rule on the page. #c9cee0 was a blue-gray and on
     ivory it read as the one control that had come from another site. */
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--card);
  font-family: inherit;
  font-size: 16.5px;
  line-height: 1.4;
  color: var(--ink);
  transition: border-color .14s ease, box-shadow .14s ease;
}

.field textarea { min-height: 130px; resize: vertical; }

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 3px solid rgba(102, 45, 145, .35);
  outline-offset: 1px;
  border-color: var(--purple);
}

.field .hint { margin: 6px 0 0; font-size: 13px; line-height: 19px; color: var(--muted); }

/* The honeypot. Positioned off-screen rather than display:none, because some
   bots skip fields they can see are hidden. aria-hidden and tabindex keep it
   away from anyone filling the form in for real. */
.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form .button { border: 0; }

/* -------------------------------------------------------- contact details */

.contact-list { margin: 0; padding: 0; }
.contact-list > div { margin-bottom: 22px; }
.contact-list dt {
  margin-bottom: 4px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 13px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--purple);
}
.contact-list dd { margin: 0; }

/* ---------------------------------------------------------- footer (cont.) --
 *
 * A logo and a copyright line is all a one-page site needs. With six pages the
 * footer is also the second navigation, so it carries the link columns and the
 * details people look for at the bottom of a page rather than the top.
 */
/* Plum, not the theme's pale blue #ecf0fb. That color was a slightly different
   white from the page above it, so the site ended by fading out rather than
   closing. A dark footer gives the paper an edge to stop at. */
.site-footer {
  padding: 76px 0 30px;
  background: var(--bg-footer);
  color: var(--footer-text);
  text-align: left;
}

/* The logo is drawn in purple on transparent and disappears on plum. */
.site-footer .footer-about img {
  filter: brightness(0) invert(1);
  opacity: .92;
}

.footer-cols {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));
  gap: 40px;
  padding-bottom: 40px;
}

.site-footer img { margin: 0 0 16px; }

.footer-about p {
  max-width: 36ch;
  margin: 0 0 14px;
  font-family: "sofia-pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 15px;
  line-height: 23px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--footer-text);
}

.footer-col h2 {
  margin: 0 0 16px;
  font-family: "futura-pt-bold", "futura-pt", "Trebuchet MS", sans-serif;
  font-size: 12px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--orange);
}

.footer-col ul { margin: 0; padding: 0; list-style: none; }
.footer-col li { margin-bottom: 11px; color: var(--footer-text); }
.footer-col a,
.footer-about a {
  font-family: "sofia-pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 15px;
  line-height: 22px;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(255, 255, 255, .74);
}
.footer-col a:hover,
.footer-about a:hover { color: #fff; }

.footer-legal {
  padding-top: 24px;
  border-top: 1px solid rgba(255, 255, 255, .14);
  text-align: center;
}
.footer-legal p { color: rgba(255, 255, 255, .42); }

/* -------------------------------------------------- breakpoints (cont.) -- */

@media (max-width: 1000px) {
  .nav-cluster { gap: 10px; }
  .nav-cta { height: 36px; padding: 0 15px; line-height: 36px; }

  .page-hero { padding: 44px 0 40px; }
  .page-hero h1 { font-size: 32px; line-height: 36px; }
  .page-hero p { font-size: 17px; line-height: 26px; }

  .section h2 { font-size: 24px; line-height: 28px; }

  .split, .split--wide-text { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .split--art-first > :first-child { order: 0; }

  .footer-cols { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 32px; }

  .cta-band { padding: 28px 24px; }
  .cta-band p { font-size: 19px; line-height: 25px; }
}

@media (max-width: 620px) {
  /* Below this width the hamburger and the CTA together crowd the logo off the
     grid. The CTA goes, and every page still ends on one. */
  .nav-cta { display: none; }

  .footer-cols { grid-template-columns: minmax(0, 1fr); }
  .card-grid { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 14px; }
  .steps > li { padding-left: 52px; }
  .page-hero h1 { font-size: 28px; line-height: 32px; }
  .codeblock { padding: 18px 16px; font-size: 12px; }
}
