@layer reset, tokens, base, layout, components, utilities;

/* ============================================================ RESET ==== */
@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  * { margin: 0; }
  html { -webkit-text-size-adjust: 100%; }
  body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
  img, picture, svg, video { display: block; max-width: 100%; }
  input, button, textarea, select { font: inherit; color: inherit; }
  button { background: none; border: 0; cursor: pointer; }
  p, h1, h2, h3, h4 { overflow-wrap: break-word; }
  ul[class], ol[class] { list-style: none; padding: 0; }
  :target { scroll-margin-block-start: 6rem; }
  html { scroll-padding-block-start: calc(var(--header-h) + 1rem); }
}

/* =========================================================== TOKENS ==== */
@layer tokens {
  :root {
    /* — spacing (4px rhythm) — */
    --space-1: .25rem;  --space-2: .5rem;   --space-3: .75rem;
    --space-4: 1rem;    --space-5: 1.5rem;  --space-6: 2rem;
    --space-8: 3rem;    --space-10: 4rem;   --space-12: 6rem;
    --space-16: 8rem;

    /* — type — */
    --font-display: 'Fraunces', 'Iowan Old Style', Georgia, serif;
    --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

    /* Bumped a step over the old scale: the body copy was too small and too
       light to read comfortably on a phone. */
    --text-2xs: clamp(.72rem, .70rem + .1vw, .76rem);
    --text-xs:  clamp(.8rem, .78rem + .12vw, .85rem);
    --text-sm:  clamp(.9rem, .87rem + .16vw, .97rem);
    --text-base:clamp(1.02rem, .99rem + .22vw, 1.12rem);
    --text-lg:  clamp(1.15rem, 1.09rem + .3vw, 1.33rem);
    --text-xl:  clamp(1.4rem, 1.25rem + .68vw, 1.85rem);
    --text-2xl: clamp(1.8rem, 1.5rem + 1.3vw, 2.65rem);
    --text-3xl: clamp(2.3rem, 1.8rem + 2.3vw, 3.5rem);
    --text-4xl: clamp(2.7rem, 1.95rem + 3.6vw, 4.7rem);

    --leading-tight: 1.12;
    --leading-snug: 1.35;
    --leading-normal: 1.65;

    /* =====================================================================
       BRAND PALETTE
       Berry Velvet #B23A5D · Peach Whip #F8C6A0 · Vanilla Glow #F4E6D2
       Rose Cloud   #E8A7B5 · Olive Mist #9DAA77
       Authored in OKLCH so hover/active states come from nudging lightness
       rather than being hand-picked and drifting out of step.
       ===================================================================== */
    --berry:        oklch(.531 .157 6.5);
    --berry-hover:  oklch(.472 .157 6.5);
    --berry-active: oklch(.418 .148 6.5);
    --berry-soft:   oklch(.960 .022 6.5);
    --berry-line:   oklch(.888 .052 6.5);

    --rose-cloud:   oklch(.794 .079 4.8);
    --rose-soft-bg: oklch(.958 .026 4.8);

    --peach-whip:   oklch(.862 .076 58.8);
    --peach-soft:   oklch(.963 .026 58.8);
    --peach-line:   oklch(.906 .050 58.8);

    --vanilla:      oklch(.931 .031 77);
    --vanilla-lite: oklch(.966 .016 77);

    --olive-mist:   oklch(.715 .072 120);
    --olive-deep:   oklch(.505 .085 122);   /* readable as text/icons */
    --olive-soft:   oklch(.957 .026 120);
    --olive-line:   oklch(.886 .048 120);

    /* — warm neutral ramp, leaning plum at the dark end to sit with Berry — */
    --n-0:   oklch(1 0 0);
    --n-25:  oklch(.989 .005 60);
    --n-50:  oklch(.976 .010 62);
    --n-100: oklch(.956 .016 66);
    --n-200: oklch(.913 .019 55);
    --n-300: oklch(.856 .021 40);
    --n-400: oklch(.722 .024 30);
    --n-500: oklch(.602 .026 24);
    --n-600: oklch(.492 .030 20);
    --n-700: oklch(.396 .034 18);
    --n-800: oklch(.306 .036 15);
    --n-900: oklch(.236 .034 14);
    --n-950: oklch(.165 .028 12);

    --danger: oklch(.545 .175 25);
    --danger-soft: oklch(.958 .028 25);
    --warn: oklch(.68 .12 65);

    /* — semantic: components reference these, never a raw brand colour — */
    --surface:        var(--n-50);
    --surface-raised: var(--n-0);
    --surface-cream:  var(--vanilla);
    --surface-sunken: var(--n-100);
    --surface-ink:    var(--n-900);
    --text:           var(--n-900);
    --text-muted:     var(--n-600);
    --text-faint:     var(--n-500);
    --border:         var(--n-200);
    --border-strong:  var(--n-300);
    --ring:           var(--berry);

    /* Legacy aliases — the component layer was written against these names,
       so re-pointing them here re-skins the whole site in one place. */
    --rose:        var(--berry);
    --rose-hover:  var(--berry-hover);
    --rose-active: var(--berry-active);
    --rose-soft:   var(--berry-soft);
    --rose-line:   var(--berry-line);
    --gold:        var(--peach-whip);
    --gold-soft:   var(--peach-soft);
    --gold-line:   var(--peach-line);
    --ok:          var(--olive-deep);
    --ok-soft:     var(--olive-soft);

    /* — shape & elevation — */
    --radius-xs: .375rem;
    --radius-sm: .625rem;
    --radius:    1rem;
    --radius-lg: 1.5rem;
    --radius-xl: 2rem;
    --radius-full: 999px;

    --shadow-xs: 0 1px 2px oklch(.30 .04 15 / .05);
    --shadow-sm: 0 1px 3px oklch(.30 .04 15 / .07), 0 1px 2px oklch(.30 .04 15 / .04);
    --shadow:    0 4px 12px oklch(.30 .04 15 / .07), 0 2px 4px oklch(.30 .04 15 / .04);
    --shadow-lg: 0 14px 32px oklch(.30 .04 15 / .10), 0 6px 12px oklch(.30 .04 15 / .05);
    --shadow-xl: 0 30px 60px oklch(.30 .04 15 / .15), 0 12px 20px oklch(.30 .04 15 / .06);

    /* — motion — */
    --ease-out: cubic-bezier(.16, .84, .44, 1);
    --ease-in-out: cubic-bezier(.65, 0, .35, 1);
    --dur-fast: 130ms;
    --dur: 210ms;
    --dur-slow: 360ms;

    --header-h: 5.5rem;
    --shell: 78rem;
    --tap: 2.75rem;          /* 44px — minimum comfortable touch target */
  }

  @media (max-width: 47.99rem) { :root { --header-h: 4.75rem; } }
  /* A phone on its side: a slimmer header leaves the short screen to the page. */
  @media (orientation: landscape) and (max-height: 32rem) { :root { --header-h: 4rem; } }
}

