/* ==========================================================================
   Anastasiia's Bakery — shared stylesheet
   1. Design tokens
   2. Reset & base
   3. Typography
   4. Layout helpers
   5. Buttons
   6. Header & navigation
   7. Footer
   8. Floating chat button
   9. Hero banner
   10. Welcome (two-column)
   11. Image cards
   12. Our Work / Instagram feed
   13. Menu page
   14. Coming soon hero
   15. Contact page
   16. Success modal
   17. Responsive
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design tokens
   -------------------------------------------------------------------------- */

:root {
  /* Palette */
  --bg-pink: #f7ebed;
  --accent-mauve: #d3b3b8;
  --accent-rose: #e8cfd3;
  --accent-deep: #998184;
  /* Darker mauve for small text on white and #f7ebed. #998184 is 3.1:1 there. */
  --deep-dark: #7a6265;
  --text-dark: #2b2b2b;
  --white: #ffffff;
  --footer-dark: #2b2626;

  /* Type stacks */
  --font-heading: "Didot", "Playfair Display", serif;
  --font-body: "Avenir", "Nunito Sans", sans-serif;

  /* Rhythm */
  --content-max: 1200px;
  --panel-inset: 40px;
  --section-gap: 40px;
  --header-height: 112px;

  /* Effects */
  --shadow-soft: 0 6px 20px rgba(43, 38, 38, 0.12);
  --transition: 0.25s ease;
}

/* --------------------------------------------------------------------------
   2. Reset & base
   -------------------------------------------------------------------------- */

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

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

body {
  margin: 0;
  background-color: var(--white);
  color: var(--text-dark);
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 1rem;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

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

/* Visible only to screen readers. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   3. Typography
   -------------------------------------------------------------------------- */

h1,
h2,
h3,
h4 {
  margin: 0 0 0.6em;
  font-family: var(--font-heading);
  font-weight: 400;
  line-height: 1.2;
  color: var(--text-dark);
}

h1 {
  font-size: clamp(2.25rem, 5vw, 3.5rem);
  letter-spacing: 0.08em;
}

h2 {
  font-size: clamp(1.75rem, 3.5vw, 2.5rem);
  letter-spacing: 0.08em;
}

h3 {
  font-size: clamp(1.25rem, 2.2vw, 1.5rem);
  letter-spacing: 0.06em;
}

h4 {
  font-size: 1.125rem;
  letter-spacing: 0.05em;
}

p {
  margin: 0 0 1.25em;
  font-size: calc(1rem + 2px);
}

p:last-child {
  margin-bottom: 0;
}

/* Underlined heading treatment, applied per page spec. */
.is-underlined {
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-thickness: 1px;
}

/* Serif body copy, for pages that call for it. */
.text-serif {
  font-family: var(--font-heading);
  font-weight: 400;
}

.text-center {
  text-align: center;
}

.eyebrow {
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--deep-dark);
}

/* --------------------------------------------------------------------------
   4. Layout helpers
   -------------------------------------------------------------------------- */

.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.page__main {
  flex: 1 0 auto;
  padding-bottom: var(--section-gap);
}

/* The single source of vertical rhythm between sections, on every page.
   Sections must not carry their own top/bottom margins or the gaps drift.
   .section-stack applies the same rhythm to sections nested inside a panel. */
.page__main > * + *,
.section-stack > * + * {
  margin-top: var(--section-gap);
}

/* Centred content column. */
.container {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: 24px;
}

/* Soft-pink panel, inset horizontally only — vertical space between sections
   comes from --section-gap so the rhythm stays uniform. */
.panel {
  background-color: var(--bg-pink);
  margin-inline: var(--panel-inset);
  padding: clamp(40px, 6vw, 88px) 0;
  border-radius: 15px;
}

.panel--flush {
  margin-inline: 0;
}

/* Centred body column for the interior pages. */
.prose {
  max-width: 760px;
  margin-inline: auto;
  text-align: center;
}

/* Narrower measure, for prose sitting in one half of a .split. */
.prose--narrow {
  max-width: 560px;
}

/* Story heading only: centered in the text column. Body copy keeps its own alignment. */
.story-copy > h1 {
  text-align: center;
}

