/* ============================================================================
   getristra.com: the site's own layer over the Bold & Strung kit.

   kit/tokens.css and kit/kit.css are Graft's kit, copied byte for byte by
   scripts/kit.mjs: never edit them here. This file adds only what the kit
   has no part for: the wordmark, the header and footer, the phone frame, the
   feature cards' mini-UIs, the screenshot row and the name story. Every color
   is a kit role (var(--bb-*)): scripts/kit.mjs check fails on a raw color or
   on a variable nothing defines, and the deploy runs it. README, "The kit".
   ========================================================================= */

@font-face {
  font-family: "Solitreo";
  src: url("/fonts/Solitreo-latin.woff2") format("woff2");
  font-display: swap;
}

body {
  margin: 0;
}

/* Symbol sheets (the mark) are drawn where they are used. */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* The app's Font Awesome Sharp glyphs (icons/ristra-icons.svg) are filled
   shapes, so they take the text color as a fill; the kit's .bb-icon strokes. */
.glyph {
  flex: none;
  width: 1em;
  height: 1em;
  fill: currentColor;
}

/* ---- Wordmark, header, footer ------------------------------------------------ */

/* Solitreo sets the wordmark and nothing else (design.getristra.com,
   "Wordmark & tagline"). */
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--bb-ink);
  font: 400 1.75rem / 1 "Solitreo", cursive;
  text-decoration: none;
}

.wordmark img {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 0.55rem;
}

.wordmark--sm {
  font-size: 1.3rem;
}

.wordmark--sm img {
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 0.45rem;
}

.site-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
}

.site-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
}

.site-link {
  color: var(--bb-link);
  font-weight: var(--bb-weight-strong);
  text-decoration: none;
}

.site-link:hover {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.3em;
}

/* Home: the header lies over the chili hero, so the hero's orbs run behind it
   uncut. Inner pages: a short chili band of its own. */
.site-head {
  position: absolute;
  inset: 0 0 auto;
  z-index: 2;
  padding-block: 1.25rem;
}

.site-band {
  padding-block: 1.25rem;
}

/* On a phone the header keeps one row: the text links are in the footer too. */
@media (max-width: 40rem) {
  .site-head .site-link,
  .site-band .site-link {
    display: none;
  }
}

.site-foot {
  padding-block: 2.5rem 3rem;
}

.site-foot p {
  margin: 0;
}

/* ---- Hero -------------------------------------------------------------------- */

.hero {
  padding-block-start: calc(var(--bb-field-pad) + 3rem);
}

/* The kit's display size, held to the screen's width on phones so the stepped
   line ("aisle by aisle.") stays one line down to 320px. */
.hero h1 {
  font-size: min(var(--bb-display-xl), 12.5vw);
}

.hero-grid {
  display: grid;
  gap: clamp(3rem, 6vw, 4.5rem);
  align-items: center;
}

@media (min-width: 75rem) {
  .hero-grid {
    grid-template-columns: minmax(0, 1fr) auto;
  }
}

.as-glyph {
  flex: none;
  width: 1.1em;
  height: 1.1em;
  fill: currentColor;
}

/* The phone: a real capture in a bezel of the field's raised color, set down
   at the kit's nudge angle. The image carries its 1320:2868 ratio through its
   width and height and the bezel wraps it: an aspect-ratio here would count
   the border (marketing/capture/verify-site.mjs checks the fit to 0.5px). */
.phone {
  justify-self: center;
  width: clamp(15rem, 23vw, 17.25rem);
  overflow: hidden;
  border: 9px solid var(--bb-raised);
  border-radius: 2.6rem;
  background: var(--bb-raised);
  transform: var(--bb-pose-nudge);
}

.phone picture,
.phone img {
  display: block;
}

.phone img {
  width: 100%;
  height: auto;
}

/* ---- Features ------------------------------------------------------------------ */

.feature-grid {
  display: grid;
  gap: 3.25rem clamp(1.25rem, 2.5vw, 2rem);
  margin: 0;
  padding: 1.75rem 0 0;
  list-style: none;
}

@media (min-width: 40rem) {
  .feature-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .feature:last-child {
    grid-column: 1 / -1;
  }
}

/* Three, then two wider. */
@media (min-width: 64rem) {
  .feature-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .feature {
    grid-column: span 2;
  }

  .feature:nth-child(n + 4),
  .feature:last-child {
    grid-column: span 3;
  }
}