/* ============================================================= BASE ==== */
@layer base {
  html { scroll-behavior: smooth; }
  /* The colour a phone shows when you pull past either end of the page. The
     page itself is light (body), but it opens under the dark announcement bar
     and ends on the dark footer, so the overscroll matches those. */
  html { background: var(--surface-ink); }
  @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

  body {
    font-family: var(--font-sans);
    font-size: var(--text-base);
    font-weight: 400;
    line-height: var(--leading-normal);
    color: var(--text);
    /* Painted as an image, not a background-color, on purpose: iPhone Safari
       colours the area past the end of the page (and behind its bottom bar)
       with the body's background-color blended over the html one. With no
       body colour it uses the html one — the dark footer ink — so the page
       ends on the footer instead of a light strip. It looks identical. */
    background: linear-gradient(var(--surface), var(--surface));
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    overflow-x: hidden;
    /* Kill the 300ms tap delay and the grey flash on tap; every interactive
       element defines its own :active state instead. */
    -webkit-tap-highlight-color: transparent;
    text-size-adjust: 100%;
  }
  body[data-locked] { overflow: hidden; }

  main { flex: 1; }
  main:focus { outline: none; }

  h1, h2, .display {
    font-family: var(--font-display);
    font-weight: 600;
    line-height: var(--leading-tight);
    letter-spacing: -0.016em;
    font-variation-settings: 'SOFT' 30, 'WONK' 0;
    text-wrap: balance;
  }
  h1 { font-size: var(--text-3xl); }
  h2 { font-size: var(--text-2xl); }
  h3 {
    font-family: var(--font-sans);
    font-size: var(--text-lg); font-weight: 600;
    letter-spacing: -0.008em; line-height: var(--leading-snug);
    text-wrap: balance;
  }
  p { text-wrap: pretty; }

  /* Anything tappable should feel instant and never select text on a
     long-press. */
  a, button, label, summary, .chip, .card { touch-action: manipulation; }
  button, .btn, .chip, summary { -webkit-user-select: none; user-select: none; }

  a { color: inherit; text-decoration-color: color-mix(in oklch, currentColor 35%, transparent); text-underline-offset: .22em; }
  a:hover { text-decoration-color: currentColor; }

  :focus-visible {
    outline: 2px solid var(--ring);
    outline-offset: 3px;
    border-radius: var(--radius-xs);
  }

  ::selection { background: var(--rose-soft); color: var(--n-900); }

  ::-webkit-scrollbar { width: 11px; height: 11px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb { background: var(--n-300); border-radius: 99px; border: 3px solid var(--surface); }
  ::-webkit-scrollbar-thumb:hover { background: var(--n-400); }
}

/* =========================================================== LAYOUT ==== */
@layer layout {
  .shell {
    --gutter: 1.25rem;
    /* The page runs to the screen edges (viewport-fit=cover): on a phone held
       sideways, keep content clear of the notch and the rounded corners. */
    width: min(100% - max(var(--gutter), env(safe-area-inset-left, 0px)) - max(var(--gutter), env(safe-area-inset-right, 0px)), var(--shell));
    margin-inline: auto;
  }
  @media (max-width: 30rem) { .shell { --gutter: .875rem; } }

  /* Break out of the shell by exactly one gutter, never more. */
  .bleed {
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
  }

  .section { padding-block: clamp(3.5rem, 7vw, var(--space-12)); }
  .section-tight { padding-block: clamp(2.5rem, 5vw, var(--space-10)); }
  .section-ink { background: var(--surface-ink); color: var(--n-100); }
  .section-cream { background: var(--surface-cream); }

  .stack > * + * { margin-block-start: var(--flow, var(--space-4)); }
  .cluster { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
  .prose { max-width: 62ch; }

  .grid-auto {
    display: grid;
    gap: var(--space-5);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  }
}

/* ======================================================= COMPONENTS ==== */
@layer components {

  /* ---------------------------------------------------- utilities-ish -- */
  .sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .skip-link {
    position: absolute; inset-inline-start: var(--space-4); inset-block-start: -100%;
    z-index: 200; background: var(--surface-ink); color: var(--n-50);
    padding: var(--space-3) var(--space-5); border-radius: var(--radius-sm);
    transition: inset-block-start var(--dur) var(--ease-out);
  }
  .skip-link:focus { inset-block-start: var(--space-4); }

  .eyebrow {
    font-size: var(--text-xs); font-weight: 600; letter-spacing: .12em;
    text-transform: uppercase; color: var(--berry);
    display: flex; align-items: center; gap: var(--space-3);
  }
  .eyebrow::before {
    content: ""; inline-size: 1.75rem; block-size: 1px;
    background: currentColor; opacity: .55; flex: none;
  }
  .eyebrow-center { justify-content: center; }
  .eyebrow-center::after {
    content: ""; inline-size: 1.75rem; block-size: 1px;
    background: currentColor; opacity: .55; flex: none;
  }
  .section-ink .eyebrow { color: var(--gold); }

  .lede { font-size: var(--text-lg); color: var(--text-muted); font-weight: 300; }
  .section-ink .lede { color: var(--n-300); }
  .muted { color: var(--text-muted); }
  .tnum { font-variant-numeric: tabular-nums; }

  .section-head { display: grid; gap: var(--space-4); margin-block-end: var(--space-8); }
  .section-head.center { justify-items: center; text-align: center; }
  .section-head .lede { max-width: 54ch; }

  /* ------------------------------------------------------------ brand -- */
  .brand-mark {
    inline-size: clamp(2.75rem, 2.4rem + 1vw, 3.1rem); block-size: clamp(2.75rem, 2.4rem + 1vw, 3.1rem); flex: none;
    background: currentColor;
    color: var(--berry);
    -webkit-mask: url('/assets/img/brand/mark.svg') center / contain no-repeat;
    mask: url('/assets/img/brand/mark.svg') center / contain no-repeat;
  }
  .brand-mark-lg { inline-size: 3.6rem; block-size: 3.6rem; }

  .brand { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; }
  .brand-words { display: grid; line-height: 1; }
  .brand-name {
    font-family: var(--font-display); font-size: clamp(1.6rem, 1.35rem + .8vw, 1.9rem); font-weight: 600;
    letter-spacing: -.01em;
  }
  .brand-sub {
    font-size: .68rem; letter-spacing: .3em; text-transform: uppercase;
    color: var(--text-muted); font-weight: 500; margin-block-start: .18rem;
  }
  /* The header logo, bigger on every screen: about 54px on a phone growing
     to 64px on a computer. Only the header — the mark elsewhere keeps its size. */
  .site-header .brand-mark {
    inline-size: clamp(3.4rem, 2.9rem + 1.4vw, 4.1rem);
    block-size: clamp(3.4rem, 2.9rem + 1.4vw, 4.1rem);
  }
  .site-header .brand-name { font-size: clamp(2rem, 1.7rem + 1vw, 2.5rem); }
  .site-header .brand-sub { font-size: clamp(.72rem, .66rem + .2vw, .8rem); }

  /* ---------------------------------------------------------- buttons -- */
  .btn {
    --btn-bg: var(--surface-ink);
    --btn-fg: var(--n-50);
    --btn-bd: transparent;
    display: inline-flex; align-items: center; justify-content: center;
    gap: var(--space-2);
    min-block-size: var(--tap);
    padding-inline: var(--space-5);
    background: var(--btn-bg); color: var(--btn-fg);
    border: 1px solid var(--btn-bd);
    border-radius: var(--radius-full);
    font-size: var(--text-sm); font-weight: 600; letter-spacing: 0;
    text-decoration: none; white-space: nowrap;
    transition: background var(--dur-fast) var(--ease-out),
                color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                transform var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out);
  }
  .btn:hover { --btn-bg: var(--n-800); box-shadow: var(--shadow); transform: translateY(-1px); }
  .btn:active { transform: translateY(0) scale(.97); box-shadow: var(--shadow-xs); }
  .btn[disabled], .btn[aria-disabled="true"] {
    opacity: .45; pointer-events: none; box-shadow: none; transform: none;
  }

  .btn-accent { --btn-bg: var(--rose); }
  .btn-accent:hover { --btn-bg: var(--rose-hover); }
  .btn-accent:active { --btn-bg: var(--rose-active); }

  .btn-outline { --btn-bg: transparent; --btn-fg: var(--text); --btn-bd: var(--border-strong); }
  .btn-outline:hover { --btn-bg: var(--n-0); --btn-bd: var(--n-400); }
  .section-ink .btn-outline { --btn-fg: var(--n-100); --btn-bd: oklch(1 0 0 / .3); }
  .section-ink .btn-outline:hover { --btn-bg: oklch(1 0 0 / .1); --btn-bd: oklch(1 0 0 / .55); }

  .btn-ghost { --btn-bg: transparent; --btn-fg: var(--text); --btn-bd: transparent; padding-inline: var(--space-3); }
  .btn-ghost:hover { --btn-bg: var(--n-100); box-shadow: none; transform: none; }

  .btn-light { --btn-bg: var(--n-0); --btn-fg: var(--n-900); }
  .btn-light:hover { --btn-bg: var(--n-100); }

  .btn-sm { min-block-size: 2.4rem; padding-inline: var(--space-4); font-size: var(--text-xs); }
  .btn-lg { min-block-size: 3.35rem; padding-inline: var(--space-6); font-size: var(--text-base); }
  .btn-block { inline-size: 100%; }
  .btn-danger { --btn-bg: transparent; --btn-fg: var(--danger); --btn-bd: color-mix(in oklch, var(--danger) 35%, transparent); }
  .btn-danger:hover { --btn-bg: var(--danger-soft); --btn-bd: var(--danger); }

  .link-arrow {
    display: inline-flex; align-items: center; gap: var(--space-2);
    font-size: var(--text-sm); font-weight: 500; letter-spacing: .04em;
    text-decoration: none; color: var(--rose);
    padding-block: var(--space-1);
  }
  .link-arrow svg { transition: transform var(--dur) var(--ease-out); }
  .link-arrow:hover svg { transform: translateX(4px); }
  .section-ink .link-arrow { color: var(--gold); }

  /* ----------------------------------------------------------- header -- */
  .announce {
    background: var(--surface-ink); color: var(--n-200);
    font-size: var(--text-2xs); font-weight: 500; letter-spacing: .06em;
    text-transform: uppercase;
    text-align: center; padding-block: .45rem; padding-inline: var(--space-4);
  }

  .site-header {
    position: sticky; inset-block-start: 0; z-index: 60;
    background: color-mix(in oklch, var(--surface) 82%, transparent);
    backdrop-filter: blur(14px) saturate(1.25);
    -webkit-backdrop-filter: blur(14px) saturate(1.25);
    border-block-end: 1px solid transparent;
    transition: border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
  }
  /* Tucked away while reading down the page; back on the first scroll up. */
  .site-header[data-hidden] { transform: translateY(-100%); }
  .site-header[data-stuck] {
    border-block-end-color: var(--border);
    background: color-mix(in oklch, var(--surface) 93%, transparent);
  }
  .header-inner {
    min-block-size: var(--header-h);
    display: flex; align-items: center; gap: var(--space-5);
  }
  .nav {
    display: flex; align-items: center; gap: clamp(.5rem, 1.4vw, 1.35rem);
    margin-inline-start: auto;
  }
  .nav a {
    font-size: var(--text-base); text-decoration: none; color: var(--text-muted);
    padding: var(--space-2) var(--space-1); position: relative;
    transition: color var(--dur-fast) var(--ease-out);
  }
  .nav a::after {
    content: ""; position: absolute; inset-inline: var(--space-1); inset-block-end: .15rem;
    block-size: 1px; background: var(--rose); transform: scaleX(0); transform-origin: left;
    transition: transform var(--dur) var(--ease-out);
  }
  .nav a:hover { color: var(--text); }
  .nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }
  .nav a[aria-current="page"] { color: var(--text); }
  .nav-trade {
    border: 1px solid var(--gold-line); border-radius: var(--radius-full);
    padding-inline: var(--space-4) !important; background: var(--gold-soft);
    color: var(--n-800) !important;
  }
  .nav-trade::after { display: none; }
  .nav-trade:hover { background: color-mix(in oklch, var(--gold-soft) 70%, var(--gold)); }

  .header-actions { display: flex; align-items: center; gap: var(--space-2); }
  .btn-cart { position: relative; gap: var(--space-2); }
  .cart-count {
    min-inline-size: 1.4rem; block-size: 1.4rem; padding-inline: .35rem;
    display: grid; place-items: center;
    background: var(--rose); color: var(--n-0);
    border-radius: var(--radius-full);
    font-size: var(--text-2xs); font-weight: 600; font-variant-numeric: tabular-nums;
    transition: transform var(--dur) var(--ease-out), background var(--dur) var(--ease-out);
  }
  .cart-count[data-empty="true"] { background: var(--n-300); color: var(--n-700); }
  .cart-count[data-bump] { animation: bump 380ms var(--ease-out); }
  @keyframes bump { 40% { transform: scale(1.35); } }

  .nav-toggle { display: none; padding: var(--space-2); border-radius: var(--radius-sm); }
  .nav-toggle-bars { display: grid; gap: 6px; inline-size: 1.6rem; }
  .nav-toggle-bars i {
    display: block; block-size: 2px; background: var(--text); border-radius: 2px;
    transition: transform var(--dur) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
  }
  /* Bars are 2px with 6px between them, so the outer two sit 8px from the middle. */
  .nav-toggle[aria-expanded="true"] i:nth-child(1) { transform: translateY(8px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] i:nth-child(2) { opacity: 0; }
  .nav-toggle[aria-expanded="true"] i:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }
  .btn-cart svg { inline-size: 1.4rem; block-size: 1.4rem; }

  @media (max-width: 63.99rem) {
    .btn-cart-label { display: none; }
    .nav-toggle { display: block; }
    .nav {
      position: fixed; inset: var(--header-h) 0 auto 0;
      flex-direction: column; align-items: stretch; gap: 0;
      background: var(--surface-raised);
      border-block-end: 1px solid var(--border);
      box-shadow: var(--shadow-lg);
      padding: var(--space-3) var(--space-5) var(--space-6);
      padding-inline: max(var(--space-5), env(safe-area-inset-left, 0px)) max(var(--space-5), env(safe-area-inset-right, 0px));
      transform: translateY(-8px); opacity: 0; pointer-events: none;
      transition: transform var(--dur) var(--ease-out), opacity var(--dur) var(--ease-out);
      /* JS sets --nav-max to what is left below the header (which may sit
         under the top strip), so the last row never ends up off screen. */
      max-block-size: var(--nav-max, calc(100svh - var(--header-h))); overflow-y: auto;
      overscroll-behavior: contain;
    }
    .nav[data-open] { transform: translateY(0); opacity: 1; pointer-events: auto; }
    .nav a { padding-block: var(--space-4); border-block-end: 1px solid var(--border); font-size: var(--text-lg); }
    .nav a::after { display: none; }
    .nav-trade { margin-block-start: var(--space-4); text-align: center; border-block-end: 1px solid var(--gold-line) !important; }
  }

  /* ------------------------------------------------------------- hero -- */
  .hero { position: relative; overflow: hidden; padding-block: clamp(3rem, 8vw, 6.5rem) clamp(3rem, 7vw, 5.5rem); }
  .hero::before {
    content: ""; position: absolute; inset: 0; z-index: -1;
    background:
      radial-gradient(70% 55% at 78% 12%, var(--rose-soft), transparent 62%),
      radial-gradient(55% 45% at 8% 88%, var(--gold-soft), transparent 60%);
  }
  .hero-grid {
    display: grid; gap: clamp(2.5rem, 5vw, var(--space-10));
    grid-template-columns: 1fr; align-items: center;
  }
  @media (min-width: 62rem) { .hero-grid { grid-template-columns: 1.05fr .95fr; } }

  .hero h1 { font-size: var(--text-4xl); font-weight: 300; }
  .hero h1 em { font-style: italic; color: var(--rose); }
  .hero-copy > * + * { margin-block-start: var(--space-5); }
  .hero-copy .lede { max-width: 46ch; }
  .hero-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }

  .hero-facts {
    display: flex; flex-wrap: wrap; gap: var(--space-5) var(--space-6);
    padding-block-start: var(--space-5); border-block-start: 1px solid var(--border);
  }
  .hero-fact strong {
    display: block; font-family: var(--font-display); font-size: var(--text-xl);
    font-weight: 500; line-height: 1.1;
  }
  .hero-fact span { font-size: var(--text-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted); }

  .hero-art { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
  .hero-art .frame:nth-child(1) { grid-row: span 2; aspect-ratio: 3 / 4.4; }
  .hero-art .frame:nth-child(2) { aspect-ratio: 4 / 3; }
  .hero-art .frame:nth-child(3) { aspect-ratio: 4 / 3; }
  .frame {
    border-radius: var(--radius-lg); overflow: hidden;
    box-shadow: var(--shadow-lg); background: var(--n-100);
    position: relative;
  }
  .frame img { inline-size: 100%; block-size: 100%; object-fit: cover; }

  /* ---------------------------------------------------- image / phold -- */
  .ph {
    position: absolute; inset: 0;
    display: grid; place-items: center; gap: var(--space-3);
    background:
      radial-gradient(120% 90% at 30% 15%, oklch(1 0 0 / .55), transparent 60%),
      linear-gradient(155deg, var(--ph-a, var(--rose-soft)), var(--ph-b, var(--gold-soft)));
    text-align: center; padding: var(--space-4);
  }
  .ph::before {
    content: ""; inline-size: clamp(2.5rem, 22%, 4.5rem); aspect-ratio: 1;
    background: var(--n-800); opacity: .16;
    -webkit-mask: url('/assets/img/brand/mark.svg') center / contain no-repeat;
    mask: url('/assets/img/brand/mark.svg') center / contain no-repeat;
  }
  .ph span {
    font-size: var(--text-2xs); letter-spacing: .18em; text-transform: uppercase;
    color: var(--n-700); opacity: .7;
  }
  [data-cat="cups"]   { --ph-a: oklch(.93 .055 5);   --ph-b: oklch(.95 .045 60); }
  [data-cat="tarts"]  { --ph-a: oklch(.93 .06 60);   --ph-b: oklch(.95 .04 100); }
  [data-cat="mochi"]  { --ph-a: oklch(.94 .045 135); --ph-b: oklch(.93 .04 50); }
  [data-cat="fresh-towers"] { --ph-a: oklch(.92 .05 120); --ph-b: oklch(.95 .04 95); }
  [data-cat="towers"] { --ph-a: oklch(.93 .05 5);    --ph-b: oklch(.92 .035 45); }
  [data-cat="cakes"]  { --ph-a: oklch(.93 .05 5);    --ph-b: oklch(.95 .035 77); }
  [data-cat="cake-designs"] { --ph-a: oklch(.94 .035 30); --ph-b: oklch(.96 .025 85); }
  [data-cat="tables"] { --ph-a: oklch(.94 .04 77);   --ph-b: oklch(.93 .05 120); }

  /* -------------------------------------------------- category cards -- */
  .cat-grid { display: grid; gap: var(--space-5); grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); }
  .cat-card {
    position: relative; display: grid; gap: var(--space-4);
    padding: var(--space-5); background: var(--surface-raised);
    border: 1px solid var(--border); border-radius: var(--radius-lg);
    text-decoration: none; overflow: hidden;
    transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
  }
  .cat-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--rose-line); }
  /* Fixed 4:5 frame, photo shown whole (contain, not cover). No hover zoom —
     scaling a photo inside its frame trims the edges. */
  .cat-card-media { position: relative; aspect-ratio: 4 / 5; border-radius: var(--radius); overflow: hidden; background: var(--n-100); }
  .cat-card-media img { inline-size: 100%; block-size: 100%; object-fit: contain; }
  .cat-card h3 { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 400; letter-spacing: -.01em; }
  .cat-card p { font-size: var(--text-sm); color: var(--text-muted); }
  .cat-card-foot {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
    font-size: var(--text-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--rose);
  }

  /* ---------------------------------------------------- product cards -- */
  .filters {
    display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center;
    padding-block: var(--space-4);
    position: sticky; inset-block-start: var(--header-h); z-index: 20;
    background: color-mix(in oklch, var(--surface) 92%, transparent);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    margin-block-end: var(--space-6);
  }
  /* On a phone the categories become one swipeable row rather than three
     stacked lines that push the products off the screen. */
  @media (max-width: 47.99rem) {
    .filters {
      flex-wrap: nowrap; overflow-x: auto; scroll-snap-type: x proximity;
      scrollbar-width: none; -ms-overflow-style: none;
      margin-inline: calc(var(--gutter, 1.25rem) * -1);
      padding-inline: var(--gutter, 1.25rem);
      /* Without this, snapping lines the first chip up with the screen edge
         and it looks cut off. */
      scroll-padding-inline: var(--gutter, 1.25rem);
      -webkit-overflow-scrolling: touch;
    }
    .filters::-webkit-scrollbar { display: none; }
  }
  .chip {
    display: inline-flex; align-items: center; gap: var(--space-2);
    min-block-size: var(--tap); padding-inline: var(--space-5);
    border: 1px solid var(--border); border-radius: var(--radius-full);
    background: var(--surface-raised); color: var(--text-muted);
    font-size: var(--text-sm); font-weight: 500;
    text-decoration: none; white-space: nowrap; scroll-snap-align: start;
    transition: all var(--dur-fast) var(--ease-out);
  }
  .chip:active { transform: scale(.96); }
  .chip:hover { border-color: var(--border-strong); color: var(--text); }
  .chip[aria-pressed="true"], .chip[aria-current="page"] {
    background: var(--surface-ink); border-color: var(--surface-ink); color: var(--n-50);
  }
  .chip-count { font-size: var(--text-2xs); opacity: .65; font-variant-numeric: tabular-nums; }

  .product-grid {
    display: grid; gap: var(--space-5);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 16.5rem), 1fr));
  }
  .card {
    container-type: inline-size;
    display: flex; flex-direction: column;
    background: var(--surface-raised);
    border: 1px solid var(--border); border-radius: var(--radius-lg);
    overflow: hidden; text-align: start;
    transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
  }
  .card:hover, .card:focus-within { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--berry-line); }
  .card:has(a:active) { transform: translateY(-1px) scale(.99); box-shadow: var(--shadow); }
  /* Same rule as the product view and category cards: a fixed 4:5 frame with
     the photo shown whole. No hover zoom — scaling inside the frame trims it. */
  .card-media { position: relative; aspect-ratio: 4 / 5; background: var(--n-100); overflow: hidden; }
  .card-media img { inline-size: 100%; block-size: 100%; object-fit: contain; }
  .card-body { padding: var(--space-4) var(--space-4) var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); flex: 1; }
  .card-title { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; letter-spacing: -.012em; line-height: 1.22; }
  .card-title a { text-decoration: none; }
  .card-title a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
  .card { position: relative; }
  .card-desc {
    font-size: var(--text-sm); color: var(--text-muted);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  .card-foot {
    margin-block-start: auto; padding-block-start: var(--space-3);
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
    border-block-start: 1px solid var(--border);
  }
  .price { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
  .price-unit { font-family: var(--font-sans); font-size: var(--text-xs); color: var(--text-muted); }
  .card-foot > span:first-child { pointer-events: none; }
  .card-cta {
    font-size: var(--text-xs); font-weight: 600; color: var(--berry);
    display: inline-flex; align-items: center; gap: .3rem;
    pointer-events: none;
  }
  .card-cta::after { content: "→"; transition: transform var(--dur) var(--ease-out); }
  .card:hover .card-cta::after { transform: translateX(3px); }

  .badge {
    position: absolute; inset-block-start: var(--space-3); inset-inline-start: var(--space-3);
    z-index: 2; padding: .3rem var(--space-3); pointer-events: none;
    background: color-mix(in oklch, var(--n-0) 92%, transparent);
    backdrop-filter: blur(6px);
    border-radius: var(--radius-full);
    font-size: var(--text-2xs); letter-spacing: .12em; text-transform: uppercase; font-weight: 500;
    box-shadow: var(--shadow-xs);
  }
  .badge-inline { position: static; display: inline-block; background: var(--rose-soft); color: var(--rose-active); }

  /* --------------------------------------------------------- surfaces -- */
  .panel {
    background: var(--surface-raised); border: 1px solid var(--border);
    border-radius: var(--radius-lg); padding: clamp(var(--space-5), 4vw, var(--space-8));
  }
  .panel-sunken { background: var(--n-100); border-color: var(--n-200); }
  .panel-gold { background: var(--gold-soft); border-color: var(--gold-line); }
  .panel-rose { background: var(--rose-soft); border-color: var(--rose-line); }

  .note {
    display: flex; gap: var(--space-3); align-items: flex-start;
    padding: var(--space-4); border-radius: var(--radius);
    background: var(--gold-soft); border: 1px solid var(--gold-line);
    font-size: var(--text-sm);
  }
  .note-icon { flex: none; inline-size: 1.15rem; block-size: 1.15rem; margin-block-start: .18rem; color: var(--n-700); }
  .note-danger { background: var(--danger-soft); border-color: color-mix(in oklch, var(--danger) 30%, transparent); }
  .note-ok { background: var(--ok-soft); border-color: color-mix(in oklch, var(--ok) 30%, transparent); }

  /* ------------------------------------------------------------ forms -- */
  .field { display: grid; gap: var(--space-2); }
  .field > label, .field-label {
    font-size: var(--text-xs); font-weight: 500; letter-spacing: .1em;
    text-transform: uppercase; color: var(--text-muted);
  }
  .field-hint { font-size: var(--text-xs); color: var(--text-faint); }
  .field-error { font-size: var(--text-xs); color: var(--danger); display: flex; gap: var(--space-2); align-items: center; }

  .input, .select, .textarea {
    inline-size: 100%; min-block-size: 3rem;
    padding: var(--space-3) var(--space-4);
    background: var(--surface-raised);
    border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
    font-size: var(--text-base); font-weight: 300; color: var(--text);
    transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
  }
  .textarea { min-block-size: 6.5rem; resize: vertical; line-height: 1.55; }
  .input::placeholder, .textarea::placeholder { color: var(--n-400); }
  .input:hover, .select:hover, .textarea:hover { border-color: var(--n-400); }
  .input:focus-visible, .select:focus-visible, .textarea:focus-visible {
    outline: none; border-color: var(--rose);
    box-shadow: 0 0 0 3px color-mix(in oklch, var(--rose) 18%, transparent);
  }
  .input[aria-invalid="true"], .textarea[aria-invalid="true"], .select[aria-invalid="true"] {
    border-color: var(--danger); background: color-mix(in oklch, var(--danger-soft) 60%, var(--surface-raised));
  }
  .select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%237a6455' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--space-4) center;
    background-size: .7rem;
    padding-inline-end: var(--space-8);
  }
  .field:has(.select) { position: relative; }

  .form-grid { display: grid; gap: var(--space-4); }
  @media (min-width: 40rem) { .form-grid-2 { grid-template-columns: 1fr 1fr; } }

  .checkline { display: flex; gap: var(--space-3); align-items: flex-start; font-size: var(--text-sm); cursor: pointer; }
  .checkline input { inline-size: 1.15rem; block-size: 1.15rem; accent-color: var(--rose); margin-block-start: .22rem; flex: none; }

  /* ---------------------------------------------------- modal & drawer -- */
  .scrim {
    position: fixed; inset: 0; z-index: 90;
    background: oklch(.22 .028 36 / .55);
    backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
    animation: fade var(--dur) var(--ease-out);
  }
  @keyframes fade { from { opacity: 0; } }

  .modal {
    position: fixed; z-index: 100; inset-block-start: 50%; inset-inline-start: 50%;
    transform: translate(-50%, -50%);
    inline-size: min(100% - 2rem, 62rem);
    max-block-size: min(90svh, 52rem);
    background: var(--surface-raised); border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl); overflow: hidden;
    display: grid; grid-template-rows: 1fr;
    animation: pop var(--dur-slow) var(--ease-out);
  }
  @keyframes pop { from { opacity: 0; transform: translate(-50%, calc(-50% + 14px)) scale(.975); } }

  .modal-close {
    position: absolute; z-index: 3; inset-block-start: var(--space-4); inset-inline-end: var(--space-4);
    inline-size: 2.4rem; block-size: 2.4rem; display: grid; place-items: center;
    border-radius: var(--radius-full);
    background: color-mix(in oklch, var(--n-0) 88%, transparent);
    box-shadow: var(--shadow-sm);
    transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  }
  .modal-close:hover { background: var(--n-0); transform: rotate(90deg); }

  .drawer {
    position: fixed; z-index: 100; inset-block: 0; inset-inline-end: 0;
    inline-size: min(100%, 27rem);
    padding-inline-end: env(safe-area-inset-right, 0px);   /* clear of a sideways notch */
    background: var(--surface-raised); box-shadow: var(--shadow-xl);
    display: grid; grid-template-rows: auto 1fr auto;
    animation: slide-in var(--dur-slow) var(--ease-out);
  }
  @keyframes slide-in { from { transform: translateX(100%); } }
  .drawer-head {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
    padding: var(--space-5); border-block-end: 1px solid var(--border);
  }
  .drawer-head h2 { font-size: var(--text-xl); }
  .drawer-body { overflow-y: auto; padding: var(--space-5); display: grid; gap: var(--space-4); align-content: start; }
  .drawer-foot { padding: var(--space-5); border-block-start: 1px solid var(--border); background: var(--n-50); display: grid; gap: var(--space-4); }

  @media (prefers-reduced-motion: reduce) {
    .scrim, .modal, .drawer { animation: none; }
    * { scroll-behavior: auto !important; }
  }

  /* ------------------------------------------------------ product view -- */
  .pv { display: grid; grid-template-columns: 1fr; overflow-y: auto; }
  /* Desktop: the photo is a true 4:5 frame, and the details panel takes its
     height from the photo and scrolls inside it — so the photo is never
     stretched to the height of the text and cropped to fit. */
  @media (min-width: 52rem) {
    .pv { grid-template-columns: auto minmax(0, 1fr); overflow: hidden; }
    .pv-panel { contain: size; }
  }

  .pv-media { position: relative; background: var(--surface-raised); min-block-size: 16rem; }
  @media (min-width: 52rem) {
    /* Sized from the viewport so it always fits on screen, width follows 4:5. */
    .pv-media { aspect-ratio: 4 / 5; block-size: min(40rem, 86svh, 58vw); min-block-size: 0; }
  }
  /* contain, not cover: a 4:5 photo fills the frame exactly, and a photo of
     any other shape is shown whole rather than trimmed. */
  .pv-media img { inline-size: 100%; block-size: 100%; object-fit: contain; }
  .pv-thumbs {
    position: absolute; inset-block-end: var(--space-4); inset-inline: var(--space-4);
    display: flex; gap: var(--space-2); overflow-x: auto; padding-block: var(--space-1);
  }
  .pv-thumb {
    inline-size: 3.4rem; block-size: 3.4rem; flex: none; border-radius: var(--radius-sm);
    overflow: hidden; border: 2px solid transparent; box-shadow: var(--shadow);
    transition: border-color var(--dur-fast) var(--ease-out);
  }
  .pv-thumb[aria-pressed="true"] { border-color: var(--n-0); }
  .pv-thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }

  .pv-panel { display: grid; grid-template-rows: 1fr auto; overflow: hidden; }
  .pv-scroll { overflow-y: auto; padding: clamp(var(--space-5), 3vw, var(--space-8)); display: grid; gap: var(--space-5); align-content: start; }
  .pv-title { font-size: var(--text-2xl); font-weight: 400; }
  .pv-price { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
  .pv-price .price { font-size: var(--text-xl); }

  .specs { display: grid; gap: var(--space-2); }
  .spec {
    display: flex; justify-content: space-between; gap: var(--space-4);
    padding-block: var(--space-2); border-block-end: 1px dashed var(--border);
    font-size: var(--text-sm);
  }
  .spec dt { color: var(--text-muted); }
  .spec dd { font-weight: 400; text-align: end; }

  /* One compact row — the estimate on the left, the button on the right — so
     the options above keep as much of the screen as possible. */
  .pv-foot {
    padding: var(--space-3) var(--space-5); border-block-start: 1px solid var(--border);
    background: var(--n-50);
    display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center;
    gap: var(--space-1) var(--space-4);
  }
  .pv-foot .pv-total { display: grid; gap: .1rem; min-inline-size: 0; }
  .pv-foot .pv-total .price { font-size: var(--text-xl); line-height: 1.1; }
  .pv-foot .pv-total-label { font-size: var(--text-2xs); }
  .pv-add { min-block-size: 3rem; padding-inline: var(--space-5); white-space: nowrap; }
  .pv-hint { grid-column: 1 / -1; margin: 0; font-size: var(--text-xs); }
  .pv-hint:empty { display: none; }
  @media (max-width: 51.99rem) { .pv-hint[data-generic] { display: none; } }
  .pv-total { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); }
  .pv-total .price { font-size: var(--text-2xl); }
  .pv-total-label { font-size: var(--text-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted); }

  /* -------------------------------------------------------- cart lines -- */
  .line { display: grid; grid-template-columns: 4.25rem 1fr; gap: var(--space-3); align-items: start; }
  .line-media { aspect-ratio: 1; border-radius: var(--radius-sm); overflow: hidden; position: relative; background: var(--n-100); }
  .line-media img { inline-size: 100%; block-size: 100%; object-fit: cover; }
  .line-media .ph::before { inline-size: 45%; }
  .line-media .ph span { display: none; }
  .line-name { font-weight: 400; font-size: var(--text-sm); }
  .line-opts { font-size: var(--text-xs); color: var(--text-muted); }
  .line-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-block-start: var(--space-2); }
  .line-price { font-variant-numeric: tabular-nums; font-size: var(--text-sm); }
  .btn-x {
    font-size: var(--text-xs); color: var(--text-muted); text-decoration: underline;
    text-underline-offset: .2em;
    min-block-size: 2.25rem; padding-inline: var(--space-2);
    display: inline-flex; align-items: center;
  }
  .btn-x:active { transform: scale(.95); }
  .btn-x:hover { color: var(--danger); }

  .empty-state { display: grid; gap: var(--space-4); justify-items: center; text-align: center; padding-block: var(--space-10); color: var(--text-muted); }
  .empty-state .brand-mark { opacity: .35; }

  /* ---------------------------------------------------------- tables -- */
  .table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-raised); }
  table.data { inline-size: 100%; border-collapse: collapse; font-size: var(--text-sm); min-inline-size: 34rem; }
  table.data th, table.data td { padding: var(--space-3) var(--space-4); text-align: start; border-block-end: 1px solid var(--border); }
  table.data th {
    font-size: var(--text-xs); letter-spacing: .1em; text-transform: uppercase;
    color: var(--text-muted); font-weight: 500; background: var(--n-50);
  }
  table.data tbody tr:last-child td { border-block-end: 0; }
  table.data tbody tr:hover { background: var(--n-50); }
  table.data .num { text-align: end; font-variant-numeric: tabular-nums; }
  .save-tag {
    display: inline-block; padding: .1rem .5rem; border-radius: var(--radius-full);
    background: var(--ok-soft); color: color-mix(in oklch, var(--ok) 75%, black);
    font-size: var(--text-2xs); letter-spacing: .06em;
  }

  /* --------------------------------------------------------- accordion -- */
  .acc { border-block-end: 1px solid var(--border); }
  .acc summary {
    display: flex; justify-content: space-between; align-items: center; gap: var(--space-4);
    padding-block: var(--space-4); cursor: pointer; list-style: none;
    font-size: var(--text-lg); font-family: var(--font-display); font-weight: 500;
  }
  .acc summary::-webkit-details-marker { display: none; }
  .acc summary::after {
    content: ""; inline-size: .65rem; block-size: .65rem; flex: none;
    border-inline-end: 1.5px solid var(--text-muted); border-block-end: 1.5px solid var(--text-muted);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform var(--dur) var(--ease-out);
  }
  .acc[open] summary::after { transform: rotate(225deg) translate(-2px, -2px); }
  .acc-body { padding-block-end: var(--space-5); color: var(--text-muted); max-width: 68ch; }
  .acc-body > * + * { margin-block-start: var(--space-3); }

  /* -------------------------------------------------------------- gate -- */
  .gate { display: grid; place-items: center; padding-block: clamp(3rem, 8vw, var(--space-12)); }
  .gate-card {
    inline-size: min(100%, 27rem); display: grid; gap: var(--space-5);
    padding: clamp(var(--space-6), 5vw, var(--space-8));
    background: var(--surface-raised); border: 1px solid var(--border);
    border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
    text-align: center; justify-items: center;
  }
  .gate-card form { inline-size: 100%; display: grid; gap: var(--space-4); text-align: start; }
  .lock-ring {
    inline-size: 3.5rem; block-size: 3.5rem; display: grid; place-items: center;
    border-radius: var(--radius-full); background: var(--gold-soft);
    border: 1px solid var(--gold-line); color: var(--n-700);
  }

  /* ------------------------------------------------------------- toast -- */
  .toast-root {
    position: fixed; z-index: 200; inset-block-end: var(--space-5); inset-inline: 0;
    display: grid; gap: var(--space-2); justify-items: center; pointer-events: none;
    padding-inline: var(--space-4);
  }
  .toast {
    display: flex; align-items: center; gap: var(--space-3);
    padding: var(--space-3) var(--space-5);
    background: var(--surface-ink); color: var(--n-50);
    border-radius: var(--radius-full); box-shadow: var(--shadow-xl);
    font-size: var(--text-sm); pointer-events: auto;
    animation: toast-in var(--dur-slow) var(--ease-out);
  }
  .toast[data-tone="error"] { background: var(--danger); }
  .toast[data-tone="ok"] { background: color-mix(in oklch, var(--ok) 82%, black); }
  .toast[data-leaving] { animation: toast-out var(--dur) var(--ease-in-out) forwards; }
  @keyframes toast-in { from { opacity: 0; transform: translateY(14px) scale(.96); } }
  @keyframes toast-out { to { opacity: 0; transform: translateY(8px) scale(.97); } }

  /* ------------------------------------------------------------ footer -- */
  /* The page runs under the iPhone's home bar (viewport-fit=cover), so the
     footer pads itself by that strip and its own colour fills it. */
  .site-footer { background: var(--surface-ink); color: var(--n-300); padding-block-end: env(safe-area-inset-bottom, 0px); }
  .footer-grid {
    display: grid; gap: var(--space-8);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
    padding-block: clamp(3rem, 6vw, var(--space-10));
  }
  .footer-brand { grid-column: span 1; }
  @media (min-width: 62rem) { .footer-brand { grid-column: span 1; max-inline-size: 22rem; } }
  .footer-brand .brand-mark { color: var(--gold); margin-block-end: var(--space-4); }
  .footer-tagline { font-family: var(--font-display); font-size: var(--text-lg); color: var(--n-100); }
  .footer-allergen { font-size: var(--text-xs); color: var(--n-500); margin-block-start: var(--space-4); }
  .footer-col h2 {
    font-family: var(--font-sans); font-size: var(--text-xs); letter-spacing: .16em;
    text-transform: uppercase; color: var(--gold); font-weight: 500; margin-block-end: var(--space-4);
  }
  .footer-col ul { display: grid; gap: var(--space-3); list-style: none; padding: 0; }
  .footer-col a { font-size: var(--text-sm); text-decoration: none; color: var(--n-300); transition: color var(--dur-fast) var(--ease-out); }
  .footer-col a:hover { color: var(--n-0); }
  .footer-col li { font-size: var(--text-sm); }
  .footer-base {
    display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: space-between;
    padding-block: var(--space-5); border-block-start: 1px solid oklch(1 0 0 / .1);
    font-size: var(--text-xs); color: var(--n-500);
  }
  .footer-admin {
    text-decoration: none; color: var(--n-500);
    min-block-size: 2.5rem; display: inline-flex; align-items: center;
    padding-inline: var(--space-2); margin-inline: calc(var(--space-2) * -1);
  }
  .footer-admin:hover { color: var(--peach-whip); }
  .footer-base p { min-block-size: 2.5rem; display: flex; align-items: center; }

  /* The big Asmaa Desserts lockup at the top of the footer, on the left,
     with a hairline between it and the columns below. */
  .footer-logo {
    display: flex; align-items: center; justify-content: flex-start;
    gap: clamp(.9rem, 3vw, 2.5rem);
    padding-block: clamp(3rem, 6vw, 5rem) clamp(2rem, 4vw, 3rem);
    border-block-end: 1px solid oklch(1 0 0 / .1);
  }
  .footer-logo-mark {
    inline-size: clamp(4.25rem, 12vw, 9.5rem); block-size: clamp(4.25rem, 12vw, 9.5rem);
    color: var(--gold);
  }
  .footer-logo-words { display: grid; line-height: .9; }
  .footer-logo-name {
    font-family: var(--font-display); font-weight: 600; letter-spacing: -.03em;
    font-size: clamp(3.75rem, 15vw, 12rem); color: var(--n-100);
  }
  .footer-logo-sub {
    font-size: clamp(.75rem, 2.4vw, 1.9rem); font-weight: 500;
    letter-spacing: .55em; text-transform: uppercase; color: var(--gold);
    margin-block-start: clamp(.4rem, 1.2vw, 1rem); padding-inline-start: .3em;
  }

  /* -------------------------------------------------------------- misc -- */
  .breadcrumb {
    display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap;
    font-size: var(--text-xs); color: var(--text-muted); font-weight: 500;
  }
  .breadcrumb a { text-decoration: none; }
  .breadcrumb a:hover { color: var(--rose); }

  .page-head { padding-block: clamp(2.5rem, 5vw, var(--space-10)) var(--space-6); }
  .page-head h1 { margin-block-start: var(--space-4); }
  .page-head .lede { margin-block-start: var(--space-4); max-width: 56ch; }

  .steps { display: grid; gap: var(--space-6); grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); counter-reset: step; }
  .step { counter-increment: step; display: grid; gap: var(--space-3); }
  .step::before {
    content: counter(step, decimal-leading-zero);
    font-family: var(--font-display); font-size: var(--text-xl); color: var(--rose);
  }
  .step h3 { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 500; }
  .step p { font-size: var(--text-sm); color: var(--text-muted); }
  .section-ink .step p { color: var(--n-400); }
  .section-ink .step::before { color: var(--gold); }

  .quote-band { display: grid; gap: var(--space-5); justify-items: center; text-align: center; }
  /* "Start an order" closes most pages. Sections bring their own padding;
     plain page content (menu grid, FAQ) needs room before the band. */
  main > :not(.section) + .cta-band { margin-block-start: clamp(3.5rem, 7vw, var(--space-12)); }
  .quote-band blockquote { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 300; font-style: italic; max-width: 30ch; line-height: 1.28; }
  .quote-band cite { font-style: normal; font-size: var(--text-xs); letter-spacing: .18em; text-transform: uppercase; color: var(--text-muted); }

  .split { display: grid; gap: clamp(2rem, 5vw, var(--space-10)); align-items: center; }
  @media (min-width: 55rem) { .split { grid-template-columns: 1fr 1fr; } .split-media-first > :first-child { order: -1; } }
  /* Title, photos, then text on a phone; photos beside title and text on a
     wider screen. */
  .split-titled { row-gap: var(--space-6); }
  @media (min-width: 55rem) {
    .split-titled { grid-template-areas: "art head" "art body"; row-gap: var(--space-5); align-items: start; }
    .split-titled > .hero-art { grid-area: art; align-self: center; }
    .split-titled > .split-head { grid-area: head; align-self: end; }
    .split-titled > .split-body { grid-area: body; }
  }

  /* ------------------------------------------------------------- admin -- */
  .admin-shell { display: grid; gap: var(--space-6); grid-template-columns: 1fr; }
  @media (min-width: 60rem) { .admin-shell { grid-template-columns: 14rem 1fr; align-items: start; } }
  .admin-nav { display: flex; flex-wrap: wrap; gap: var(--space-2); }
  @media (min-width: 60rem) {
    .admin-nav { flex-direction: column; position: sticky; inset-block-start: calc(var(--header-h) + 1rem); }
    .admin-nav .chip { justify-content: flex-start; inline-size: 100%; }
  }
  .admin-list { display: grid; gap: var(--space-2); }
  .admin-row {
    display: grid; grid-template-columns: 3.25rem 1fr auto; gap: var(--space-4); align-items: center;
    padding: var(--space-3); background: var(--surface-raised);
    border: 1px solid var(--border); border-radius: var(--radius);
    transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
  }
  .admin-row:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
  .admin-row[data-inactive] { opacity: .55; }
  .admin-thumb { aspect-ratio: 1; border-radius: var(--radius-xs); overflow: hidden; position: relative; background: var(--n-100); }
  .admin-thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }
  .admin-thumb .ph span { display: none; }
  .admin-thumb .ph::before { inline-size: 55%; }
  .admin-row-meta { min-inline-size: 0; }
  .admin-row-name { font-size: var(--text-sm); font-weight: 400; }
  .admin-row-sub { font-size: var(--text-xs); color: var(--text-muted); }

  .dropzone {
    display: grid; place-items: center; gap: var(--space-3);
    padding: var(--space-6); text-align: center;
    border: 1.5px dashed var(--border-strong); border-radius: var(--radius);
    background: var(--n-50); color: var(--text-muted); font-size: var(--text-sm);
    transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
    cursor: pointer;
  }
  .dropzone:hover, .dropzone[data-over] { border-color: var(--rose); background: var(--rose-soft); color: var(--rose-active); }

  .img-grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr)); }
  .img-tile { position: relative; aspect-ratio: 1; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--border); }
  .img-tile img { inline-size: 100%; block-size: 100%; object-fit: cover; }
  .img-tile-bar {
    position: absolute; inset-block-end: 0; inset-inline: 0;
    display: flex; justify-content: space-between; gap: var(--space-1); padding: var(--space-1);
    background: linear-gradient(to top, oklch(.22 .028 36 / .78), transparent);
    opacity: 0; transition: opacity var(--dur-fast) var(--ease-out);
  }
  .img-tile:hover .img-tile-bar, .img-tile:focus-within .img-tile-bar { opacity: 1; }
  .img-tile-bar button {
    font-size: var(--text-2xs); color: var(--n-0); padding: .15rem .4rem;
    border-radius: var(--radius-xs); background: oklch(0 0 0 / .35);
  }
  .img-tile-bar button:hover { background: oklch(0 0 0 / .6); }
  .img-tile[data-primary]::after {
    content: "Main"; position: absolute; inset-block-start: var(--space-1); inset-inline-start: var(--space-1);
    background: var(--rose); color: var(--n-0); font-size: var(--text-2xs);
    padding: .1rem .4rem; border-radius: var(--radius-xs); letter-spacing: .06em;
  }

  .opt-editor { display: grid; gap: var(--space-3); padding: var(--space-4); border: 1px solid var(--border); border-radius: var(--radius); background: var(--n-50); }
  .opt-choice-row { display: grid; grid-template-columns: 1fr 6rem auto; gap: var(--space-2); align-items: center; }

  .sticky-save {
    position: sticky; inset-block-end: 0; z-index: 30;
    display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; justify-content: space-between;
    padding: var(--space-4); margin-block-start: var(--space-5);
    background: color-mix(in oklch, var(--surface-raised) 92%, transparent);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--border); border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
  }
  .dirty-dot { display: inline-block; inline-size: .5rem; block-size: .5rem; border-radius: 99px; background: var(--warn); margin-inline-end: var(--space-2); }

  /* ---------------------------------------------------------- reveal -- */
  .reveal { opacity: 0; transform: translateY(16px); }
  .reveal[data-shown] {
    opacity: 1; transform: none;
    transition: opacity 620ms var(--ease-out), transform 620ms var(--ease-out);
    transition-delay: var(--reveal-delay, 0ms);
  }
  @media (prefers-reduced-motion: reduce) {
    .reveal, .reveal[data-shown] { opacity: 1; transform: none; transition: none; }
  }
}