/* The global reset strips link styling so nav items and cards stay clean, but
   a link inside body copy still has to look clickable. */
.prose a {
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--transition);
}

.prose a:hover,
.prose a:focus-visible {
  color: var(--deep-dark);
}

/* Two equal columns that stack on mobile. */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
}

/* Source order stays image-then-text so the mobile stack matches. On wide
   screens the image moves to the right column. */
.split--swap .split__media {
  order: 2;
}

/* Tower only. The shared narrow rule sizes by width, which makes this taller
   portrait larger than the cube cake. At a 1280px desktop the cube cake image
   renders 483px tall (75% of the column × its 1873/1600 ratio). Cap the tower
   to that same height and let the width follow, centred in the column. */
.split__media--tower {
  container-type: inline-size;
}

.split__media--narrow img.macaron-tower {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: calc(75cqi * 1873 / 1600);
  margin-inline: auto;
  aspect-ratio: 2 / 3;
}

.split__media img {
  width: 100%;
  height: auto;
  border-radius: 15px;
}

/* Three-quarter width image, still centred in its column. */
.split__media--narrow img {
  width: 75%;
  margin-inline: auto;
}

/* Portrait frame, centred in its column. The ratio matches the 2:3 source so
   nothing is cropped today; object-fit keeps the frame stable if the photo is
   ever swapped for one shot at a different ratio. */
.split__media--portrait img {
  max-width: 500px;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  margin-inline: auto;
}

/* Same rhythm as --section-gap, for a block nested inside a section. */
.section-gap-top {
  margin-top: var(--section-gap);
}

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-block;
  padding: 14px 34px;
  background-color: var(--accent-mauve);
  /* Dark text on the mauve fill is 7.4:1. White on this fill is 1.9:1. */
  color: var(--text-dark);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-align: center;
  border-radius: 2px;
  transition: background-color var(--transition), color var(--transition);
}

.btn:hover,
.btn:focus-visible {
  /* #998184 with this dark text is 3.9:1. #a89094 is the same deeper mauve,
     lightened just enough to clear 4.5:1. */
  background-color: #a89094;
  color: var(--text-dark);
}

/* Set while a form post is in flight, to block a double submission. */
.btn[disabled],
.text-button[disabled] {
  opacity: 0.6;
  cursor: default;
}

.btn--outline {
  background-color: transparent;
  color: var(--text-dark);
  border: 1px solid var(--accent-mauve);
}

.btn--outline:hover,
.btn--outline:focus-visible {
  background-color: var(--accent-rose);
  color: var(--text-dark);
}

/* White serif label plate, used for the home cards and the Instagram CTA. */
.label-button {
  display: inline-block;
  padding: 12px 40px;
  background-color: var(--white);
  color: var(--text-dark);
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: 400;
  letter-spacing: 0.06em;
  line-height: 1.4;
  text-align: center;
  border: 1px solid rgba(43, 43, 43, 0.25);
  transition: background-color var(--transition);
}

.label-button:hover,
.label-button:focus-visible {
  background-color: var(--accent-rose);
}

/* 1.5x the base plate, for a standalone call to action. Eases down on narrow
   phones, where the full size would be wider than the screen. */
.label-button--lg {
  padding: 18px clamp(24px, 7vw, 60px);
  font-size: clamp(1.125rem, 5.5vw, 1.5rem);
}

/* --------------------------------------------------------------------------
   6. Header & navigation
   -------------------------------------------------------------------------- */

.site-header {
  position: relative;
  z-index: 20;
  background-color: var(--white);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding: 16px 24px;
}

/* Brand ------------------------------------------------------------------ */

.brand {
  display: flex;
  align-items: center;
  gap: 18px;
}

.brand__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 80px;
  height: 80px;
  background-color: var(--accent-mauve);
  /* White on this fill is 1.9:1. Dark text is 7.4:1, same as .btn. */
  color: var(--text-dark);
  font-family: var(--font-heading);
  font-size: 1.75rem;
  letter-spacing: 0.08em;
}

