/* ==========================================================================
   Design Wall — designwallquilts.com
   Everything visual lives here. All the words live in content.json.

   Browser support: Chrome/Edge 90+, Firefox 90+, Safari 15+ (2021 onward).
   Nothing here needs a build step, a preprocessor or a polyfill.
   ========================================================================== */

/* --- tokens -------------------------------------------------------------- */
:root {
  /* the app icon's own two colour runs */
  --lime: #c9dd6d;  --green: #90df8e;  --mint: #53dbb2;  --turq: #1ad1d1;
  --orange: #fb7a39; --coral: #f75e50; --rose: #ed446b;  --magenta: #db2c87;
  --hearth: #720041;

  --ink: #341c35;
  --ink-70: rgba(52, 28, 53, .74);
  --ink-50: rgba(52, 28, 53, .54);
  --ink-12: rgba(52, 28, 53, .12);

  --calico: #f4f2ea;
  --paper: #fffdf7;
  --page: #faf8f2;
  --cream: #f4f2ea;

  --sash: 18px;              /* sashing width; the narrow field halves it */
  --wrap: 1180px;
  --radius: 0px;             /* piecing has no rounded corners. cards neither. */

  --shadow-card: 0 26px 62px rgba(52, 28, 53, .30);
  --shadow-lift: 0 20px 50px rgba(52, 28, 53, .18);

  --font: Outfit, "Avenir Next", "Segoe UI", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

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

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

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { margin: 0; letter-spacing: -.032em; line-height: 1; }
p { margin: 0; }
img { max-width: 100%; height: auto; display: block; }

a { color: var(--hearth); text-decoration: none; }
a:hover { color: var(--magenta); }

button, input { font: inherit; }

:focus-visible { outline: 3px solid var(--hearth); outline-offset: 2px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 20;
  background: var(--hearth); color: #fff; padding: 12px 18px; font-weight: 600;
}
.skip:focus { left: 0; color: #fff; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }
.mono { font-family: var(--mono); }

.eyebrow {
  font-family: var(--mono); font-weight: 500; font-size: 11px;
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-50);
}

.lede { font-size: 19px; line-height: 1.55; color: var(--ink-70); }

/* --- the app icon, drawn in CSS ------------------------------------------ */
.icon {
  position: relative; display: block; flex: 0 0 auto;
  width: 88px; height: 88px; border-radius: 19.5px; /* iOS squircle ≈ 22.4% */
  overflow: hidden; box-shadow: 0 8px 22px rgba(52, 28, 53, .28);
}
.icon i { position: absolute; display: block; }
/* The nav is now the only place the mark appears, so it carries a little more
   weight than a nav icon usually would. */
.icon-sm { width: 50px; height: 50px; border-radius: 11px; box-shadow: 0 3px 10px rgba(0, 0, 0, .28); }
.icon-xs { width: 28px; height: 28px; border-radius: 6.5px; box-shadow: none; }

/* --- pieced blocks -------------------------------------------------------- */
/* Each .blk is one quilt block: a ground (--g) and a patch colour (--a).
   The <i> children are the patches, cut with clip-path. */
.blk { position: relative; background: var(--g); }
.blk i { position: absolute; inset: 0; display: block; background: var(--a); }

.blk .hst { -webkit-clip-path: polygon(0 0, 100% 0, 0 100%); clip-path: polygon(0 0, 100% 0, 0 100%); }
.blk .q1  { -webkit-clip-path: polygon(0 0, 0 50%, 50% 50%); clip-path: polygon(0 0, 0 50%, 50% 50%); }
.blk .q2  { -webkit-clip-path: polygon(50% 0, 100% 0, 50% 50%); clip-path: polygon(50% 0, 100% 0, 50% 50%); }
.blk .q3  { -webkit-clip-path: polygon(0 100%, 0 50%, 50% 100%); clip-path: polygon(0 100%, 0 50%, 50% 100%); }
.blk .q4  { -webkit-clip-path: polygon(50% 50%, 100% 50%, 100% 100%); clip-path: polygon(50% 50%, 100% 50%, 100% 100%); }
.blk .dia { -webkit-clip-path: polygon(50% 8%, 92% 50%, 50% 92%, 8% 50%); clip-path: polygon(50% 8%, 92% 50%, 50% 92%, 8% 50%); }
.blk .g1  { -webkit-clip-path: polygon(50% 0, 100% 50%, 0 50%); clip-path: polygon(50% 0, 100% 50%, 0 50%); }
.blk .g2  { -webkit-clip-path: polygon(50% 50%, 100% 100%, 0 100%); clip-path: polygon(50% 50%, 100% 100%, 0 100%); }
.blk .qtr { -webkit-clip-path: circle(96% at 0 100%); clip-path: circle(96% at 0 100%); }

/* two-colour pinwheel, used for the sample quilts */
.blk .q2b { background: var(--b); -webkit-clip-path: polygon(50% 0, 100% 0, 50% 50%); clip-path: polygon(50% 0, 100% 0, 50% 50%); }
.blk .q4b { background: var(--b); -webkit-clip-path: polygon(50% 50%, 100% 50%, 100% 100%); clip-path: polygon(50% 50%, 100% 50%, 100% 100%); }

/* --- the sashed field ----------------------------------------------------- */
/* Sashing is part of the grid rather than a gap: odd tracks are blocks, even
   tracks are sashing. That makes cornerstones real cells, so nothing has to be
   positioned by hand and the whole field stays exact at any width. */
/* Track lists are written inline by build.mjs — see sashedField(). */
.field { display: grid; background: var(--page); }
.sash { background: var(--page); }
.stone { display: block; }

.field-narrow { display: none; }

/* --- nav ------------------------------------------------------------------ */
.nav { background: var(--hearth); }
.nav-inner { display: flex; align-items: center; gap: 24px; min-height: 92px; }
.brand { display: flex; align-items: center; gap: 14px; margin-right: auto; }
.brand:hover { color: inherit; }
.wordmark { font-weight: 800; letter-spacing: -.028em; }
.nav .wordmark { font-size: 27px; color: #fff; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  font-weight: 700; border: 0; cursor: pointer; text-align: center;
  min-height: 46px; padding: 0 24px; border-radius: 999px;
  transition: filter .15s ease;
}
.btn:hover { filter: brightness(1.06); }
.btn-lime { background: var(--lime); color: var(--ink); }
.btn-lime:hover { color: var(--ink); }
.btn-hearth { background: var(--hearth); color: #fff; }
.btn-hearth:hover { color: #fff; }
.btn-hearth[disabled] { opacity: .45; cursor: not-allowed; filter: none; }
.btn-store { background: var(--hearth); color: #fff; min-height: 58px; padding: 0 28px; }
.btn-store:hover { color: #fff; }
.btn-store span { display: flex; flex-direction: column; line-height: 1.15; text-align: left; }
.btn-store small { font-size: 11px; font-weight: 500; opacity: .8; }
.btn-store strong { font-size: 17.5px; font-weight: 700; }

/* --- hero ----------------------------------------------------------------- */
.hero { position: relative; background: var(--page); padding: var(--sash) 0; }
.hero .field-wide { height: 720px; }
.hero-wrap { position: absolute; inset: 0; display: flex; align-items: center; }

.card { background: var(--paper); padding: 50px 46px; box-shadow: var(--shadow-card); }
.hero-card { width: min(630px, 100%); display: flex; flex-direction: column; gap: 22px; }
.hero-card h1 { font-weight: 800; font-size: clamp(34px, 4.4vw, 58px); line-height: .98; text-wrap: balance; }

/* The identity lives in the nav bar and nowhere else on the page. What sits
   above the headline is the tagline alone — it says what the product is,
   which the wordmark does not. */
.hero-kicker { color: var(--hearth); margin-bottom: -8px; }

.hero-cta { display: flex; flex-direction: column; gap: 10px; }
.hero-cta-row { flex-direction: row; align-items: center; gap: 18px; flex-wrap: wrap; }

.capture-heading { font-weight: 700; font-size: 19px; letter-spacing: -.02em; }
.capture-body { font-size: 16px; line-height: 1.5; color: var(--ink-70); }
.capture { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 4px; }
.capture-field {
  flex: 1 1 240px; min-height: 46px; padding: 0 16px;
  border: 1px solid var(--ink-12); border-radius: 999px;
  background: #fff; color: var(--ink);
}
.capture-field::placeholder { color: var(--ink-50); }
.capture-field[disabled] { background: rgba(52, 28, 53, .05); cursor: not-allowed; }
.capture-note { font-family: var(--mono); font-size: 11px; color: var(--ink-50); }

.rating { display: flex; flex-direction: column; gap: 4px; }
.stars { display: flex; gap: 3px; }
.stars span {
  width: 16px; height: 16px; background: var(--orange);
  -webkit-clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}
.rating-num { font-weight: 700; font-size: 14.5px; }
.rating-note { font-family: var(--mono); font-size: 10.5px; color: var(--ink-50); }

/* --- the app, lifted off the piecing -------------------------------------- */
.device-band { background: var(--page); padding: 64px 0 88px; }
.device {
  max-width: 960px; margin: 0 auto; background: #241226; padding: 13px;
  border-radius: 26px; box-shadow: 0 34px 76px rgba(52, 28, 53, .32);
}
.device-bar {
  background: #ece9e0; border-radius: 14px 14px 0 0; padding: 12px 16px;
  font-weight: 600; font-size: 13px;
}
.device-empty .quilt { border-radius: 0 0 14px 14px; overflow: hidden; }
.device-note {
  margin-top: 12px; color: rgba(255, 255, 255, .72); font-size: 13px;
  display: flex; flex-direction: column; gap: 4px; padding: 0 4px 4px;
}
.device-note em { font-family: var(--mono); font-size: 10.5px; color: rgba(255, 255, 255, .48); font-style: normal; }

/* --- sample quilts -------------------------------------------------------- */
.quilt { display: grid; grid-template-columns: repeat(var(--cols), 1fr); }
.quilt .blk { aspect-ratio: 1 / 1; }
.demo { transition: filter .3s ease; }
.demo.is-value { filter: grayscale(1) contrast(1.02); }

/* --- feature slots -------------------------------------------------------- */
.slot { padding: 88px 0; }
.slot-1 { background: var(--turq); }
.slot-2 { background: var(--lime); }
.slot-3 { background: var(--magenta); }
.slot-3 h2, .slot-3 .lede { color: #fff; }
.slot-3 .eyebrow { color: rgba(255, 255, 255, .75); }

.slot-inner { display: flex; gap: 60px; align-items: center; }
.slot-2 .slot-inner { flex-direction: row-reverse; }
.slot-text { flex: 0 0 452px; display: flex; flex-direction: column; gap: 18px; }
.slot-text h2 { font-weight: 800; font-size: clamp(30px, 3.6vw, 52px); text-wrap: balance; }
.slot-text .lede { color: rgba(52, 28, 53, .82); }
.slot-figure { flex: 1 1 auto; min-width: 0; }

.panel { background: var(--paper); padding: 26px; box-shadow: var(--shadow-lift); }

.toggle {
  display: inline-flex; padding: 4px; border-radius: 999px;
  background: rgba(52, 28, 53, .12); margin-bottom: 18px;
}
.toggle button {
  min-height: 42px; padding: 0 24px; border: 0; border-radius: 999px;
  background: transparent; color: var(--ink-70); font-weight: 600; cursor: pointer;
}
.toggle button.is-on { background: var(--paper); color: var(--ink); }

.caption { margin-top: 16px; font-size: 15px; line-height: 1.55; font-weight: 500; color: var(--ink-70); min-height: 3em; }

/* the cutting chart */
.chart { padding: 0; }
.chart-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 16px 20px; background: #ece9e0; font-weight: 600; font-size: 13px;
}
.chart-head .mono { font-size: 10.5px; color: var(--ink-50); font-weight: 500; }
.chart-row {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 15px 20px; border-bottom: 1px solid rgba(52, 28, 53, .07);
}
.chip { width: 26px; height: 26px; flex: 0 0 auto; border: 1px solid var(--ink-12); }
.chart-unit { flex: 1 1 160px; font-weight: 500; font-size: 14.5px; }
.chart-rule { font-size: 11.5px; color: var(--ink-50); }
.chart-cut { font-size: 14.5px; font-weight: 500; margin-left: auto; }
.chart-foot { padding: 14px 20px; font-size: 10.5px; color: var(--ink-50); background: rgba(52, 28, 53, .035); }

/* screenshot placeholders */
.shot-empty {
  display: flex; flex-direction: column; justify-content: center; gap: 10px;
  aspect-ratio: 3 / 2; padding: 28px; text-align: center;
  border: 2px dashed rgba(114, 0, 65, .3); color: var(--ink-70);
}
.shot-empty em { font-family: var(--mono); font-size: 11px; font-style: normal; color: var(--ink-50); }

/* --- proof ---------------------------------------------------------------- */
.proof { background: var(--hearth); padding: 72px 0; }
.proof-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 36px; }
.proof-num { font-weight: 800; font-size: clamp(38px, 3.8vw, 52px); letter-spacing: -.04em; line-height: 1; }
.proof-label { margin-top: 9px; font-size: 14.5px; line-height: 1.45; color: rgba(255, 255, 255, .8); }

/* --- closing -------------------------------------------------------------- */
.closing { position: relative; background: var(--page); padding: var(--sash) 0; }
.closing .field-wide { height: 560px; }
.closing-wrap { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.closing-card {
  width: min(700px, 100%); display: flex; flex-direction: column;
  align-items: center; gap: 20px; text-align: center;
}
.closing-card h2 { font-weight: 800; font-size: clamp(30px, 3.8vw, 52px); text-wrap: balance; }
.closing-card .lede { max-width: 470px; }
.closing-cta { display: flex; flex-direction: column; align-items: center; gap: 10px; width: 100%; }
.closing-cta .capture { justify-content: center; max-width: 460px; width: 100%; }
.closing-note { font-family: var(--mono); font-size: 11.5px; color: var(--ink-50); }

/* --- footer --------------------------------------------------------------- */
.foot { background: var(--ink); padding: 44px 0; }
.foot-inner { display: flex; align-items: center; gap: 32px; flex-wrap: wrap; }
.foot-brand { display: flex; align-items: center; gap: 11px; margin-right: auto; }
.foot-words { display: flex; flex-direction: column; gap: 2px; }
.foot .wordmark { font-size: 16px; color: var(--calico); }
.foot-domain { font-size: 10.5px; color: rgba(244, 242, 234, .52); }
.foot-links { display: flex; gap: 26px; flex-wrap: wrap; font-size: 14px; }
.foot-links a { color: rgba(244, 242, 234, .7); }
.foot-links a:hover { color: #fff; }
.foot-copy { font-size: 11px; color: rgba(244, 242, 234, .45); }

/* ==========================================================================
   Responsive. Three steps: the card stops floating over the piecing, the
   slots stack, then everything goes single column.
   ========================================================================== */

@media (max-width: 1080px) {
  .hero .field-wide { height: 620px; }
  .slot-text { flex-basis: 380px; }
  .slot-inner { gap: 40px; }
}

@media (max-width: 900px) {
  /* The hero card stops being an overlay and sits under a shallow band of
     piecing. Absolute positioning over a field is a desktop luxury. */
  .hero, .closing { padding: 0; }
  .hero .field-wide, .closing .field-wide { display: none; }
  .field-narrow { display: grid; height: 220px; --sash: 10px; }
  .hero-wrap, .closing-wrap { position: static; display: block; padding-top: 0; }
  /* No negative margin here. Overlapping the field is a desktop move: at this
     size the card's top edge slices the bottom row of blocks in half, which
     reads as a rendering fault rather than as depth. Flush is deliberate. */
  .hero-card, .closing-card { width: auto; margin: 0 24px 48px; padding: 36px 28px; }
  .closing-card { margin-bottom: 0; }
  .closing { padding-bottom: 56px; }
  .wrap.hero-wrap, .wrap.closing-wrap { padding: 0; }

  .slot { padding: 64px 0; }
  .slot-inner, .slot-2 .slot-inner { flex-direction: column; align-items: stretch; gap: 32px; }
  .slot-text { flex-basis: auto; }

  .proof-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; }
  .device-band { padding: 40px 0 64px; }
}

/* --- phones --------------------------------------------------------------
   The band of piecing gets SHORTER and its blocks get SMALLER, not bigger.
   Three fat blocks read as three random shapes; twelve small ones read as a
   quilt. Same rule the brand package gives for the wall — what makes a woven
   field look like cloth is how many repetitions are in view, not how large
   each one is. The band is decoration, and it must not push the headline off
   the first screen. */
@media (max-width: 560px) {
  body { font-size: 16px; }
  .lede { font-size: 17px; }

  .nav-inner { min-height: 64px; gap: 12px; }
  .nav .wordmark { font-size: 19px; }
  .icon-sm { width: 34px; height: 34px; border-radius: 7.5px; }
  .btn { padding: 0 18px; font-size: 15px; min-height: 44px; }

  /* Height is chosen so the blocks come out square at a typical phone width:
     6 columns and a 6px sash across ~400px gives a ~62px block, so two rows
     plus one sash is ~130. */
  .field-narrow { height: 130px; --sash: 6px; }

  .hero-card, .closing-card { margin: 0 14px 36px; padding: 26px 20px; gap: 16px; }
  .hero-card h1 { overflow-wrap: break-word; }
  .hero-kicker { letter-spacing: .14em; }

  .wrap { padding: 0 16px; }
  .panel { padding: 16px; }
  .chart-row { gap: 10px; padding: 13px 16px; }
  .chart-rule { display: none; }          /* the rule column is the first to go */
  .chart-head, .chart-foot { padding: 13px 16px; }
  .chart-head { font-size: 12px; }

  .device { padding: 8px; border-radius: 18px; }
  .device-bar { padding: 10px 12px; font-size: 12px; border-radius: 10px 10px 0 0; }
  .device-note { font-size: 12px; }

  /* Touch targets. A 20px-tall link is a coin toss with a thumb, so the footer
     links and the toggle get real height here even though they look fine on a
     mouse. 44px is Apple's floor, not a target. */
  .toggle button { min-height: 44px; }
  .foot-links a { display: inline-flex; align-items: center; min-height: 44px; }

  /* The smallest labels come up a little. The mono kicker stays small on
     purpose — it is the brand's own section-label style — but 9.5px of
     letterspaced caps is asking a lot of a phone. */
  .chart-foot, .foot-domain { font-size: 11.5px; }
  .chart-head .mono { font-size: 11px; }

  .proof { padding: 56px 0; }
  .proof-grid { grid-template-columns: 1fr; gap: 24px; }
  .foot { padding: 36px 0; }
  .foot-inner { gap: 16px; }
  .foot-links { gap: 4px 20px; font-size: 14px; }

  /* Once the form stacks, the main axis is vertical — so flex-basis would be
     read as a HEIGHT and blow the field up to 240px tall. Reset it. */
  .capture { flex-direction: column; }
  .capture-field, .capture .btn { flex: 0 0 auto; width: 100%; }
}

/* Small phones — iPhone SE is 375, the 12/13 mini 360. */
@media (max-width: 400px) {
  .hero-card, .closing-card { margin-left: 10px; margin-right: 10px; padding: 22px 18px; }
  .wrap { padding: 0 12px; }
  .field-narrow { height: 120px; }
  .nav .wordmark { font-size: 18px; }
  .icon-sm { width: 32px; height: 32px; border-radius: 7px; }
}

/* --- respect the reader --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

@media print {
  .nav, .field, .toggle, .skip { display: none; }
  body { background: #fff; }
  .card { box-shadow: none; border: 1px solid #ccc; }
}