/* ======================================================== UTILITIES ==== */
@layer utilities {
  .center { text-align: center; }
  .mt-0 { margin-block-start: 0; }
  .mt-4 { margin-block-start: var(--space-4); }
  .mt-5 { margin-block-start: var(--space-5); }
  .mt-6 { margin-block-start: var(--space-6); }
  .mt-8 { margin-block-start: var(--space-8); }
  .flow-tight { --flow: var(--space-2); }
  .flow-loose { --flow: var(--space-5); }
  .full { inline-size: 100%; }
  .hide { display: none !important; }
  @media (max-width: 47.99rem) { .hide-sm { display: none !important; } }
}

/* ============================================================ PRINT ==== */
@media print {
  .site-header, .site-footer, .announce, .filters, .toast-root,
  .skip-link, .hero-actions, .btn { display: none !important; }
  .reveal { opacity: 1 !important; transform: none !important; }
  body { background: #fff; }
  .card, .panel { break-inside: avoid; border-color: #ddd; }
  a[href^="#"]::after { content: ""; }
}

/* ==================================================== MOBILE & TOUCH ==== */
/* Re-opening the layer so these rules keep the component layer's ordering. */
@layer components {

  /* ---------------------------------------- persistent order bar (phone) */
  /* On a phone the header cart button scrolls away, and people lose track of
     what they have chosen. This bar only appears once something is in the
     list, so it never steals space from an empty state. */
  .order-bar {
    position: fixed; inset-inline: 0; inset-block-end: 0; z-index: 55;
    display: none;
    align-items: center; justify-content: space-between; gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    padding-block-end: max(var(--space-3), env(safe-area-inset-bottom));
    padding-inline: max(var(--space-4), env(safe-area-inset-left, 0px)) max(var(--space-4), env(safe-area-inset-right, 0px));
    background: color-mix(in oklch, var(--surface-raised) 94%, transparent);
    backdrop-filter: blur(16px) saturate(1.3);
    -webkit-backdrop-filter: blur(16px) saturate(1.3);
    border-block-start: 1px solid var(--border);
    box-shadow: 0 -6px 24px oklch(.30 .04 15 / .08);
    animation: bar-up var(--dur-slow) var(--ease-out);
  }
  @keyframes bar-up { from { transform: translateY(100%); } }
  .order-bar[data-show] { display: flex; }
  .order-bar-meta { display: grid; line-height: 1.25; min-inline-size: 0; }
  .order-bar-count { font-size: var(--text-xs); color: var(--text-muted); font-weight: 500; }
  .order-bar-total { font-family: var(--font-display); font-weight: 600; font-size: var(--text-lg); }
  .order-bar .btn { flex: none; }

  @media (min-width: 48rem) { .order-bar { display: none !important; } }
  @media (max-width: 47.99rem) {
    body:has(.order-bar[data-show]) .site-footer { padding-block-end: calc(4.5rem + env(safe-area-inset-bottom, 0px)); }
  }

  /* ------------------------------------------------ bigger phone targets */
  @media (max-width: 63.99rem) {
    .nav a {
      min-block-size: 3.25rem;
      display: flex; align-items: center;
      font-weight: 500;
    }
    .nav a:active { background: var(--berry-soft); }
    .nav-toggle { min-inline-size: var(--tap); min-block-size: var(--tap); display: grid; place-items: center; }
    .btn-cart { min-inline-size: var(--tap); min-block-size: var(--tap); }
    /* The nav drops out of the header row here, and its auto margin was what
       pushed these buttons right — without this they sat next to the logo. */
    .header-actions { margin-inline-start: auto; }
  }

  /* ------------------------------------- modals become sheets on a phone */
  @media (max-width: 51.99rem) {
    .modal {
      inset-block-start: auto; inset-block-end: 0;
      inset-inline-start: 0; transform: none;
      inline-size: 100%; max-block-size: 92svh;
      border-radius: var(--radius-lg) var(--radius-lg) 0 0;
      animation: sheet-up var(--dur-slow) var(--ease-out);
      padding-inline: env(safe-area-inset-left, 0px) env(safe-area-inset-right, 0px);
    }
    @keyframes sheet-up { from { transform: translateY(100%); } }
    .modal-close {
      inset-block-start: var(--space-3); inset-inline-end: max(var(--space-3), env(safe-area-inset-right, 0px));
      inline-size: var(--tap); block-size: var(--tap);
    }
    /* A grab handle reads as "swipe/close" without needing a label. */
    .modal::before {
      content: ""; position: absolute; z-index: 4;
      inset-block-start: .55rem; inset-inline-start: 50%;
      transform: translateX(-50%);
      inline-size: 2.5rem; block-size: .25rem; border-radius: 99px;
      background: var(--n-300);
    }
    /* Phone: the whole sheet scrolls as one — the photo at its true 4:5 shape
       first, then the details — with the price and Add button pinned to the
       bottom so they are always one tap away. */
    .pv { display: block; overflow-y: auto; overscroll-behavior: contain; }
    /* The photo is also capped by the screen height, so the choices — and the
       price bar, which can only stick within them — show on opening, even
       on a phone held sideways. */
    .pv-media {
      aspect-ratio: 4 / 5; min-block-size: 0;
      inline-size: min(100%, 28rem, 36svh); margin-inline: auto;
    }
    .pv-panel { display: block; overflow: visible; }
    .pv-scroll { overflow: visible; padding-block-start: var(--space-5); display: flex; flex-direction: column; }
    .pv-foot { position: sticky; inset-block-end: 0; z-index: 2; }
    .pv-title { font-size: var(--text-xl); }

    /* On a phone, put the choices right under the name. The description and
       specs still follow — they just stop pushing the dropdowns off screen. */
    .pv-scroll > .pv-head    { order: 1; }
    .pv-scroll > .pv-options { order: 2; }
    .pv-scroll > .pv-desc    { order: 3; }
    .pv-scroll > .pv-specs   { order: 4; }
    .pv-scroll > .panel      { order: 5; }
    .pv-scroll > .pv-note-field { order: 6; }
    .pv-scroll > .note       { order: 7; }

    .drawer {
      inline-size: 100%; inset-block-start: 4svh;
      padding-inline-start: env(safe-area-inset-left, 0px);
      border-radius: var(--radius-lg) var(--radius-lg) 0 0;
      animation: sheet-up var(--dur-slow) var(--ease-out);
    }
    .drawer-foot { padding-block-end: max(var(--space-5), env(safe-area-inset-bottom)); }
  }

  /* The sticky action footer inside a sheet must clear the home indicator. */
  .pv-foot { padding-block-end: max(var(--space-3), env(safe-area-inset-bottom)); }

  /* ------------------------------------------------ phone layout tuning */
  @media (max-width: 47.99rem) {
    .hero { padding-block: var(--space-6) var(--space-8); }
    .page-head { padding-block: var(--space-5) var(--space-4); }
    .page-head h1 { margin-block-start: var(--space-2); }
    .page-head .lede { margin-block-start: var(--space-3); font-size: var(--text-base); }
    .hero-art { gap: var(--space-3); }
    .hero-art .frame:nth-child(1) { aspect-ratio: 3 / 4; }
    .hero-actions .btn { flex: 1 1 100%; }
    .hero-facts { gap: var(--space-4) var(--space-5); }

    .product-grid { grid-template-columns: repeat(2, 1fr); gap: var(--space-3); }
    .card-body { padding: var(--space-3) var(--space-3) var(--space-4); }
    .card-desc { -webkit-line-clamp: 2; font-size: var(--text-xs); }
    .card-foot { flex-direction: column; align-items: flex-start; gap: var(--space-1); }

    /* Two big cards a row with the photo on top — the photo is what people
       choose by, so it gets the room (it was a 104px thumbnail). */
    .cat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
    .cat-card { padding: var(--space-3); gap: var(--space-3); border-radius: var(--radius); }
    .cat-card h3 { font-size: var(--text-lg); line-height: 1.2; }
    .cat-card p {
      font-size: var(--text-xs);
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    }
    .cat-card-foot { flex-wrap: wrap; gap: var(--space-1) var(--space-2); font-size: var(--text-2xs); }

    .section-head { margin-block-end: var(--space-6); }
    .steps { gap: var(--space-5); }
    .table-wrap { margin-inline: calc(var(--gutter, 1.25rem) * -1); border-radius: 0; border-inline: 0; }
  }

  /* Very narrow phones: one product per row reads better than two cramped. */
  @media (max-width: 22.5rem) {
    .product-grid { grid-template-columns: 1fr; }
  }

  /* --------------------------------------------------- pointer niceties */
  /* Hover lifts are wrong on touch — they stick after a tap. */
  @media (hover: none) {
    .card:hover, .cat-card:hover { transform: none; box-shadow: var(--shadow-sm); }
    .btn:hover { transform: none; box-shadow: none; }
    .card:hover .card-media img, .cat-card:hover .cat-card-media img { transform: none; }
  }

  /* Give every small control a real hit area even where the ink is small. */
  .footer-col a, .breadcrumb a, .link-arrow {
    min-block-size: 2.5rem; display: inline-flex; align-items: center;
  }
  .footer-col ul { gap: var(--space-1); }
}

/* =================================================== WHOLESALE DESK ==== */
@layer components {
  .ws-jump { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-block-start: var(--space-5); }

  .ws-list { display: grid; gap: var(--space-3); }

  /* Header and rows share one column template so prices line up under their
     "1 dozen / 2 dozen / 3+ dozen" headings. */
  .ws-head, .ws-item {
    display: grid; align-items: center; gap: var(--space-4);
    grid-template-columns: 4.5rem minmax(0, 1fr) repeat(3, 5.75rem) 18rem;
    padding: var(--space-3) var(--space-4);
  }
  .ws-head {
    border: 1px solid transparent; padding-block: 0;
    font-size: var(--text-xs); font-weight: 600; color: var(--text-muted);
    letter-spacing: .06em; text-transform: uppercase;
  }
  .ws-head span:nth-child(3), .ws-head span:nth-child(4), .ws-head span:nth-child(5) { text-align: center; }
  .ws-head span:last-child { text-align: end; }

  .ws-item {
    background: var(--surface-raised);
    border: 1px solid var(--border); border-radius: var(--radius);
    transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
  }
  .ws-item:hover { border-color: var(--berry-line); box-shadow: var(--shadow-sm); }
  .ws-item-simple { grid-template-columns: 4.5rem minmax(0, 1fr) auto auto; }

  .ws-thumb {
    position: relative; display: block; aspect-ratio: 1;
    border-radius: var(--radius-sm); overflow: hidden; background: var(--n-100);
  }
  .ws-thumb img, .ws-card-media img { inline-size: 100%; block-size: 100%; object-fit: cover; }
  .ws-thumb .ph span { display: none; }
  .ws-thumb .ph::before { inline-size: 55%; }

  .ws-info { min-inline-size: 0; }
  .ws-name { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; line-height: 1.2; letter-spacing: -.01em; }
  .ws-name a { text-decoration: none; }
  .ws-name a:hover { color: var(--berry); }
  .ws-meta { font-size: var(--text-xs); color: var(--text-muted); margin-block-start: .2rem; }
  .ws-deal { font-size: var(--text-sm); font-weight: 600; color: var(--olive-deep); }

  .ws-ladder {
    grid-column: 3 / span 3; margin: 0;
    display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4);
  }
  .ws-tier {
    text-align: center; padding: var(--space-2) var(--space-1);
    border-radius: var(--radius-sm);
    transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
  }
  .ws-tier dt { font-size: var(--text-2xs); font-weight: 600; color: var(--text-muted); }
  .ws-tier dd {
    margin: 0; font-family: var(--font-display); font-weight: 600;
    font-size: var(--text-lg); font-variant-numeric: tabular-nums;
  }
  .ws-tier[data-active] {
    background: var(--berry-soft); color: var(--berry-active);
    box-shadow: inset 0 0 0 1.5px var(--berry-line);
  }
  .ws-tier[data-active] dt { color: var(--berry-active); }

  .ws-add { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3); }
  /* Match the stepper's height: a full tap target, and the pair reads as one control. */
  .ws-add-btn { min-inline-size: 7.5rem; min-block-size: var(--tap); }
  .ws-add-btn[data-done] { --btn-bg: var(--olive-deep); }

  /* -------------------------------------------------------- stepper --- */
  .stepper {
    display: inline-flex; align-items: center; flex: none;
    background: var(--surface-raised);
    border: 1px solid var(--border-strong); border-radius: var(--radius-full);
  }
  .stepper-btn {
    inline-size: var(--tap); block-size: var(--tap);
    display: grid; place-items: center; border-radius: var(--radius-full);
    font-size: 1.3rem; line-height: 1; color: var(--text);
    transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  }
  .stepper-btn:hover { background: var(--n-100); }
  .stepper-btn:active { background: var(--berry-soft); transform: scale(.9); }
  .stepper-btn[disabled] { opacity: .3; pointer-events: none; }
  .stepper-val {
    min-inline-size: 4.75rem; text-align: center;
    font-size: var(--text-sm); font-weight: 600; font-variant-numeric: tabular-nums;
  }

  /* ------------------------------------------------ quoted item cards --- */
  .ws-cards { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 15.5rem), 1fr)); }
  .ws-card {
    display: flex; flex-direction: column; overflow: hidden;
    background: var(--surface-raised);
    border: 1px solid var(--border); border-radius: var(--radius-lg);
    transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
  }
  .ws-card:hover { border-color: var(--berry-line); box-shadow: var(--shadow-sm); }
  .ws-card-media { position: relative; display: block; aspect-ratio: 4 / 3; background: var(--n-100); }
  .ws-card-body { display: flex; flex-direction: column; gap: var(--space-2); flex: 1; padding: var(--space-4); }
  .ws-card-body .ws-meta {
    font-size: var(--text-sm);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  .ws-card-body .ws-deal { margin-block-end: var(--space-2); }
  .ws-card-body .btn { margin-block-start: auto; }

  /* --------------------------------------------------------- send band --- */
  .ws-send {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-5);
    padding: clamp(var(--space-5), 3vw, var(--space-6));
    background: var(--rose-soft-bg); border: 1px solid var(--berry-line); border-radius: var(--radius-lg);
  }
  .ws-send-title { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 600; }

  /* On wide screens the column headings carry the tier names. */
  @media (min-width: 64rem) {
    .ws-item:not(.ws-item-simple) .ws-tier dt {
      position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%);
    }
  }

  /* Tablet and phone: each row stacks — photo and name, then the three prices,
     then quantity and Add across the full width. */
  @media (max-width: 63.99rem) {
    .ws-head { display: none; }
    .ws-item, .ws-item-simple {
      grid-template-columns: 4rem minmax(0, 1fr);
      gap: var(--space-3) var(--space-4); padding: var(--space-4);
    }
    .ws-ladder { grid-column: 1 / -1; gap: var(--space-2); }
    .ws-tier { background: var(--n-50); box-shadow: inset 0 0 0 1px var(--border); }
    .ws-deal { grid-column: 1 / -1; }
    .ws-add { grid-column: 1 / -1; justify-content: space-between; }
    .ws-add-btn { flex: 1; }
    .ws-send .btn { inline-size: 100%; }
  }
}