/* Wordmark. The serif renders ~8% wider in Didot than in the Playfair Display
   fallback, so the sizes below are measured against Didot — the wider of the
   two — and the nav then clears at every width.

   Every term is 60% of the 4x sizing this replaced, so it still tops out once
   the 1200px content cap allows it and the vw term scales it down below that.
   The tightest width is just above 1024px, where the wider nav gaps come back. */
.brand__name {
  font-family: var(--font-heading);
  font-size: clamp(0.75rem, 5.56vw - 1.91rem, 2.25rem);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: 0.05em;
  white-space: nowrap;
  color: var(--text-dark);
}

/* Nav -------------------------------------------------------------------- */

.primary-nav {
  display: flex;
  align-items: center;
  gap: 32px;
  flex: 0 0 auto; /* the wordmark scales instead of squeezing the nav */
}

.primary-nav__list {
  display: flex;
  align-items: center;
  gap: 32px;
}

/* Tops out at 1.125rem from about 1200px up. Below that the vw term eases it
   down so the links always clear the wordmark on one line; every term is 75% of
   the sizing it replaced, so the ratio holds at each width. */
.primary-nav__link {
  font-size: clamp(0.75rem, 1.29vw + 0.16rem, 1.125rem);
  font-weight: 400;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap; /* keep "MY STORY" and "CONTACT US" on one line */
  color: var(--text-dark);
  transition: color var(--transition);
}

.primary-nav__link:hover,
.primary-nav__link:focus-visible {
  color: var(--deep-dark);
}

.primary-nav__link[aria-current="page"] {
  color: var(--deep-dark);
}

/* Social icons ----------------------------------------------------------- */

.social-links {
  display: flex;
  align-items: center;
  gap: 16px;
}

.social-links__link {
  display: flex;
  color: var(--text-dark);
  transition: color var(--transition);
}

.social-links__link:hover,
.social-links__link:focus-visible {
  color: var(--deep-dark);
}

.social-links__link svg {
  width: 27px;
  height: 27px;
}

/* Hamburger -------------------------------------------------------------- */

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0;
}

.nav-toggle__bar {
  display: block;
  width: 24px;
  height: 1px;
  margin-inline: auto;
  background-color: var(--text-dark);
  transition: transform var(--transition), opacity var(--transition);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) {
  opacity: 0;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* --------------------------------------------------------------------------
   7. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  padding: 26px 24px;
  background-color: var(--footer-dark);
  color: var(--white);
  text-align: center;
}

.site-footer__text {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 300;
  letter-spacing: 0.06em;
}

.site-footer__text + .site-footer__text {
  margin-top: 0.45em;
}

/* --------------------------------------------------------------------------
   8. Floating chat button
   -------------------------------------------------------------------------- */

.chat-button {
  position: fixed;
  right: 28px;
  bottom: 28px;
  z-index: 50;
  padding: 14px 26px;
  background-color: var(--accent-mauve);
  color: var(--text-dark);
  font-family: var(--font-heading);
  font-size: 1rem;
  letter-spacing: 0.04em;
  border-radius: 8px;
  box-shadow: var(--shadow-soft);
  transition: background-color var(--transition), transform var(--transition);
}

.chat-button:hover,
.chat-button:focus-visible {
  background-color: #a89094;
  color: var(--text-dark);
  transform: translateY(-2px);
}

/* --------------------------------------------------------------------------
   9. Welcome banner
   -------------------------------------------------------------------------- */

.welcome-banner {
  position: relative;
  height: 54vh;
  min-height: 352px;
  max-height: 539px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.welcome-banner__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 52%;
}

.welcome-banner__overlay {
  position: absolute;
  inset: 0;
  background: rgba(247, 235, 237, 0.3);
}

.welcome-banner__title {
  position: relative;
  margin: 0;
  font-family: Didot, "Playfair Display", serif;
  font-weight: 400;
  font-size: 80px;
  letter-spacing: 3.2px;
  line-height: 1.2; /* 96px at 80px; scales with the mobile size below */
  color: #2b2b2b;
  text-align: center;
  padding: 0 1rem;
  text-shadow: 0 1px 8px rgba(255, 255, 255, 0.55);
}

/* --------------------------------------------------------------------------
   10. Welcome (two-column)
   -------------------------------------------------------------------------- */