/* A raised card the kit's tag overhangs: the quote card's geometry, for a feature. */
.feature {
  position: relative;
  display: grid;
  align-content: start;
  gap: 1rem;
  padding: 3rem clamp(1.25rem, 3vw, 2rem) 2rem;
  border-radius: var(--bb-radius-card);
}

.feature p {
  margin: 0;
}

/* ---- Tour art --------------------------------------------------------------------- */

/* Each feature card draws the app's own Tour art (src/components/Tour.svelte in the app
   repo: steps add, stores, share, swipe and photo), redrawn here as live SVG with the
   same shapes, glyphs, type and swipe animation. The colors are the app's tokens for
   that art, resolved to the same Ristra ramp steps the app uses (ristra-design
   semantics) through the kit's color tokens; where the app uses an off-ramp tone, the
   nearest step stands in, noted inline. The app repo's tests/siteTourArt.test.mjs fails
   when the Tour's art changes, so this copy is redrawn in the same pass. */
:root {
  --art-bg: var(--bb-color-earth-50);
  --art-surface: var(--bb-color-white);
  --art-sunken: var(--bb-color-earth-100);
  --art-border: var(--bb-color-earth-200);
  --art-separator: color-mix(in srgb, var(--art-border) 60%, var(--art-surface));
  --art-text: var(--bb-color-earth-900);
  --art-muted: var(--bb-color-earth-700); /* the app's is #77695b, between steps */
  --art-accent: var(--bb-color-terra-600);
  --art-accent-strong: var(--bb-color-terra-700);
  --art-on-accent: var(--bb-color-white);
  --art-title: var(--bb-color-turquoise-500);
  --art-pill: var(--bb-color-earth-100);
  --art-incart: var(--bb-color-turquoise-700);
  --art-finish: var(--bb-color-turquoise-600);
  --art-on-finish: var(--bb-color-white);
  --art-got: var(--bb-color-turquoise-600);
  --art-skip: var(--bb-color-ochre-600);
  --art-delete: var(--bb-color-terra-600);
  --art-lift-ink: var(--bb-color-earth-950);
  --art-lift-near: 0.09;
  --art-lift-far: 0.07;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --art-bg: var(--bb-color-earth-975);
    --art-surface: var(--bb-color-earth-950);
    --art-sunken: var(--bb-color-earth-975); /* the app's is #18130d */
    --art-border: var(--bb-color-earth-800); /* the app's is #3f362d */
    --art-separator: var(--art-border);
    --art-text: var(--bb-color-earth-100);
    --art-muted: var(--bb-color-earth-300);
    --art-accent: var(--bb-color-terra-400);
    --art-accent-strong: var(--bb-color-terra-300);
    --art-on-accent: var(--bb-color-earth-975);
    --art-title: var(--bb-color-turquoise-300);
    --art-pill: var(--bb-color-earth-900); /* the app's is #352c23 */
    --art-incart: var(--bb-color-turquoise-400);
    --art-finish: var(--bb-color-turquoise-400);
    --art-on-finish: var(--bb-color-earth-975);
    --art-lift-ink: var(--bb-color-earth-975); /* the app's is black */
    --art-lift-near: 0.45;
    --art-lift-far: 0.38;
  }
}

:root[data-theme="dark"] {
  --art-bg: var(--bb-color-earth-975);
  --art-surface: var(--bb-color-earth-950);
  --art-sunken: var(--bb-color-earth-975);
  --art-border: var(--bb-color-earth-800);
  --art-separator: var(--art-border);
  --art-text: var(--bb-color-earth-100);
  --art-muted: var(--bb-color-earth-300);
  --art-accent: var(--bb-color-terra-400);
  --art-accent-strong: var(--bb-color-terra-300);
  --art-on-accent: var(--bb-color-earth-975);
  --art-title: var(--bb-color-turquoise-300);
  --art-pill: var(--bb-color-earth-900);
  --art-incart: var(--bb-color-turquoise-400);
  --art-finish: var(--bb-color-turquoise-400);
  --art-on-finish: var(--bb-color-earth-975);
  --art-lift-ink: var(--bb-color-earth-975);
  --art-lift-near: 0.45;
  --art-lift-far: 0.38;
}

/* The Tour's art slot: a sunken panel at the art's own 376:150, which the SVG fills. */
.tour-art {
  overflow: hidden;
  aspect-ratio: 376 / 150;
  margin-bottom: 0.5rem;
  border-radius: 16px;
  background: var(--art-sunken);
}