/* ====================================================== HERO PHOTOS ==== */
@layer components {
  .hero-photo { isolation: isolate; }
  .hero-photo > .shell { position: relative; z-index: 1; }

  /* The rotating photos sit behind the copy at half opacity. */
  .hero-bg { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
  .hero-slide {
    position: absolute; inset: 0; inline-size: 100%; block-size: 100%;
    object-fit: cover; object-position: 50% 50%;
    opacity: 0; transition: opacity 1.4s var(--ease-in-out);
  }
  .hero-slide[data-active] { opacity: .5; }

  /* A soft wash of the page colour behind the text side only, so the
     paragraph and the berry accent stay readable over a busy photo. */
  .hero-bg::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(90deg,
      color-mix(in oklch, var(--surface) 78%, transparent) 0%,
      color-mix(in oklch, var(--surface) 50%, transparent) 40%,
      transparent 68%);
  }

  /* With the collage gone the copy keeps its reading width on the left. */
  .hero-photo .hero-grid { grid-template-columns: 1fr; }
  .hero-photo .hero-copy { max-inline-size: 38rem; }

  /* Phone: a 4:5 photo band behind the top of the banner, fading into the
     page so the rest of the copy sits on the plain background. */
  @media (max-width: 47.99rem) {
    .hero-bg {
      inset: 0 0 auto 0; aspect-ratio: 4 / 5;
      -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
              mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
    }
    .hero-slide { object-position: var(--focus, 50% 50%); }
    .hero-bg::after { background: color-mix(in oklch, var(--surface) 25%, transparent); }
  }

  /* Over a half-opacity photo the lighter text drops below readable
     contrast (the paragraph measured 2.6:1 on a phone). Rather than fade the
     photos further, use darker shades of the same colours — in this banner
     only. Measured worst case over all three photos must clear WCAG AA. */
  .hero-photo .eyebrow           { color: oklch(.34 .12 6.5); }     /* deep berry */
  .hero-photo h1 em              { color: var(--berry-active); }
  .hero-photo .lede              { color: var(--text); }
  .hero-photo .hero-fact span    { color: var(--n-700); }

  @media (prefers-reduced-motion: reduce) { .hero-slide { transition: none; } }
}