/* Same outer width as the home card row: the 1200px column minus the 24px
   side padding that .container puts around the cards. 50/50, no gap, so the
   photo can sit flush on every edge of its half. */
.welcome {
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: min(100% - 48px, calc(var(--content-max) - 48px));
  margin-inline: auto;
  background-color: var(--bg-pink);
  overflow: hidden;
  border-radius: 15px;
}

.welcome__text {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(20px, 2.5vw, 40px) clamp(24px, 4vw, 56px);
  text-align: center;
}

/* Sized against the column, not the viewport, so the explicit line break in
   the markup stays two lines instead of spilling onto a third. */
.welcome__title {
  margin-bottom: 1.1em;
  font-size: clamp(1.75rem, 2.6vw, 2.25rem);
  font-size: min(2.5rem, 7cqw);
}

.welcome__body {
  max-width: 520px;
}

/* Fills its half edge to edge. The text column sets the height; the photo
   covers that box with no gap at the seam or the outer edges. */
.welcome__media {
  position: relative;
  min-width: 0;
  min-height: 100%;
}

.welcome__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: center;
}

/* --------------------------------------------------------------------------
   11. Image cards
   -------------------------------------------------------------------------- */

.cards__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 3vw, 36px);
}

.card {
  position: relative;
  display: block;
}

.card__image {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: 15px;
}

.card__label {
  position: absolute;
  bottom: 33%;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
}

/* The whole card is the link, so hovering anywhere lights up the label. */
.card:hover .card__label,
.card:focus-visible .card__label {
  background-color: var(--accent-rose);
}

/* --------------------------------------------------------------------------
   12. Our Work / Instagram feed
   -------------------------------------------------------------------------- */

.our-work__title {
  margin-bottom: 0;
  text-align: center;
}

/* Wrapper only — the widget styles its own internals.
   min-height matches the live widget so the feed doesn't shove the page
   down when the script arrives: 861px at 1280 (feed maxes out at 1200px
   wide), 724px at 1024, 535px at 768, 273px at 375. */
.our-work__feed {
  max-width: var(--content-max);
  margin-inline: auto;
  padding: clamp(32px, 4vw, 56px) 24px;
  min-height: 861px;
}

@media (max-width: 1279px) {
  .our-work__feed {
    min-height: calc(724px + 137 * (100vw - 1024px) / 256);
  }
}

@media (max-width: 1024px) {
  .our-work__feed {
    min-height: calc(535px + 189 * (100vw - 768px) / 256);
  }
}

@media (max-width: 767px) {
  .our-work__feed {
    min-height: calc(273px + 262 * (100vw - 375px) / 393);
  }
}

.our-work__cta {
  text-align: center;
}

/* --------------------------------------------------------------------------
   13. Menu page
   -------------------------------------------------------------------------- */

/* Orders & pricing -------------------------------------------------------- */

/* 60/40 either side of a hairline, which occupies the middle track so the two
   text columns keep their ratio independent of it. Both columns stretch so
   the divider can run from the headings through the copy. The panel's own
   padding-block is what keeps it off the border. */
.orders {
  display: grid;
  grid-template-columns: 3fr 1px 2fr;
  gap: clamp(24px, 3vw, 40px);
  align-items: stretch;
  text-align: center;
}

.orders__divider {
  width: 1px;
  min-height: 100%;
  background-color: var(--accent-mauve);
}

/* Wrap rather than overflow if the label is wider than the column. */
.orders .btn {
  max-width: 100%;
  white-space: normal;
  line-height: 1.35;
  box-sizing: border-box;
}

/* Ingredients ------------------------------------------------------------ */

/* 60/40: the photo fills the wider left column and dissolves into the panel,
   the copy sits in the narrower right one. Column-gap stays tight so the
   faded right edge nearly meets the text; row-gap keeps the stacked spacing. */
.ingredients {
  display: grid;
  grid-template-columns: 3fr 2fr;
  column-gap: 10px;
  row-gap: clamp(24px, 4vw, 56px);
  align-items: stretch;
}

/* The image is taken out of flow so it can fill whatever height the copy sets,
   without its own proportions forcing the row taller. min-height is the floor
   for the short-copy case. */
.ingredients__media {
  position: relative;
  min-height: 340px;
}