/* overflow: visible lets the stores step's lift shadow paint past the lifted group. */
.tour-art > svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* geometricPrecision: WebKit otherwise lays SVG text out at the scaled size, so its
   width moves with the zoom (measured in the app's Tour; see Tour.svelte). */
.tour-art text {
  font-family: inherit;
  text-rendering: geometricPrecision;
}

.tour-art .surface { fill: var(--art-surface); }
.tour-art .sunken { fill: var(--art-sunken); }
.tour-art .accent { fill: var(--art-accent); }
.tour-art .finish { fill: var(--art-finish); }
.tour-art .pill { fill: var(--art-pill); }
.tour-art .got { fill: var(--art-got); }
.tour-art .skip { fill: var(--art-skip); }
.tour-art .delete { fill: var(--art-delete); }
.tour-art .lift-card { fill: var(--art-bg); stroke: var(--art-border); }

/* Glyphs: the app's Sharp symbols from icons/ristra-icons.svg. The sprite's paths fill
   with currentColor, so each role sets color (an inherited fill would be ignored). */
.tour-art .g-muted { color: var(--art-muted); }
.tour-art .g-accent { color: var(--art-accent); }
.tour-art .g-incart { color: var(--art-incart); }
.tour-art .g-on-accent { color: var(--art-on-accent); }
.tour-art .g-title { color: var(--art-title); }
.tour-art .g-text { color: var(--art-text); }
.tour-art .g-got { color: var(--art-got); }
.tour-art .g-skip { color: var(--art-skip); }
.tour-art .g-delete { color: var(--art-delete); }

/* Type, as the Tour sets it. Every label clears 4.5:1 in both themes. */
.tour-art .head { font-size: 12.5px; font-weight: 700; fill: var(--art-text); }
.tour-art .name { font-size: 14.5px; font-weight: 500; fill: var(--art-text); }
.tour-art .name.small { font-size: 13.5px; }
.tour-art .note { font-size: 13px; fill: var(--art-muted); }
.tour-art .italic { font-style: italic; }
.tour-art .lens { font-size: 13px; font-weight: 600; fill: var(--art-text); }
.tour-art .change { font-size: 13px; font-weight: 700; fill: var(--art-accent-strong); }
.tour-art .initial { font-size: 17px; font-weight: 700; }
.tour-art .on-accent { fill: var(--art-on-accent); }
.tour-art .on-finish { fill: var(--art-on-finish); }

.tour-art .link { fill: none; stroke: var(--art-accent); stroke-width: 1.8; stroke-dasharray: 4 4; stroke-linecap: round; }
.tour-art .frame { fill: none; stroke: var(--art-muted); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.tour-art .sep { stroke: var(--art-separator); stroke-width: 1; }

/* The arrowhead lives in the page's symbol sheet, so it reads the art tokens from :root. */
.arrowhead { fill: none; stroke: var(--art-accent); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* The stores step: the lifted Bakery aisle, nudged, tilted and shadowed. A url()
   filter, because WebKit never painted a CSS drop-shadow() on this nested group
   (measured in the app's Tour). */
.tour-art .lifted {
  transform: translate(6px, -2px) rotate(-1.2deg);
  transform-origin: 188px 65px;
  filter: url(#tour-lift);
}

.tour-art .lift-near { flood-color: var(--art-lift-ink); flood-opacity: var(--art-lift-near); }
.tour-art .lift-far { flood-color: var(--art-lift-ink); flood-opacity: var(--art-lift-far); }

/* The swipe step plays the Tour's loop: Milk out to Got It and back, then Paper towels
   out to Delete and Skip It and back. The touch dot is the finger. */
.tour-art .fade-edge { fill: url(#tour-fade-left); }
.tour-art .fade-from { stop-color: var(--art-surface); stop-opacity: 1; }
.tour-art .fade-to { stop-color: var(--art-surface); stop-opacity: 0; }
.tour-art .touch { fill: var(--art-text); opacity: 0; }
.tour-art .swipe-got { animation: tour-swipe-got 5s var(--ease-out) infinite; }
.tour-art .swipe-skip { animation: tour-swipe-skip 5s var(--ease-out) infinite; }
.tour-art .zone-got { animation: tour-zone-got 5s linear infinite; }
.tour-art .zone-skip { animation: tour-zone-skip 5s linear infinite; }
.tour-art .swipe-got .touch { animation: tour-touch-got 5s linear infinite; }
.tour-art .swipe-skip .touch { animation: tour-touch-skip 5s linear infinite; }

@keyframes tour-swipe-got {
  0%, 8% { transform: translateX(0); }
  20%, 40% { transform: translateX(76px); }
  50%, 100% { transform: translateX(0); }
}

@keyframes tour-swipe-skip {
  0%, 52% { transform: translateX(0); }
  64%, 84% { transform: translateX(-152px); }
  94%, 100% { transform: translateX(0); }
}

@keyframes tour-zone-got {
  0%, 7.9% { opacity: 0; }
  8%, 49.9% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

@keyframes tour-zone-skip {
  0%, 51.9% { opacity: 0; }
  52%, 93.9% { opacity: 1; }
  94%, 100% { opacity: 0; }
}

@keyframes tour-touch-got {
  0%, 5% { opacity: 0; }
  8%, 20% { opacity: 0.18; }
  25%, 100% { opacity: 0; }
}

@keyframes tour-touch-skip {
  0%, 49% { opacity: 0; }
  52%, 64% { opacity: 0.18; }
  69%, 100% { opacity: 0; }
}

/* Reduced motion: the Tour's still frame, both swipes open and the finger shown. */
@media (prefers-reduced-motion: reduce) {
  .tour-art .swipe-got,
  .tour-art .swipe-skip,
  .tour-art .zone-got,
  .tour-art .zone-skip,
  .tour-art .touch {
    animation: none;
  }

  .tour-art .swipe-got { transform: translateX(76px); }
  .tour-art .swipe-skip { transform: translateX(-152px); }
  .tour-art .touch { opacity: 0.18; }
}

/* ---- Screenshots ------------------------------------------------------------------ */

/* The five light captures set down in a row. The row scrolls sideways with snap;
   its inset lines the first shot up with the kit's wrap, and its padding keeps
   the turned corners inside the scroller. */
.shots-field {
  padding-block: clamp(3rem, 2rem + 4vw, 5.5rem);
}

.shots {
  --inset: max(var(--bb-gutter), calc((100vw - var(--bb-wrap)) / 2 + var(--bb-gutter)));
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--inset);
  overscroll-behavior-x: contain;
}

.shots-list {
  display: flex;
  gap: clamp(1.25rem, 2.5vw, 2rem);
  width: max-content;
  margin: 0;
  padding: 1.5rem var(--inset) 2rem;
  list-style: none;
}

.shots-list > li {
  scroll-snap-align: start;
}

.shots figure {
  width: 15.5rem;
  margin: 0;
}

.shots picture {
  display: block;
}

.shots img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--bb-radius-card);
}

.shots figcaption {
  margin-top: 0.9rem;
  font-weight: var(--bb-weight-strong);
  line-height: 1.35;
  text-wrap: pretty;
}

@media (max-width: 40rem) {
  .shots figure {
    width: 13.75rem;
  }
}

/* ---- Name story ------------------------------------------------------------------ */

.story-grid {
  display: grid;
  gap: 2rem 3rem;
  align-items: center;
}

.ristra-vertical {
  display: none;
  width: 6.5rem;
  color: var(--bb-accent);
}

@media (min-width: 48rem) {
  .story-grid {
    grid-template-columns: 7.5rem minmax(0, 1fr);
  }

  .ristra-vertical {
    display: block;
  }
}

/* ---- Privacy and support ----------------------------------------------------------- */

/* The text starts on the home page's column and keeps a reading width
   (verify-site.mjs checks the left edge against the home page's .bb-wrap). */
.page-body {
  max-width: var(--bb-measure-wide);
}

.page-body > * {
  margin: 0;
}

.page-body h2 {
  margin-top: 1.25rem;
}

.page-body ul {
  display: grid;
  gap: 0.6rem;
  padding-inline-start: 1.25rem;
}

.page-body a {
  color: var(--bb-link);
  font-weight: var(--bb-weight-strong);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.2em;
}

/* ---- Dark theme seams ---------------------------------------------------------- */

/* In the dark theme, day turns earth 975, which sits 1.15:1 against night's
   earth 950: the lower field draws its line across the seam (Saturday Sort
   hit the same). Only siblings are caught, so check both themes after any
   layout change that nests fields. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .bb-field-day + .bb-field-night,
  :root:not([data-theme="light"]) .bb-field-night + .bb-field-day {
    box-shadow: inset 0 2px 0 var(--bb-line);
  }
}

:root[data-theme="dark"] .bb-field-day + .bb-field-night,
:root[data-theme="dark"] .bb-field-night + .bb-field-day {
  box-shadow: inset 0 2px 0 var(--bb-line);
}