/* ================================================ ADMIN: CATEGORY PHOTOS */
@layer components {
  .cover-grid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); }
  .cover-card { padding: var(--space-4); display: grid; gap: var(--space-4); align-content: start; }
  /* Same 4:5 frame and contain rule as the home-page card, so what you see
     here is what the customer sees. */
  .cover-preview { position: relative; aspect-ratio: 4 / 5; border-radius: var(--radius); overflow: hidden; background: var(--n-100); }
  .cover-preview img { inline-size: 100%; block-size: 100%; object-fit: contain; }
  .cover-tag {
    position: absolute; inset-block-start: var(--space-2); inset-inline-start: var(--space-2);
    padding: .25rem var(--space-3); border-radius: var(--radius-full);
    background: color-mix(in oklch, var(--n-0) 92%, transparent); box-shadow: var(--shadow-xs);
    font-size: var(--text-2xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  }
  .cover-body { display: grid; gap: var(--space-2); }
  .cover-body h3 { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; }
  .cover-drop { padding: var(--space-4); }
}

/* ====================================================== PHOTO SETS ==== */
@layer components {
  /* A set of photos in one frame; they cross-fade so the card never jumps. */
  .slides { position: absolute; inset: 0; container-type: inline-size; }
  .slides .slide {
    position: absolute; inset: 0; inline-size: 100%; block-size: 100%;
    object-fit: contain; opacity: 0;
    transition: opacity 420ms var(--ease-in-out);
  }
  .slides .slide[data-active] { opacity: 1; }

  /* Liquid-glass arrows: frosted and translucent with a bright top edge.
     They fade in over the photo on hover; touch screens have no hover, so
     there they stay visible. */
  .glass-arrow {
    position: absolute; inset-block-start: 50%; z-index: 3;
    inline-size: 2.5rem; block-size: 2.5rem; margin-block-start: -1.25rem;
    display: grid; place-items: center; border-radius: var(--radius-full);
    color: var(--n-900);
    background: linear-gradient(180deg, oklch(1 0 0 / .62), oklch(1 0 0 / .26));
    border: 1px solid oklch(1 0 0 / .65);
    box-shadow: inset 0 1px 0 oklch(1 0 0 / .85), 0 6px 18px oklch(.3 .04 15 / .2);
    backdrop-filter: blur(14px) saturate(1.6);
    -webkit-backdrop-filter: blur(14px) saturate(1.6);
    opacity: 0; transform: scale(.9);
    transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out), background var(--dur-fast) var(--ease-out);
  }
  .glass-arrow::before { content: ""; position: absolute; inset: -.3rem; } /* bigger tap area */
  .glass-prev { inset-inline-start: var(--space-3); }
  .glass-next { inset-inline-end: var(--space-3); }
  .slides:hover .glass-arrow, .slides:focus-within .glass-arrow { opacity: 1; transform: none; }
  /* On menu and category cards the full-card link lies over the photo, so
     the photo itself never gets the hover — show the arrows for the card. */
  :is(.card, .cat-card):hover .glass-arrow,
  :is(.card, .cat-card):focus-within .glass-arrow { opacity: 1; transform: none; }
  .glass-arrow:hover { background: linear-gradient(180deg, oklch(1 0 0 / .82), oklch(1 0 0 / .45)); }
  .glass-arrow:active { transform: scale(.88); }
  .glass-arrow[disabled] { opacity: .3 !important; pointer-events: none; }
  @media (hover: none) { .glass-arrow { opacity: 1; transform: none; } }

  .slide-dots {
    position: absolute; inset-block-end: var(--space-3); inset-inline: 0; z-index: 2;
    display: flex; justify-content: center; gap: .35rem; pointer-events: none;
  }
  .slide-dots i {
    inline-size: .4rem; block-size: .4rem; border-radius: 99px;
    background: oklch(.3 .04 15 / .28);
    transition: inline-size var(--dur) var(--ease-out), background var(--dur) var(--ease-out);
  }
  .slide-dots i[data-active] { inline-size: 1.1rem; background: var(--berry); }

  /* Small frames (the phone's category thumbnails): smaller arrows, no dots. */
  @container (max-width: 170px) {
    .glass-arrow { inline-size: 2rem; block-size: 2rem; margin-block-start: -1rem; }
    .glass-prev { inset-inline-start: .3rem; }
    .glass-next { inset-inline-end: .3rem; }
    .slide-dots { display: none; }
  }

  /* Category card is an article with a full-card link, so arrows can sit on top. */
  .cat-card-link { color: inherit; text-decoration: none; }
  .cat-card-link::after { content: ""; position: absolute; inset: 0; z-index: 1; }

  /* Admin photo tiles: their buttons only appear on hover, which touch
     screens do not have. */
  @media (hover: none) { .img-tile-bar { opacity: 1; } }

  /* ------------------------------------------------------ gallery band --- */
  .gallery-band { padding-block: clamp(3rem, 6vw, var(--space-10)); }
  /* Straight after a plain section (the menu) the section's own padding is
     gap enough. */
  .section:not(.section-cream, .section-ink) + .gallery-band { padding-block-start: 0; }
  .gallery-frame { position: relative; margin-block-start: var(--space-6); }
  .gallery-track {
    --row: clamp(15rem, 30vw, 26rem);
    --cap: 70vw;
    --edge: max(1.25rem, env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px), calc((100% - var(--shell)) / 2));
    display: flex; align-items: center; gap: var(--space-4);
    overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    padding-inline: var(--edge); scroll-padding-inline: var(--edge);
    padding-block: var(--space-2);
    scrollbar-width: none;
  }
  .gallery-track::-webkit-scrollbar { display: none; }
  .gallery-track:focus-visible { outline-offset: -4px; }
  /* Every tile takes its photo's own shape (--ar = width / height), so a 4:5
     shot is a 4:5 tile and a banner shot a wide one — nothing is cropped. */
  .gal-tile {
    flex: none; margin: 0; scroll-snap-align: start;
    inline-size: min(var(--cap), calc(var(--row) * var(--ar)));
    aspect-ratio: var(--ar);
    border-radius: var(--radius-lg); overflow: hidden;
    background: var(--n-100); box-shadow: var(--shadow);
  }
  .gal-tile img { inline-size: 100%; block-size: 100%; object-fit: cover; }
  .gallery-frame .glass-arrow { opacity: 1; transform: none; }
  .gallery-frame .glass-prev { inset-inline-start: var(--space-4); }
  .gallery-frame .glass-next { inset-inline-end: var(--space-4); }
  @media (max-width: 47.99rem) {
    .gallery-track { --row: 68vw; --cap: 86vw; gap: var(--space-3); }
  }

  /* ------------------------------------------------------ admin gallery --- */
  .gal-admin { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: flex-start; }
  .gal-admin-tile { margin: 0; inline-size: min(100%, calc(11rem * var(--ar))); display: grid; gap: var(--space-2); }
  .gal-admin-tile img {
    inline-size: 100%; aspect-ratio: var(--ar); object-fit: cover;
    border-radius: var(--radius-sm); border: 1px solid var(--border);
  }
  .gal-admin-tile figcaption { display: flex; flex-wrap: wrap; gap: var(--space-2); }
}