.ingredients__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* No border or shadow: an edge would give away where the fade ends. Only the
     left corners are rounded — the right pair must stay square so the fade has
     no outline to reveal. */
  border: 0;
  border-radius: 15px 0 0 15px;
  box-shadow: none;
  /* Static fade over the last 55%, so the photo dissolves into the panel the
     text sits on rather than stopping at a rectangle. */
  -webkit-mask-image: linear-gradient(to right, black 45%, transparent 90%);
  mask-image: linear-gradient(to right, black 45%, transparent 90%);
}

.ingredients__text {
  align-self: center;
  padding-left: 0;
}

/* Hug the image side of the column; leftover width, if any, stays on the right. */
.ingredients__text h2,
.ingredients__text .prose {
  margin-inline: 0 auto;
}

/* The framed box, used by both full-width panels on the menu page. It carries
   the background as well as the border, which is what keeps the border on the
   same element as the pink it encloses. Block padding is 40% of a plain
   .panel's at every width, each clamp term scaled so the ratio holds.
   Width and inline padding live here once, so the two boxes stay identical:
   85% of a plain panel's width, centred, with inline padding at 1.2× the
   site container's 24px. */
.panel--framed {
  --framed-width: calc(0.85 * (100% - 2 * var(--panel-inset)));
  --framed-pad-inline: calc(24px * 1.2);
  background-color: var(--bg-pink);
  border: 5px solid var(--accent-mauve);
  padding-block: clamp(16px, 2.4vw, 35.2px);
  width: var(--framed-width);
  max-width: var(--framed-width);
  margin-inline: auto;
}

.panel--framed > .container {
  padding-inline: var(--framed-pad-inline);
}

/* The other large vertical space inside the frame is the rhythm between the
   MENU block and the ingredients block, trimmed to match. The multiplier is
   0.8 of the halved --section-gap, which lands on the same px as the 0.4 of the
   old value — the inside of this box is deliberately independent of the
   sitewide rhythm. */
.panel--framed .section-stack > * + * {
  margin-top: calc(var(--section-gap) * 0.8);
}

/* Three across at every width down to the 768px phone breakpoint, where it
   drops straight to a single column. There is no two-column tablet step. */
.flavors {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(24px, 3vw, 40px);
}

.flavor {
  text-align: center;
}

/* Fixed square frame so source photos of any size render uniformly.
   overflow: hidden clips the per-image zoom below.
   The tint shows while the photo loads, so an empty cell never looks broken. */
.flavor__media {
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background-color: var(--accent-rose);
  border-radius: 15px;
}

/* The source photos are shot at different distances, so each <img> carries an
   inline --zoom to bring every macaron to the same on-screen size, plus
   --nudge-x / --nudge-y to re-centre it afterwards. Defaults leave the photo
   untouched. Percentages resolve against the tile, and scale runs first.
   object-position is no help here: source and tile are both square, so cover
   crops nothing and there is nothing for it to reposition. Keep each nudge
   within (zoom - 1) / 2 or the opposite edge pulls away from the frame. */
.flavor__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: translate(var(--nudge-x, 0), var(--nudge-y, 0)) scale(var(--zoom, 1));
}

.flavor__name {
  margin: 18px 0 4px;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.flavor__label {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 300;
  letter-spacing: 0.06em;
  color: var(--deep-dark);
}

/* --------------------------------------------------------------------------
   14. Coming soon hero
   -------------------------------------------------------------------------- */

/* cta-hero background: uncomment background-image and point it at the photo.
   Paths are relative to this stylesheet, so they start with ../images/. */
.cta-hero {
  position: relative;
  /* background-image: url("../images/menu/coming-soon.jpg"); */
  background-color: var(--accent-rose);
  background-size: cover;
  background-position: center;
  border-radius: 15px;
  padding-block: clamp(56px, 8vw, 112px);
  color: var(--text-dark);
  text-align: center;
}

.cta-hero__overlay {
  position: absolute;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.25);
}

/* Lifts the content above the overlay. */
.cta-hero__inner {
  position: relative;
}

.cta-hero h2 {
  color: inherit;
}

/* Subscribe form ---------------------------------------------------------- */

.subscribe {
  max-width: 520px;
  margin: clamp(24px, 3vw, 36px) auto 0;
}

.subscribe__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}

.subscribe__input {
  flex: 1 1 240px;
  min-width: 0;
  padding: 14px 18px;
  background-color: var(--white);
  color: var(--text-dark);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 300;
  border: 1px solid var(--accent-mauve);
  border-radius: 2px;
}

.subscribe__input::placeholder {
  color: var(--deep-dark);
}

/* A solid chip so the message stays legible over any background photo. */
.subscribe__error {
  display: inline-block;
  margin: 14px 0 0;
  padding: 6px 14px;
  background-color: var(--white);
  color: #a3261e;
  font-size: 0.8125rem;
  border-radius: 2px;
}

.subscribe__error[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   15. Contact page
   -------------------------------------------------------------------------- */

.form-card {
  max-width: 860px;
  margin-inline: auto;
  padding: clamp(28px, 5vw, 50px);
  background-color: var(--white);
  border-radius: 15px;
}

/* Shown by js/main.js only when the background post to Formspree fails. */
.form-error {
  margin: 18px 0 0;
  text-align: center;
  font-size: 0.875rem;
  color: #a3261e;
}

.form-error[hidden] {
  display: none;
}

/* One gap value drives the spacing between every row and field. */
.form-fields {
  display: grid;
  gap: clamp(26px, 4vw, 38px);
}

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 3vw, 40px);
}

.field__label {
  display: block;
  margin-bottom: 6px;
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
}

/* Underline only — no box, no fill. */
.field__input {
  display: block;
  width: 100%;
  padding: 8px 0;
  background-color: transparent;
  border: 0;
  border-bottom: 1px solid var(--text-dark);
  border-radius: 0;
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--text-dark);
}

/* The underline stays, and the same 2px outline used on links and buttons
   stays visible. A thicker border would shift the line. */
.field__input:focus-visible {
  outline: 2px solid var(--accent-deep);
  outline-offset: 3px;
  border-bottom-color: var(--accent-deep);
  box-shadow: 0 1px 0 0 var(--accent-deep);
}

.subscribe__input:focus-visible {
  outline: 2px solid var(--accent-deep);
  outline-offset: 3px;
}

textarea.field__input {
  resize: vertical;
}

.form-actions {
  margin-top: clamp(32px, 5vw, 44px);
  text-align: center;
}

/* Text-only button, for a form that should stay quiet. */
.text-button {
  padding: 0;
  background: none;
  border: 0;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 1rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dark);
  cursor: pointer;
  transition: color var(--transition);
}

.text-button:hover,
.text-button:focus-visible {
  color: var(--deep-dark);
}

/* 630x300 embed that keeps its ratio as it narrows. */
.map {
  max-width: 630px;
  margin-inline: auto;
  aspect-ratio: 21 / 10;
  overflow: hidden;
  border-radius: 15px;
}

.map iframe,
.map__facade {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Click-to-load stand-in. It fills the same 21/10 box the iframe uses. */
.map__facade {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin: 0;
  padding: 16px;
  background-color: #e8cfd3;
  color: var(--text-dark);
  font-family: var(--font-body);
  cursor: pointer;
}

.map__pin {
  width: 36px;
  height: 36px;
}

.map__address {
  font-size: calc(1rem + 2px);
  line-height: 1.7;
}

.map__external {
  margin: 14px 0 0;
  text-align: center;
}

.map__external a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --------------------------------------------------------------------------
   16. Success modal
   -------------------------------------------------------------------------- */

/* Shared by the subscribe and contact forms. js/main.js builds the markup once
   and refills the copy from each form's data-success-* attributes. */
.modal {
  position: fixed;
  inset: 0;
  z-index: 60; /* clears the floating chat button at 50 */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: modal-fade 0.2s ease-out;
}

/* Without this the display above would override the hidden attribute. */
.modal[hidden] {
  display: none;
}

@keyframes modal-fade {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

.modal__backdrop {
  position: absolute;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.35);
}

.modal__card {
  position: relative;
  width: 100%;
  max-width: 420px;
  padding: clamp(32px, 6vw, 48px);
  background-color: var(--bg-pink);
  border: 5px solid var(--accent-mauve);
  border-radius: 15px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.2);
  text-align: center;
}