/* ======================================== GALLERY CENTRING, ABOUT PHOTOS ==== */
@layer components {
  /* Every photo fits: drop the looping copies and centre the real row with
     auto margins on its first and last photo. */
  .gallery-frame[data-static] .gal-tile[data-clone] { display: none; }
  .gallery-frame[data-static] .gal-tile[data-first] { margin-inline-start: auto; }
  .gallery-frame[data-static] .gal-tile[data-last] { margin-inline-end: auto; }
  .gallery-frame[data-static] .glass-arrow { display: none; }
  /* Everything fits: drop the wide side padding so the auto margins centre
     the row on the page. */
  .gallery-frame[data-static] .gallery-track { padding-inline: 1.25rem; }
  /* Swipes and arrows settle each photo in the centre of the page. */
  .gal-tile { scroll-snap-align: center; }
  .gallery-track { position: relative; } /* tiles measure their position from the track */

  /* About page photos: shown whole in their 4:5 frame, like every other photo. */
  .about-frame img { object-fit: contain; }

  /* ------------------------------------------------------------ reviews --- */
  /* A page of review cards at a time — three on a computer, two on a tablet,
     one on a phone (wireReviews sets --per). The pages share one grid cell,
     so the band is as tall as the tallest page and never jumps while they
     cross-fade. A short last page sits centred. */
  .reviews { display: grid; gap: var(--space-6); justify-items: center; }
  .reviews-stage { display: grid; inline-size: 100%; }
  .review-page {
    grid-area: 1 / 1; display: flex; justify-content: center; gap: var(--space-5);
    opacity: 0; visibility: hidden;
    transition: opacity 900ms var(--ease-in-out), visibility 0s linear 900ms;
  }
  .review-page[data-active] { opacity: 1; visibility: visible; transition-delay: 0s; }
  .review {
    flex: 0 1 calc((100% - (var(--per, 1) - 1) * var(--space-5)) / var(--per, 1));
    min-inline-size: 0; margin: 0;
    display: flex; flex-direction: column; gap: var(--space-4);
    padding: clamp(1.25rem, 2.5vw, 1.75rem);
    background: var(--surface-raised); border: 1px solid var(--border);
    border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
  }
  .review-top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
  .stars { display: inline-flex; gap: .15rem; color: var(--berry); }
  .review blockquote {
    flex: 1;
    font-family: var(--font-display); font-size: var(--text-lg); font-weight: 400; font-style: italic;
    line-height: 1.45; text-wrap: pretty;
  }
  .review figcaption {
    display: grid; gap: .2rem; font-size: var(--text-sm);
    padding-block-start: var(--space-3); border-block-start: 1px solid var(--border);
  }
  .review figcaption strong { font-weight: 600; }
  .review figcaption span { color: var(--text-muted); font-size: var(--text-xs); letter-spacing: .08em; text-transform: uppercase; }
  .reviews-controls { display: flex; align-items: center; gap: var(--space-4); }
  /* The shared glass arrows float over photos; here they sit in a row. */
  .reviews-controls .glass-arrow { position: relative; inset: auto; margin: 0; opacity: 1; transform: none; }
  .reviews-controls .glass-arrow:active { transform: scale(.88); }
  .reviews-controls .slide-dots { position: static; }
  @media (prefers-reduced-motion: reduce) { .review-page { transition: none; } }
  /* The owner's preview before any real review exists. */
  .sample-tag {
    font-size: var(--text-2xs); font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
    color: var(--berry); background: var(--berry-soft);
    border-radius: var(--radius-full); padding: .25rem .7rem;
  }

  /* ---------------------------------------------- first load / refresh --- */
  /* Until the menu has loaded, main is empty, so the footer would sit right
     under the header and flash on every refresh. Hold it, the logo strip and
     the back-to-top arrow back until the first page is in, and keep the space
     with a quietly pulsing mark. */
  body:not([data-ready]) :is(.logo-marquee, .site-footer, .to-top) { display: none; }
  .boot-loader { min-block-size: calc(100svh - var(--header-h)); display: grid; place-items: center; }
  .boot-loader .brand-mark {
    inline-size: 3.5rem; block-size: 3.5rem;
    animation: boot-pulse 1.4s var(--ease-in-out) infinite alternate;
  }
  @keyframes boot-pulse { from { opacity: .25; transform: scale(.94); } to { opacity: .6; transform: none; } }
  @media (prefers-reduced-motion: reduce) { .boot-loader .brand-mark { animation: none; opacity: .45; } }

  /* ------------------------------------------ bars under a hidden header --- */
  .filters { transition: inset-block-start var(--dur-slow) var(--ease-out); }
  body:has(.site-header[data-hidden]) .filters { inset-block-start: 0; }
  body:has(.site-header[data-hidden]) .admin-nav { inset-block-start: 1rem; }

  /* ------------------------------------------------ logo strip over footer --- */
  /* Fills the gap between the last section and the footer. Two identical
     runs slide left by one run's width, so the loop has no seam. */
  .logo-marquee {
    overflow: hidden; padding-block: clamp(1.5rem, 3.5vw, 2.5rem);
    -webkit-mask: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
    mask: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  }
  main:not(:has(> .cta-band:last-child)) + .logo-marquee { margin-block-start: var(--space-10); }
  .mq-track { display: flex; inline-size: max-content; animation: mq 70s linear infinite; }
  .logo-marquee:hover .mq-track { animation-play-state: paused; }
  .mq-run { display: flex; align-items: center; gap: clamp(2rem, 4vw, 3.5rem); padding-inline-end: clamp(2rem, 4vw, 3.5rem); }
  .mq-item {
    display: inline-flex; align-items: center; gap: .7rem; white-space: nowrap;
    font-family: var(--font-display); font-size: clamp(1.2rem, 1rem + 1.1vw, 1.9rem); color: var(--n-800);
  }
  .mq-item .brand-mark { inline-size: 1.5em; block-size: 1.5em; color: var(--berry); }
  .mq-brand { font-weight: 600; color: var(--berry); }
  @keyframes mq { to { transform: translateX(-50%); } }
  @media (prefers-reduced-motion: reduce) { .mq-track { animation: none; } }

  /* ---------------------------------------------------------- back to top --- */
  .to-top {
    position: fixed; z-index: 54;
    inset-inline-end: max(1rem, env(safe-area-inset-right));
    inset-block-end: max(1rem, env(safe-area-inset-bottom));
    inline-size: 3rem; block-size: 3rem; display: grid; place-items: center;
    border-radius: var(--radius-full); color: var(--n-900);
    background: linear-gradient(180deg, oklch(1 0 0 / .75), oklch(1 0 0 / .4));
    border: 1px solid oklch(1 0 0 / .7);
    box-shadow: inset 0 1px 0 oklch(1 0 0 / .85), 0 8px 24px oklch(.3 .04 15 / .22);
    backdrop-filter: blur(14px) saturate(1.6); -webkit-backdrop-filter: blur(14px) saturate(1.6);
    opacity: 0; transform: translateY(12px) scale(.9); pointer-events: none;
    transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out), inset-block-end var(--dur) var(--ease-out);
  }
  .to-top[data-show] { opacity: 1; transform: none; pointer-events: auto; }
  .to-top[data-show]:active { transform: scale(.9); }
  /* On a phone, sit above the order bar when it is showing. */
  @media (max-width: 47.99rem) {
    body:has(.order-bar[data-show]) .to-top { inset-block-end: calc(5rem + env(safe-area-inset-bottom)); }
  }

  /* -------------------------------------------------------- cake builder --- */
  .tb { display: grid; gap: var(--space-5); }
  /* Segmented control: tier count, and real/faux per tier. */
  .seg {
    display: flex; flex-wrap: wrap; gap: .25rem; padding: .25rem;
    inline-size: fit-content; max-inline-size: 100%;
    background: var(--n-100); border-radius: var(--radius-full);
  }
  .seg button {
    min-block-size: 2.5rem; min-inline-size: 2.75rem; padding-inline: var(--space-4);
    border-radius: var(--radius-full); font-size: var(--text-sm); font-weight: 500; color: var(--text-muted);
    transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
  }
  .seg button:hover:not(:disabled) { color: var(--text); }
  .seg button[aria-checked="true"] { background: var(--surface-raised); color: var(--text); box-shadow: var(--shadow-sm); }
  .seg button:disabled { opacity: .4; cursor: not-allowed; }
  .seg-count button { font-weight: 600; font-variant-numeric: tabular-nums; }

  /* The little drawing of the cake, top tier first. */
  .tb-visual {
    display: grid; justify-items: center; gap: var(--space-3);
    padding: var(--space-4); border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--n-50);
  }
  .tb-stack { inline-size: min(100%, 12rem); display: grid; justify-items: center; }
  .tb-layer { display: block; block-size: 1.35rem; border-radius: 4px 4px 2px 2px; transition: inline-size var(--dur) var(--ease-out); }
  :is(.tb-layer, .tb-legend i)[data-kind="real"] { background: var(--gold); box-shadow: inset 0 3px 0 var(--berry); }
  :is(.tb-layer, .tb-legend i)[data-kind="faux"] {
    background: repeating-linear-gradient(135deg, var(--n-100) 0 5px, var(--n-300) 5px 7px);
    box-shadow: inset 0 0 0 1px var(--border-strong);
  }
  .tb-plate { display: block; inline-size: 100%; block-size: 4px; margin-block-start: 2px; border-radius: 2px; background: var(--n-300); }
  .tb-legend { display: flex; gap: var(--space-4); font-size: var(--text-xs); color: var(--text-muted); }
  .tb-legend span { display: inline-flex; align-items: center; gap: .35rem; }
  .tb-legend i { display: inline-block; inline-size: .85rem; block-size: .85rem; border-radius: 2px; }

  .tb-tiers { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
  .tb-tier {
    display: grid; gap: var(--space-3); padding: var(--space-4);
    border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-raised);
  }
  .tb-tier[data-kind="faux"] { background: color-mix(in oklch, var(--n-50) 70%, var(--surface-raised)); }
  .tb-tier-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); }
  .tb-tier-head strong { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 500; }
  .tb-tier-price { font-weight: 600; font-variant-numeric: tabular-nums; }
  .tb-fields { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr)); }
  .tb-faux-note { align-self: center; }

  /* Admin: the builder's size table and the wholesale tier rows. */
  .opt-choice-row.tb-admin-row { grid-template-columns: minmax(6rem, 1fr) 5.5rem 5.5rem minmax(6rem, 1fr) auto; }
  .opt-choice-row.ws-tier-row { grid-template-columns: minmax(6rem, 1fr) 5rem 6rem 6rem auto; }
  :is(.tb-admin-head, .ws-tier-head) span { font-size: var(--text-xs); }
  @media (max-width: 40rem) {
    .opt-choice-row.tb-admin-row, .opt-choice-row.ws-tier-row { grid-template-columns: 1fr 1fr; }
    .tb-admin-head, .ws-tier-head { display: none; }
  }

  /* ---------------------------------------------------------- quick add --- */
  /* On every product card, above the card's full-card link, so a tap opens
     the quick sheet rather than the product page. */
  .card-quick {
    position: relative; z-index: 2;
    display: inline-flex; align-items: center; justify-content: center; gap: .35rem;
    min-block-size: 2.5rem; padding-inline: var(--space-4);
    border-radius: var(--radius-full);
    background: var(--berry-soft); color: var(--berry);
    font-size: var(--text-xs); font-weight: 600; white-space: nowrap;
    transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  }
  .card-quick:hover { background: var(--berry); color: var(--n-0); }
  .card-quick:active { transform: scale(.95); }
  @media (hover: none) { .card-quick { min-block-size: var(--tap); } }
  @media (max-width: 47.99rem) { .card-quick { align-self: stretch; } }

  /* The quick sheet. Computer: a roomy card, the photo (whole, 4:5) beside
     the choices, which scroll inside it. Phone: a tall bottom sheet with a
     big photo above the choices, capped by the screen height so the choices
     and price bar still show on opening. */
  .qa-media { position: relative; aspect-ratio: 4 / 5; background: var(--surface-raised); overflow: hidden; }
  .qa-media img { inline-size: 100%; block-size: 100%; object-fit: contain; }
  .pv-quick .pv-panel { contain: none; min-block-size: 0; }
  .pv-quick .pv-title { font-size: var(--text-xl); }
  .qa-head { padding-inline-end: 2.75rem; }   /* clear of the close button */
  @media (min-width: 52rem) {
    .modal-quick { inline-size: min(100% - 2rem, 58rem); }
    .pv-quick { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); }
    .pv-quick > .qa-media { align-self: start; }
  }
  @media (max-width: 51.99rem) {
    .pv-quick > .qa-media {
      inline-size: min(100% - 2 * var(--space-5), 20rem, 38svh);
      margin: var(--space-7, 2.25rem) auto 0; border-radius: var(--radius);
    }
  }
  .qa-more { justify-self: start; font-size: var(--text-sm); min-block-size: var(--tap); display: inline-flex; align-items: center; }

  /* ----------------------------------------------- phones on their side --- */
  /* Short landscape screens: a slimmer logo (the header is 4rem here) and a
     shorter hero, so the first screen isn't all banner. */
  @media (orientation: landscape) and (max-height: 32rem) {
    .site-header .brand-mark { inline-size: 2.75rem; block-size: 2.75rem; }
    .site-header .brand-name { font-size: 1.6rem; }
    .site-header .brand-sub { font-size: .66rem; }
    .hero { padding-block: var(--space-6) var(--space-8); }
    .hero h1 { font-size: clamp(1.9rem, 4.4vw, 2.6rem); }
    .hero .lede { font-size: var(--text-base); }
    .hero-copy > * + * { margin-block-start: var(--space-4); }
  }
  /* Short screens, whichever layout: in the product sheet the choices come
     straight after the name, before the description and specs. */
  @media (max-height: 32rem) {
    .pv-scroll > .pv-head    { order: 1; }
    .pv-scroll > .pv-options { order: 2; }
    .pv-scroll > .pv-desc    { order: 3; }
    .pv-scroll > .pv-specs   { order: 4; }
    .pv-scroll > .panel      { order: 5; }
    .pv-scroll > .pv-note-field { order: 6; }
    .pv-scroll > .note       { order: 7; }
  }

  /* ---------------------------------------------------------- cake menu --- */
  /* Straight after a plain section, that section's own padding is gap enough. */
  .section:not(.section-cream, .section-ink) + .section.cake-menu { padding-block-start: 0; }
  /* The thin "Can't find your cake?" divider before the fully custom cakes. */
  .cake-divider {
    display: grid; justify-items: center; gap: var(--space-2); text-align: center;
    margin-block: clamp(2.5rem, 5vw, var(--space-10)) var(--space-6);
  }
  .cake-divider-title {
    display: flex; align-items: center; gap: var(--space-4); inline-size: 100%;
    font-family: var(--font-display); font-size: var(--text-xl); font-weight: 500;
  }
  .cake-divider-title::before, .cake-divider-title::after {
    content: ""; flex: 1; block-size: 1px; background: var(--border-strong);
  }
  .cake-divider-sub { font-size: var(--text-sm); color: var(--text-muted); max-inline-size: 46ch; }
  /* The custom cakes sit centred under the divider, each card the same width
     as a card in the full grid above (auto-fill of 16.5rem columns with a
     1.5rem gap: 2 columns from 34.5rem wide, 3 from 52.5rem, 4 from 70.5rem;
     phones use two columns, the smallest one). */
  .cake-custom { container-type: inline-size; }
  .product-grid-center {
    --cols: 1; --g: var(--space-5);
    display: flex; flex-wrap: wrap; justify-content: center; gap: var(--g);
  }
  .product-grid-center > * { flex: 0 0 calc((100% - (var(--cols) - 1) * var(--g)) / var(--cols)); min-inline-size: 0; }
  @container (min-width: 34.5rem) { .product-grid-center { --cols: 2; } }
  @container (min-width: 52.5rem) { .product-grid-center { --cols: 3; } }
  @container (min-width: 70.5rem) { .product-grid-center { --cols: 4; } }
  @media (max-width: 47.99rem) { .product-grid-center { --cols: 2; --g: var(--space-3); } }
  @media (max-width: 22.5rem)  { .product-grid-center { --cols: 1; } }
  /* The Cakes story now follows the dessert-table planner (both plain). */
  .table-plan + .section:not(.section-cream, .section-ink) { padding-block-start: 0; }

  /* --------------------------------------------------- dessert-table plan --- */
  .planner {
    display: grid; gap: var(--space-4);
    padding: var(--space-5); border-radius: var(--radius-lg);
    background: var(--gold-soft); border: 1px solid var(--gold-line);
    animation: plan-in var(--dur-slow) var(--ease-out);
    scroll-margin-block-start: var(--space-4);
  }
  @keyframes plan-in { from { opacity: 0; transform: translateY(8px); } }
  .planner-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-3); flex-wrap: wrap; }
  .planner-title { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 500; margin-block-start: var(--space-1); }
  .planner-head .btn-x { min-block-size: var(--tap); }
  .plan-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
  .plan-row {
    display: grid; gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius);
  }
  .plan-row-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); }
  .plan-cat { font-size: var(--text-xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); }
  .plan-price { font-weight: 600; font-variant-numeric: tabular-nums; }
  .plan-fields { display: grid; gap: var(--space-2); grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); }
  .plan-fields > .plan-product { grid-column: 1 / -1; }
  .plan-remove { justify-self: start; min-block-size: var(--tap); }
  .plan-empty { font-size: var(--text-sm); color: var(--text-muted); }
  .planner-total {
    display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3);
    padding-block-start: var(--space-3); border-block-start: 1px solid var(--gold-line);
  }
  .planner-total strong { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 600; }
  @media (prefers-reduced-motion: reduce) { .planner { animation: none; } }

  /* Product cards on the dark Centrepieces band keep their own dark text. */
  .section-ink .card { color: var(--text); }
  .centrepiece-items { margin-block-start: clamp(2.5rem, 5vw, var(--space-10)); }
  .centrepiece-items-head {
    display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap;
    gap: var(--space-2) var(--space-4); margin-block-end: var(--space-5);
  }
  .centrepiece-items-head h3 { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 500; color: var(--n-50); }

  /* The dessert-table planner on the home page. */
  .tp-card {
    max-inline-size: 52rem; margin-inline: auto;
    display: grid; gap: var(--space-5);
    padding: clamp(var(--space-5), 3vw, var(--space-8));
    background: var(--surface-raised); border: 1px solid var(--border);
    border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
  }
  /* The dessert table's photos across the top of the card, in a fixed 16:9
     frame, so nothing jumps as they load. A 16:9 photo fills it exactly;
     other shapes are trimmed to fit. Several flip with the glass arrows or a
     sideways swipe (pan-y leaves up-and-down to the page). */
  .tp-photo {
    position: relative; margin: 0; aspect-ratio: 16 / 9;
    border-radius: var(--radius); overflow: hidden;
    background: var(--n-100); touch-action: pan-y;
  }
  .tp-photo img, .tp-photo .slides .slide {
    position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: cover;
  }
  .tp-fields { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
  .tp-fields > .tp-wide, .tp-fields > .planner { grid-column: 1 / -1; }
  .tp-foot {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: var(--space-3) var(--space-5);
    padding-block-start: var(--space-4); border-block-start: 1px solid var(--border);
  }
  @media (max-width: 47.99rem) { .tp-foot .btn { inline-size: 100%; } }

  /* ------------------------------------------------- keyboard and forms --- */
  /* When a box in a sheet or drawer gets focus and scrolls into view, leave
     room for the pinned price bar or buttons, so the keyboard doesn't hide
     the box being typed in behind them. */
  :is(.pv, .drawer) :is(.input, .textarea, .select) { scroll-margin-block: 5rem 8rem; }
  /* iPhone draws date boxes its own way (centred, shorter, ignoring the
     width); make them sit like every other box. iOS only. */
  @supports (-webkit-touch-callout: none) {
    input.input[type="date"] { -webkit-appearance: none; appearance: none; display: flex; align-items: center; min-inline-size: 0; }
    input.input[type="date"]::-webkit-date-and-time-value { text-align: start; margin: 0; }
  }

  /* ------------------------------------------------------- social links --- */
  .social { display: flex; align-items: center; gap: var(--space-2); }
  .social[hidden] { display: none !important; }
  .social a {
    display: grid; place-items: center; flex: none;
    inline-size: 2.75rem; block-size: 2.75rem; border-radius: var(--radius-full);
    color: inherit; text-decoration: none;
    transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  }
  .social a:active { transform: scale(.92); }
  .social svg { inline-size: 1.3rem; block-size: 1.3rem; }
  .social-label { font-size: var(--text-xs); font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); margin-inline-end: var(--space-2); }

  /* Footer's bottom line: peach rings on the ink. */
  .footer-base .social a { color: var(--gold); box-shadow: inset 0 0 0 1px oklch(1 0 0 / .16); }
  .footer-base .social a:hover { background: oklch(1 0 0 / .08); color: var(--n-0); }

  /* Top strip: small icons at its right end on a computer (the phone menu has them). */
  .announce { position: relative; }
  .social-announce { position: absolute; inset-block: 0; inset-inline-end: max(var(--space-4), env(safe-area-inset-right, 0px)); gap: 0; }
  .social-announce a { inline-size: 2rem; block-size: 100%; border-radius: 0; color: var(--n-200); }
  .social-announce a:hover { color: var(--gold); }
  .social-announce svg { inline-size: 1rem; block-size: 1rem; }
  @media (max-width: 63.99rem) { .social-announce { display: none; } }

  /* Phone menu: a "Follow us" row under Wholesale, big enough to tap. */
  .nav .social-nav { display: none; }
  @media (max-width: 63.99rem) {
    .nav .social-nav {
      display: flex; gap: var(--space-3);
      margin-block-start: var(--space-3); padding-block-start: var(--space-4);
      border-block-start: 1px solid var(--border);
    }
    .nav .social-nav a {
      display: grid; inline-size: 3rem; block-size: 3rem; min-block-size: 0; padding: 0;
      background: var(--berry-soft); color: var(--berry);
    }
    .nav .social-nav a::after { display: none; }
    .nav .social-nav a:active { background: var(--berry-line); }
  }
}