.modal__heading {
  margin: 0;
  font-size: clamp(1.375rem, 4vw, 1.75rem);
}

.modal__text {
  margin: 14px 0 30px;
  font-size: calc(1rem + 2px);
}

/* --------------------------------------------------------------------------
   17. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1024px) {
  :root {
    --panel-inset: 24px;
  }

  .primary-nav,
  .primary-nav__list {
    gap: 22px;
  }

  .cards__grid {
    gap: 18px;
  }

  .card__label {
    padding: 10px 24px;
    font-size: 0.9375rem;
  }
}

@media (max-width: 767px) {
  :root {
    --panel-inset: 0px;
    --section-gap: 24px;
  }

  .site-header__inner {
    flex-wrap: wrap;
    padding: 12px 20px;
  }

  .nav-toggle {
    display: flex;
  }

  /* Nav collapses into a dropdown toggled by main.js. */
  .primary-nav {
    display: none;
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
    flex-basis: 100%;
    padding: 20px 0 8px;
    border-top: 1px solid var(--bg-pink);
  }

  .primary-nav.is-open {
    display: flex;
  }

  .primary-nav__list {
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
  }

  /* The dropdown stacks vertically, so it takes the size unreduced by width. */
  .primary-nav__link {
    font-size: 1.3125rem;
  }

  .brand__mark {
    width: 64px;
    height: 64px;
    font-size: 1.5rem;
  }

  /* Cap and vw term are both 60% of the previous sizing. The floor stays at
     12px: 60% of it would be too small to read, and at this size the wordmark
     already clears the hamburger on the narrowest phones. */
  .brand__name {
    font-size: clamp(0.75rem, 5.45vw - 0.64rem, 0.825rem);
  }

  /* 80px clips "Anastasiia's" inside a 375px banner. 58px is the largest
     size that keeps every word inside the heading's side padding. */
  .welcome-banner__title {
    font-size: 58px;
  }

  /* Photo full width above the text, flush to the pink box. */
  .welcome {
    grid-template-columns: 1fr;
  }

  .welcome__media {
    order: -1;
    padding: 0;
    min-height: 0;
  }

  .welcome__media img {
    position: static;
    width: 100%;
    height: auto;
    max-width: none;
    object-fit: cover;
  }

  .cards__grid {
    grid-template-columns: 1fr;
    gap: 28px;
  }

  .split {
    grid-template-columns: 1fr;
  }

  .split--swap .split__media {
    order: 0;
  }

  /* Stacked, so the fade moves to the edge that now meets the text. */
  .ingredients {
    grid-template-columns: 1fr;
  }

  .ingredients__media {
    min-height: 260px;
  }

  .ingredients__image {
    /* Rounding follows the fade: the top pair is now the framed edge. */
    border-radius: 15px 15px 0 0;
    -webkit-mask-image: linear-gradient(to bottom, black 45%, transparent 90%);
    mask-image: linear-gradient(to bottom, black 45%, transparent 90%);
  }

  /* Full width once stacked — 75% of a narrow column is too small. */
  .split__media--narrow img {
    width: 100%;
  }

  /* Stacked cube cake is the full column wide, so match that height instead
     of the desktop 75% column. */
  .split__media--narrow img.macaron-tower {
    width: auto;
    max-height: calc(100cqi * 1873 / 1600);
  }

  .flavors {
    grid-template-columns: 1fr;
  }

  .orders {
    grid-template-columns: 1fr;
  }

  /* The vertical hairline becomes a horizontal one between the stacked columns. */
  .orders__divider {
    justify-self: center;
    align-self: center;
    width: 60%;
    height: 1px;
    min-height: 0;
  }

  .field-row {
    grid-template-columns: 1fr;
  }

  .card__image {
    aspect-ratio: 4 / 3;
  }

  .card__label {
    padding: 12px 40px;
    font-size: 1rem;
  }

  .chat-button {
    right: 16px;
    bottom: 16px;
    padding: 12px 20px;
    font-size: 0.9375rem;
  }

  /* Keep the copyright clear of the floating chat button. */
  .site-footer {
    padding-bottom: 76px;
  }
}

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