/* ==========================================================================
   Bean Ri — the only stylesheet.

   Organised by @layer, never by media query and never by file. Ordering by
   layer rather than by source order means a section rule can no longer beat
   a state rule (focus, :disabled, reduced-motion) by accident — which is the
   exact class of bug the old style.css / mobile-tweaks.css split produced.

   Media queries live inside the rule that owns the property, so a section's
   whole responsive story reads in one place.

     1  reset
     2  tokens        palette, role tokens per surface, type scale, spacing
     3  base          document, typography defaults
     4  layout        .shell, .grid, surfaces, .band, .section-head
     5  components    buttons, links, rules, tiles
     6  sections      header, hero, statement, pieces, girls, commission,
                      fittings, origin, team, enquiry, footer
     7  states        hover, focus-visible, active
     8  utilities     .only-wide / .only-narrow

   The mockup is drawn at 390, 834 and 1440. Sizes and spacing run on a
   fluid scale between them; the layout switches at two points:
     < 834     phone, one column
     834+      tablet, 6-column grid
     1080+     desktop, 12-column grid (84 / 28 / 62 at 1440)
   There is no 1440 breakpoint — the clamps top out there arithmetically.
   ========================================================================== */

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

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

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

  body, h1, h2, h3, p, figure, blockquote, ul, ol, dl, dd { margin: 0; }

  ul[class], ol[class] { list-style: none; padding: 0; }

  img, picture, svg, video { display: block; max-width: 100%; }

  img { height: auto; }

  input, button, textarea, select { font: inherit; color: inherit; }

  button { background: none; border: 0; padding: 0; cursor: pointer; }

}

/* ========================================================================== */
@layer tokens {
  :root {
    color-scheme: light only;

    /* ---- Palette -------------------------------------------------------
       The nine colours of the mockup, and nothing else. Components never
       reach for these directly: they use the role tokens below.            */
    --paper:        #F4F0EA;
    --paper-light:  #FDFBF7;
    --ink:          #181512;
    --muted:        #6E6861;   /* on paper 4.85:1, on paper-light 5.32:1 */
    --line:         #BDB4AA;
    --line-ink:     #3A3733;
    --stone-40:     #C9C2BB;   /* on ink 10.32:1 */
    --stone-60:     #A9A098;   /* on ink  7.07:1 */
    --alert:        #E08472;

    --error: var(--alert);

    /* ---- Type -----------------------------------------------------------
       Display steps interpolate 390 -> 1440. UI steps never move: a 13px
       label is 13px everywhere, or it stops being the same thing.
       --t-input is a hard floor — iOS Safari zooms any input under 16px.   */
    --font-display: "Cormorant Garamond", Georgia, "Times New Roman", serif;
    --font-ui:      "Schibsted Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;

    --t-numeral:  clamp(72px, 51.20px + 5.333vw, 128px);
    --t-display:  clamp(40px, 24.40px + 4.000vw,  82px);
    --t-h2:       clamp(30px, 19.60px + 2.667vw,  58px);
    --t-h3:       clamp(22px, 15.31px + 1.714vw,  40px);
    --t-quote:    clamp(22px, 19.77px + 0.571vw,  28px);
    --t-wordmark: clamp(22px, 19.03px + 0.762vw,  30px);
    --t-lead:     clamp(15px, 13.89px + 0.286vw,  18px);
    --t-facts:    clamp(16px, 15.26px + 0.190vw,  18px);

    --t-input:  16px;
    --t-body:    15px;
    --t-caption: 14px;
    --t-action:  13px;
    --t-label:   12px;

    /* Set by measurement, not by eye. Rendering the face and scanning pixels
       column by column: at 1.08 the clear band between two 64px lines is 4px
       and the worst ink-to-ink gap 5px — which reads as touching, because the
       ink itself spans 1.01em (0.73 above the baseline, 0.28 below). 1.22
       gives a 13px band. Tighter display leading is a real convention, but
       not with a face whose descenders run this deep. */
    --lh-display: 1.22;
    --lh-body:    1.65;
    --ls-caps:    0.1em;

    /* ---- Space ---------------------------------------------------------- */
    /* The page runs under the phone's bars (viewport-fit=cover), so the
       side gutters never shrink past the notch in landscape. */
    --gutter:  max(clamp(20px, 4.40px + 4vw, 62px), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
    /* The header sits nearer the edge than the content, as on main. */
    --gutter-header: max(clamp(16px, 4.86px + 2.857vw, 46px), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
    --content: 1316px;
    --pad-y:   clamp(72px, 57.14px + 3.810vw, 112px);
    --header-h: clamp(64px, 57.31px + 1.714vw, 82px);
    /* What the browser's own top bar covers: the status bar in Safari,
       the address bar in Telegram's browser. The header's glass fills it
       and the logo sits under it; 0 on a desktop. --bar-h is the whole
       band the header takes from the top of the window. */
    --safe-top: env(safe-area-inset-top, 0px);
    --bar-h:    calc(var(--header-h) + var(--safe-top));

    /* 26 / 37 / 56 are not on one line, so two ramps meet at 834. */
    --gap-row:   clamp(26px, max(16.34px + 2.477vw, 10.85px + 3.135vw), 56px);
    /* 12 on the phone, 28 from the tablet up: the ramp tops out at 834. */
    --gap-grid:  clamp(12px, 3.604vw - 2.05px, 28px);
  }

  /* ---- Surfaces ---------------------------------------------------------
     A section declares its tone with data-surface; everything inside reads
     the role tokens and never needs a per-section colour override. paper
     and paper-light differ only in the ground. */
  :root,
  [data-surface="paper"],
  [data-surface="paper-light"] {
    --bg:          var(--paper);
    --text:        var(--ink);
    --text-muted:  var(--muted);
    --text-subtle: var(--muted);
    --divider:     var(--line);
    --control:     var(--muted);
  }
  [data-surface="paper-light"] { --bg: var(--paper-light); }
  [data-surface="ink"] {
    --bg:          var(--ink);
    --text:        var(--paper-light);
    --text-muted:  var(--stone-40);
    --text-subtle: var(--stone-60);
    --divider:     var(--line-ink);
    --control:     var(--stone-60);
  }
}

/* ========================================================================== */
@layer base {
  /* Anchors land just under the sticky header, not behind it. */
  html { block-size: 100%; scroll-padding-block-start: var(--bar-h); }
  /* Menu links and "Start an enquiry" glide to their section rather than
     jump, so it reads as one page. */
  @media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
  }
  /* iPhone Safari takes the page's colour from html and body together
     and uses it for the fade under the status bar and the rubber band
     above the page. Every section paints its own ground, so the body
     stays clear and html alone sets it: ink while the header is over the
     dark hero, paper after. */
  html { background: var(--paper); }
  html:has(.site-header[data-pinned][data-surface="ink"]) { background: var(--ink); }
  /* The page stays put under an open piece card. */
  html:has(.piece-sheet[open]) { overflow: hidden; }

  body {
    min-block-size: 100%;
    margin: 0;
    color: var(--text);
    font-family: var(--font-ui);
    font-size: var(--t-body);
    line-height: var(--lh-body);
    font-synthesis-weight: none;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
  }
  /* iOS only (the one engine with touch-callout). On iOS 26 WebKit clips
     each pinned box to the window, unless it sits in a layer of its own
     other than the page's root; so the header's glass could not reach up
     under Telegram's bar. Giving the body its own layer lifts the clip.
     Opacity, because it does not make the body the frame for fixed
     children, as transform would. */
  @supports (-webkit-touch-callout: none) {
    body { will-change: opacity; }
  }

  h1, h2, .display {
    font-family: var(--font-display);
    font-weight: 500;
    line-height: var(--lh-display);
    text-wrap: pretty;
  }

  h2 { font-size: var(--t-h2); }

  /* Display: the first screen and "Tell us what you imagine". */
  h1, .display { font-size: var(--t-display); letter-spacing: -0.018em; }

  /* Метка: 13 / 600 caps — names in the team, and nothing else uses h3
     without overriding it. */
  h3 {
    font-size: var(--t-action);
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
  }

  p { text-wrap: pretty; }

  a { color: inherit; }

  ::selection { background: var(--text); color: var(--bg); }
}

/* ========================================================================== */
@layer layout {
  /* Above 1440 the content stays at 1316 and the margins grow. */
  .shell {
    inline-size: min(var(--content), 100% - 2 * var(--gutter));
    margin-inline: auto;
  }

  /* The page grid. One column on the phone, 6 on the tablet, 12 on the
     desktop; children span the full width unless a section says otherwise. */
  .grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    column-gap: var(--gap-grid);
  }
  .grid > * { grid-column: 1 / -1; }
  @media (min-width: 834px)  { .grid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
  @media (min-width: 1080px) { .grid { grid-template-columns: repeat(12, minmax(0, 1fr)); } }

  [data-surface] { background: var(--bg); color: var(--text); }

  .band { padding-block: var(--pad-y); }

  /* Section heading: title over intro, then title in columns 1–7 and the
     intro in 8–12 on the desktop. */
  /* --stack is the section's own vertical rhythm. On the desktop every
     section uses --gap-row; below 1080 the tablet and phone frames give
     some sections their own (set in the sections layer). */
  .band { --stack: var(--gap-row); }

  .section-head {
    display: grid;
    gap: 16px;
    margin-block-end: var(--stack);
  }
  /* The intro sits on the heading's bottom edge, not its top. */
  @media (min-width: 1080px) {
    .section-head {
      grid-template-columns: repeat(12, minmax(0, 1fr));
      column-gap: var(--gap-grid);
      align-items: end;
    }
    .section-head > h2 { grid-column: 1 / 8; }
    .section-head__intro { grid-column: 8 / -1; }
  }

  .section-head__intro {
    font-size: var(--t-lead);
    line-height: 1.6;
    color: var(--text-muted);
  }
}

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

  /* ---- Text bits ------------------------------------------------------- */
  /* Подпись: 14 / 500, in sentence case. Caps are kept for things you
     press or scan: buttons, links, the menu, names, the footer line. */
  .caption {
    font-size: var(--t-caption);
    font-weight: 500;
    line-height: 1.6;
    color: var(--text-subtle);
  }

  .rule {
    border: 0;
    block-size: 1px;
    margin: 0;
    background: var(--divider);
  }

  .wordmark {
    display: inline-flex;
    align-items: center;
    min-block-size: 44px;
    font-family: var(--font-display);
    font-size: var(--t-wordmark);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-decoration: none;
    white-space: nowrap;
  }
  /* The wordmark set in TT Ricordi Nobili, as a mask so it takes the
     surface's text colour (the header flips between ink and paper-light). */
  .wordmark__logo {
    display: block;
    inline-size: clamp(130px, 109.6px + 5.24vw, 185px);
    aspect-ratio: 3570 / 707;
    background: currentColor;
    mask: url("public/images/logo.a50303d1.svg") center / contain no-repeat;
  }

  /* ---- Buttons --------------------------------------------------------- */
  /* A button is its own surface (paper-light in the mockup), so it takes its
     colours from data-surface like a section does. Full width on the phone.
     The shadow lives on a pseudo so hover animates one opacity rather than
     interpolating box-shadow. */
  .btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 100%;
    min-block-size: 52px;
    padding-inline: 28px;
    background: var(--bg);
    color: var(--text);
    font-size: var(--t-action);
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    text-decoration: none;
    white-space: nowrap;
  }
  .btn::after {
    content: "";
    position: absolute;
    inset: 0;
    box-shadow: 0 10px 24px -16px rgb(16 14 12 / 0.55);
    opacity: 0;
  }
  @media (min-width: 834px) { .btn { inline-size: auto; } }

  /* ---- Arrow links ----------------------------------------------------
     Метка with an arrow. The underline is a background image so it can be
     drawn left to right; the padding makes a 44px target without moving
     the text.                                                             */
  .link-arrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding-block: 14px;
    margin-block: -14px;
    font-size: var(--t-action);
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    text-decoration: none;
    background-image: linear-gradient(currentColor, currentColor);
    background-size: 0% 1px;
    background-position: 0 calc(100% - 11px);
    background-repeat: no-repeat;
  }
  .arrow { display: inline-block; font-size: 1.1em; line-height: 1; }

  .skip-link {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    z-index: 100;
    padding: 12px 18px;
    background: var(--ink);
    color: var(--paper-light);
    font-size: var(--t-label);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    transform: translateY(-120%);
  }
  .skip-link:focus { transform: none; }

  .burger {
    display: grid;
    gap: 6px;
    inline-size: 44px;
    block-size: 44px;
    margin-inline-end: -10px;
    place-content: center;
  }
  .burger span {
    display: block;
    inline-size: 24px;
    block-size: 1px;
    background: currentColor;
  }
  @media (min-width: 1080px) { .burger { display: none; } }

  .to-top {
    position: fixed;
    inset-block-end: calc(20px + env(safe-area-inset-bottom, 0px));
    inset-inline-end: max(20px, env(safe-area-inset-right, 0px));
    z-index: 40;
    inline-size: 44px;
    block-size: 44px;
    display: grid;
    place-content: center;
    background: var(--ink);
    color: var(--paper-light);
    border-radius: 999px;
  }
  .to-top[hidden] { display: none; }
}

/* ========================================================================== */
@layer sections {

  /* ---- Header ---------------------------------------------------------- */
  /* At the top of the page it has no ground of its own: ink tone, sitting
     on the hero. app.js pins it (data-pinned) and sets two things:
       data-glass      frosted glass appears under it, from the middle of
                       the hero: the photo's top half stays clear;
       data-surface    ink while it is over the hero, paper-light after.
     So the text colour flips once, at the hero's bottom edge, and never
     again. The light glass is dense enough to carry ink text over the dark
     sections too (Girls, origin, enquiry: about 5:1 at 0.50), so it doesn't
     switch back and forth down the page; it is kept thin on purpose, and a rare moment
     where it blends into a photo is the accepted price. Without app.js it stays in place, as before: a
     sticky header in the hero's light tone would vanish on paper.
     The glass is a pseudo-element because a backdrop-filter on the header
     itself would become the containing block of the fixed mobile menu.

     The pinned box is a plain div, hidden, and everything in it is shown
     again (the glass, and the <header> inside with its own layer). It
     looks the same, but iPhone Safari, which looks for a pinned box at
     the top of the window to paint its colour as a solid band under the
     status bar, skips a hidden one. It keeps its soft fade instead, in the
     page's colour (see html in base). */
  .site-header {
    position: relative;
    z-index: 50;
    padding-block-start: var(--safe-top);
    background: none;
    visibility: hidden;
    transition: color .3s ease;
  }
  .site-header[data-pinned] { position: sticky; inset-block-start: 0; }
  /* The glass reaches 200px above the header, for Telegram's browser: its
     bar sits above the page's window and shows what the page draws above
     it. Anywhere else that part is above the window and never seen. */
  .site-header::before {
    content: "";
    position: absolute;
    inset: -200px 0 0;
    z-index: -1;
    visibility: visible;
    opacity: 0;
    background: rgb(24 21 18 / 0.30);
    -webkit-backdrop-filter: blur(28px) saturate(1.4);
    backdrop-filter: blur(28px) saturate(1.4);
    /* The glass fades in slowly and eases at both ends, so it settles in
       rather than switches on. The ink-to-light change at the hero's end
       keeps the shorter time, in step with the text colour. */
    transition:
      opacity .9s cubic-bezier(.45, 0, .25, 1),
      background-color .3s ease,
      box-shadow .3s ease;
  }
  .site-header[data-glass]::before { opacity: 1; }
  .site-header[data-surface="paper-light"]::before {
    background: rgb(253 251 247 / 0.50);
    box-shadow: 0 1px 0 rgb(189 180 170 / 0.55);
  }
  /* An open menu is a solid sheet; glass under its top bar looks torn. */
  .site-header:has(.site-nav.is-open)::before {
    opacity: 1;
    background: var(--bg);
    box-shadow: none;
  }
  @media (prefers-reduced-motion: reduce) {
    .site-header, .site-header::before { transition: none; }
  }
  /* Two 1px markers on the hero that app.js watches, each one
     header-height above a line that matters: the middle and the bottom
     edge. When a marker leaves the top of the window, that line has gone
     under the header. */
  .header-probe {
    position: absolute;
    inset-inline-start: 0;
    inline-size: 1px;
    block-size: 1px;
    pointer-events: none;
  }
  .header-probe--mid { inset-block-start: calc(50% - var(--bar-h)); }
  .header-probe--end { inset-block-end: var(--bar-h); }
  .site-header__inner {
    position: relative;
    visibility: visible;
    inline-size: calc(100% - 2 * var(--gutter-header));
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-grid);
    min-block-size: var(--header-h);
  }

  .site-nav { display: none; }
  .site-nav ul { display: flex; gap: 40px; list-style: none; padding: 0; }
  .site-nav a {
    display: inline-block;
    padding-block: 14px;
    margin-block: -14px;
    font-size: var(--t-action);
    font-weight: 500;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    text-decoration: none;
    background-image: linear-gradient(currentColor, currentColor);
    background-size: 0% 1px;
    background-position: 0 calc(100% - 12px);
    background-repeat: no-repeat;
  }

  /* The mobile menu. Toggled by app.js; below 1080 the nav is otherwise
     hidden, so without this the burger opens nothing. */
  .site-nav.is-open {
    display: block;
    position: fixed;
    inset: var(--bar-h) 0 0;
    z-index: 45;
    padding: 32px var(--gutter);
    background: var(--bg);
    color: var(--text);
  }
  .site-nav.is-open ul { flex-direction: column; gap: 22px; }
  .site-nav.is-open a { font-size: var(--t-body); }

  @media (min-width: 1080px) {
    .site-nav, .site-nav.is-open {
      display: block;
      position: static;
      padding: 0;
      background: none;
    }
    .site-nav.is-open ul { flex-direction: row; gap: 40px; }
    .site-nav.is-open a { font-size: var(--t-action); }
  }

  /* ---- Hero ------------------------------------------------------------ */
  /* 640 / 720 / 832 tall, as drawn. Past 1440 it keeps the desktop frame's
     proportion (832 / 1440) until it fills the window. */
  .hero {
    position: relative;
    isolation: isolate;
    display: grid;
    align-content: end;
    min-block-size: max(clamp(640px, 568.69px + 18.286vw, 832px), min(57.78vw, 100svh));
    margin-block-start: calc(-1 * var(--bar-h));
    padding-block: calc(var(--bar-h) + 40px) clamp(44px, 30.63px + 3.429vw, 80px);
    overflow: hidden;
  }
  .hero__media, .hero__media img {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    z-index: -2;
  }
  .hero__media img { object-fit: cover; }

  /* The mockup's scrim, per width: on the phone one vertical ramp that
     darkens under the copy; from the tablet a top band for the header, a
     horizontal ramp and a left band behind the headline. The tablet frame
     draws no left band, but without it the facts line sits on the bright
     plinths at about 3:1 — measured, not guessed. */
  .hero::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(180deg, rgb(16 14 12 / 0.55) 0%, rgb(16 14 12 / 0.20) 30%, rgb(16 14 12 / 0.90) 100%);
  }
  @media (min-width: 834px) {
    .hero::before {
      background:
        linear-gradient(180deg, rgb(16 14 12 / 0.60) 0%, rgb(16 14 12 / 0) 26%),
        linear-gradient(270deg, rgb(16 14 12 / 0.45) 0%, rgb(16 14 12 / 0.12) 38%, rgb(16 14 12 / 0.70) 100%),
        linear-gradient(90deg, rgb(16 14 12 / 0.70) 0%, rgb(16 14 12 / 0) 60%);
    }
  }

  /* Text blocks stretch to the column rather than shrink to their text:
     WebKit sizes a shrink-wrapped block narrower than its own text-wrap:
     pretty needs, and "Any complexity" broke onto a third line on iOS. */
  .hero__copy { display: grid; gap: 14px; }
  .hero h1 .line { display: block; }
  .hero__rule { display: none; inline-size: 120px; }
  .hero__facts {
    font-size: var(--t-facts);
    font-weight: 500;
    line-height: 1.5;
    color: var(--text-muted);
  }
  .hero__actions { justify-self: stretch; display: flex; }

  @media (min-width: 834px)  { .hero__copy { gap: 16px; } }
  @media (min-width: 1080px) {
    .hero__copy { gap: 40px; }
    .hero__rule { display: block; }
  }

  /* ---- Statement ------------------------------------------------------- */
  /* Text 1–6, a vertical rule centred in 7–9, the numeral 10–12. On the
     tablet 1–4 and 5–6; on the phone one stack with a horizontal rule. */
  .statement__grid { row-gap: 28px; }
  .statement__claim p { max-inline-size: 560px; margin-block-start: 28px; color: var(--text-muted); }
  .statement__lead { display: grid; gap: 28px; align-content: start; }
  /* Room for the descender inside the box, cancelled outside it, so the
     line box is the drawn 0.9 and the label keeps its distance. */
  .numeral {
    padding-block: 0.18em;
    margin-block: -0.18em;
    font-family: var(--font-display);
    font-size: var(--t-numeral);
    font-weight: 500;
    line-height: 0.9;
    letter-spacing: -0.023em;
  }
  .statement__label { color: var(--text); }
  .statement__note { color: var(--text-muted); }

  @media (min-width: 834px) {
    .statement__claim p { margin-block-start: 26px; }
    .statement__lead { gap: 20px; }
    .statement__claim { grid-area: 1 / 1 / 2 / 5; }
    .statement__rule  { grid-area: 1 / 4 / 2 / 6; justify-self: center; inline-size: 1px; block-size: auto; min-block-size: 300px; }
    .statement__lead  { grid-area: 1 / 5 / 2 / -1; }
  }
  @media (min-width: 1080px) {
    .statement__claim { grid-area: 1 / 1 / 2 / 7; }
    /* The mockup's heading box is 660, 16 wider than the six columns, which
       is what keeps "a feeling," on the first line. */
    .statement__claim h2 { margin-inline-end: -16px; }
    .statement__claim p { margin-block-start: 30px; }
    .statement__lead { gap: 22px; }
    .statement__rule  { grid-area: 1 / 7 / 2 / 10; min-block-size: 360px; }
    .statement__lead  { grid-area: 1 / 10 / 2 / -1; }
  }

  /* ---- Selected pieces -------------------------------------------------- */
  /* 2 × 2 on the phone and tablet, four across on the desktop. The tile is a
     paper surface on the paper-light band. */
  @media (max-width: 1079.98px) { .pieces { --stack: 40px; } }
  .pieces__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: 1fr;   /* every tile as tall as the tallest, as drawn */
    gap: var(--gap-grid);
  }
  @media (min-width: 834px)  { .pieces__grid { row-gap: 40px; } }
  @media (min-width: 1080px) { .pieces__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); row-gap: var(--gap-grid); } }

  .piece__link {
    display: flex;
    flex-direction: column;
    block-size: 100%;
    padding: 16px 12px;
    background: var(--paper);
    text-decoration: none;
    color: inherit;
  }
  @media (min-width: 834px) { .piece__link { padding: 26px 22px; } }
  .piece__media img { inline-size: 100%; aspect-ratio: 1; object-fit: contain; }
  .piece__title {
    margin-block-start: 24px;
    font-size: var(--t-action);
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
  }
  .piece__materials { margin-block-start: 6px; font-size: var(--t-action); line-height: 1.5; color: var(--text-muted); }
  /* As a shop prints it: the price on its own line, in the text colour. */
  .piece__price { margin-block-start: 10px; font-size: var(--t-action); font-weight: 500; line-height: 1.5; }
  /* Ссылка малая: 12 / 500 caps. Pushed to the bottom so the four line up. */
  .piece__cta {
    align-self: start;
    margin-block-start: auto;
    padding-block-start: 16px;
    font-size: var(--t-label);
    font-weight: 500;
    line-height: 1.6;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    background-image: linear-gradient(currentColor, currentColor);
    background-size: 0% 1px;
    background-position: 0 100%;
    background-repeat: no-repeat;
  }
  .piece__cta .arrow { margin-inline-start: 4px; }

  /* ---- Bean Ri Girls ---------------------------------------------------- */
  /* A rail that bleeds off the right edge on the phone and tablet; four
     equal columns with staggered tops on the desktop. */
  .girls__rail {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline-start: var(--gutter);
    padding-inline: var(--gutter);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .girls__rail::-webkit-scrollbar { display: none; }
  .girls__rail > li { flex: 0 0 260px; scroll-snap-align: start; }
  .girls__rail img { inline-size: 100%; block-size: 340px; object-fit: cover; }
  /* Each photo opens full screen (app.js, PhotoSwipe); without it, the
     link opens the full-size file. */
  .girls__open { display: block; cursor: zoom-in; }
  .girls__open img { transition: opacity .3s ease; }
  @media (max-width: 833.98px) { .girls { --stack: 26px; } }
  @media (min-width: 834px) and (max-width: 1079.98px) { .girls { --stack: 30px; } }
  .girls__foot {
    display: flex;
    justify-content: flex-end;
    margin-block-start: var(--stack);
  }

  @media (min-width: 834px) {
    .girls__rail { gap: 14px; }
    .girls__rail > li { flex-basis: 318px; }
    .girls__rail img { block-size: 400px; }
  }

  @media (min-width: 1080px) {
    .girls__rail {
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: var(--gap-grid);
      overflow: visible;
      padding-inline: 0;
      inline-size: min(var(--content), 100% - 2 * var(--gutter));
      margin-inline: auto;
    }
    /* The staggered tops are the section's whole idea; the shared baseline is
       what stops it reading as accidental. Both are preserved here. */
    .girls__rail > li:nth-child(1) { padding-block-start: 20px; }
    .girls__rail > li:nth-child(2) { padding-block-start: 60px; }
    .girls__rail > li:nth-child(4) { padding-block-start: 40px; }
    .girls__rail img { block-size: auto; aspect-ratio: 308 / 470; }
    .girls__rail > li:nth-child(2) img { aspect-ratio: 308 / 430; }
    .girls__rail > li:nth-child(3) img { aspect-ratio: 308 / 490; }
    .girls__rail > li:nth-child(4) img { aspect-ratio: 308 / 450; }
  }

  /* ---- The commission --------------------------------------------------- */
  /* Rows with a thumbnail on the phone and tablet, three columns of four on
     the desktop, each with a rule above the number. */
  @media (max-width: 833.98px) { .commission { --stack: 34px; } }
  @media (min-width: 834px) and (max-width: 1079.98px) { .commission { --stack: 36px; } }
  .commission__steps { display: grid; gap: var(--stack); }
  .step {
    display: grid;
    grid-template-columns: 88px minmax(0, 1fr);
    column-gap: 12px;
    align-items: start;
  }
  /* 2 : 3 at every width: 88 x 132, 140 x 210, 420 x 630. */
  .step__photo { inline-size: 100%; aspect-ratio: 2 / 3; object-fit: cover; }
  .step__text { display: grid; gap: 8px; }
  .step__num {
    padding-block: 0.18em;
    margin-block: -0.18em;
    font-family: var(--font-display);
    font-size: var(--t-h3);
    font-weight: 500;
    line-height: 0.9;
    color: var(--text-muted);
  }
  .step__title {
    font-family: var(--font-display);
    font-size: var(--t-quote);
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: 0;
    text-transform: none;
  }
  .step__body { color: var(--text-muted); }
  /* The phone mockup ends the section on the last step. */
  .commission__action { display: none; justify-content: flex-end; margin-block-start: var(--stack); }

  @media (min-width: 834px) {
    .commission__action { display: flex; }
    .step { grid-template-columns: 140px minmax(0, 1fr); column-gap: 28px; }
  }
  @media (min-width: 1080px) {
    .commission__steps { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--gap-grid); }
    .step { grid-template-columns: minmax(0, 1fr); row-gap: 24px; }
    .step__text { gap: 24px; }
  }

  /* ---- Private fittings --------------------------------------------------- */
  /* Phone: the room first, then two details side by side, then the text.
     Tablet: three equal photographs in a row. Desktop: 3 + 3 + 6, the text
     under the wide photograph. */
  @media (max-width: 833.98px) { .fittings { --stack: 26px; } }
  @media (min-width: 834px) and (max-width: 1079.98px) { .fittings { --stack: 30px; } }
  .fittings__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 26px; }
  .fittings__grid img { inline-size: 100%; block-size: auto; object-fit: cover; }
  .fittings__lead { grid-area: 1 / 1 / 2 / -1; }
  .fittings__lead img { aspect-ratio: 350 / 420; }
  .fittings__a { grid-area: 2 / 1; aspect-ratio: 169 / 220; }
  .fittings__b { grid-area: 2 / 2; aspect-ratio: 169 / 220; }
  .fittings__text { grid-area: 3 / 1 / 4 / -1; display: grid; gap: 26px; }
  .fittings__quote { font-family: var(--font-display); font-size: var(--t-quote); line-height: 1.2; }
  .fittings__facts { display: grid; gap: 26px; color: var(--text-muted); }
  .fittings__action { display: flex; justify-content: flex-end; }

  @media (min-width: 834px) {
    .fittings__grid { grid-template-columns: repeat(6, minmax(0, 1fr)); row-gap: 30px; }
    .fittings__a    { grid-area: 1 / 1 / 2 / 3; }
    .fittings__b    { grid-area: 1 / 3 / 2 / 5; }
    .fittings__lead { grid-area: 1 / 5 / 2 / 7; }
    .fittings__a, .fittings__b, .fittings__lead img { aspect-ratio: 234 / 279; }
    .fittings__text { grid-area: 2 / 1 / 3 / -1; gap: 30px; }
    .fittings__facts {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 8px var(--gap-grid);
    }
  }
  @media (min-width: 1080px) {
    .fittings__grid { grid-template-columns: repeat(12, minmax(0, 1fr)); row-gap: 22px; align-items: start; }
    .fittings__a    { grid-area: 1 / 1 / 3 / 4; }
    .fittings__b    { grid-area: 1 / 4 / 3 / 7; }
    .fittings__a, .fittings__b { aspect-ratio: 308 / 495; }
    .fittings__lead { grid-area: 1 / 7 / 2 / -1; }
    .fittings__lead img { aspect-ratio: 644 / 413; }
    .fittings__text { grid-area: 2 / 7 / 3 / -1; gap: 22px; }
  }

  /* ---- Brand origin ------------------------------------------------------ */
  /* Photograph on top on the phone and tablet. On the desktop it bleeds off
     the left edge at 590 / 1440 of the width and keeps the drawn 590 x 650
     format at any width, so on a wide screen the section grows taller
     rather than the portrait being cropped. The text starts at column 7. */
  .origin__media { display: block; }
  .origin__photo { inline-size: 100%; aspect-ratio: 390 / 380; object-fit: cover; }
  .origin__grid { padding-block: var(--pad-y); }
  .origin__text { display: grid; gap: 22px; }
  .origin__cols { display: grid; gap: 22px; }
  .origin__cols p { color: var(--text-muted); }
  /* The name's meaning, set in the display face's italic in the heading
     and in the text alike. */
  .origin em { font-style: italic; font-weight: 400; }
  .origin__cols em {
    font-family: var(--font-display);
    font-size: 1.22em;
    line-height: 1;
    color: var(--text);
  }

  @media (min-width: 834px) {
    .origin__photo { aspect-ratio: 834 / 420; }
    .origin__text { gap: 24px; }
    .origin__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 38px; }
  }
  @media (min-width: 1080px) {
    .origin { display: grid; }
    .origin > * { grid-area: 1 / 1; }
    .origin__media {
      justify-self: start;
      align-self: stretch;
      inline-size: 40.97%;
      aspect-ratio: 590 / 650;
    }
    .origin__photo { block-size: 100%; aspect-ratio: auto; }
    .origin__grid { align-self: start; }
    .origin__text { grid-column: 7 / -1; gap: 44px; }
    .origin__cols { gap: var(--gap-grid); }
  }

  /* ---- Team ---------------------------------------------------------------- */
  /* Heading in 1–5, the two portraits in 7–9 and 10–12. */
  .team__grid { row-gap: 34px; }
  .team__people { display: grid; gap: 34px; }
  .team__people li { display: grid; gap: 14px; align-content: start; }
  .team__people img { inline-size: 220px; block-size: 220px; border-radius: 50%; object-fit: cover; }
  .team__people p { color: var(--text-muted); }

  @media (min-width: 834px) {
    .team__grid { row-gap: 40px; }
    .team__people { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap-grid); }
  }
  @media (min-width: 1080px) {
    .team__intro  { grid-area: 1 / 1 / 2 / 6; }
    .team__people { grid-area: 1 / 7 / 2 / -1; }
  }

  /* ---- Enquiry ------------------------------------------------------------- */
  /* Intro in 1–5, the form in 7–12. Fields are a label over an underline,
     two to a row from the tablet up. */
  .enquiry__grid { row-gap: 40px; }
  .enquiry__intro { display: grid; gap: 28px; align-content: start; }
  .enquiry__copy { color: var(--text-muted); }
  .enquiry__micro { font-size: var(--t-label); line-height: 1.6; color: var(--text-subtle); }

  /* Native controls (the date picker, the select's list) in their dark
     form, to match the ground. */
  .enquiry__form { display: grid; gap: 28px var(--gap-grid); align-content: start; color-scheme: dark; }
  .field { display: grid; gap: 6px; align-content: start; min-inline-size: 0; }
  .field__label {
    font-size: var(--t-label);
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-muted);
  }
  .field__opt {
    margin-inline-start: 6px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--text-subtle);
  }
  .field__input {
    display: block;
    inline-size: 100%;
    min-inline-size: 0;
    min-block-size: 46px;
    padding: 10px 0;
    background: transparent;
    border: 0;
    border-block-end: 1px solid var(--control);
    border-radius: 0;
    color: var(--text);
    font-size: var(--t-input);
    line-height: 1.5;
    appearance: none;
    transition: border-color .2s ease;
  }
  .field__input::placeholder { color: var(--text-subtle); opacity: 1; }
  .field__input--area { min-block-size: 112px; resize: vertical; }
  .field__input:-webkit-autofill {
    -webkit-text-fill-color: var(--text);
    box-shadow: 0 0 0 100px var(--bg) inset;
  }
  .field__select { position: relative; display: block; }
  .field__select .field__input { padding-inline-end: 28px; cursor: pointer; }
  .field__select::after {
    content: "";
    position: absolute;
    inset-inline-end: 4px;
    inset-block-start: calc(50% - 6px);
    inline-size: 8px;
    block-size: 8px;
    border: solid var(--text-muted);
    border-width: 0 1px 1px 0;
    transform: rotate(45deg);
    pointer-events: none;
  }
  .field__select option { background: var(--ink); color: var(--paper-light); }
  .field__input[aria-invalid="true"] { border-block-end-color: var(--error); }
  .field__error { font-size: var(--t-label); line-height: 1.5; color: var(--error); }

  /* The file input stays in the tab order, invisible; its label is the
     control you see. */
  .field--files { justify-items: start; gap: 12px; }
  .field__file {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    opacity: 0;
    overflow: hidden;
  }
  .field--files .link-arrow { cursor: pointer; }
  .field__files { font-size: var(--t-caption); line-height: 1.5; color: var(--text-muted); overflow-wrap: anywhere; }
  .field__files:empty { display: none; }

  .enquiry__send { display: grid; gap: 14px; margin-block-start: 6px; }
  .enquiry__status {
    padding: 14px 16px;
    border: 1px solid var(--control);
    font-size: var(--t-caption);
    line-height: 1.6;
  }

  @media (min-width: 834px) {
    .enquiry__intro { gap: 22px; }
    .enquiry__form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .field--wide, .enquiry__send { grid-column: 1 / -1; }
    .enquiry__send .btn { justify-self: start; }
  }
  @media (min-width: 1080px) {
    .enquiry__intro { grid-area: 1 / 1 / 2 / 6; gap: 28px; }
    .enquiry__form  { grid-area: 1 / 7 / 2 / -1; }
  }

  /* ---- Piece card ------------------------------------------------------------ */
  /* The <dialog> covers the window and scrolls; the panel inside is the
     card, so a click on the dialog itself is a click outside the card.
     Phone: a full-screen sheet, photograph on top, the request button
     pinned to the bottom. From the tablet up: a centred two-column card. */
  .piece-sheet {
    position: fixed;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    max-inline-size: none;
    max-block-size: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--ink);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .piece-sheet::backdrop { background: rgb(24 21 18 / 0.6); }
  .piece-sheet__panel {
    position: relative;
    display: grid;
    align-content: start;
    min-block-size: 100%;
    padding-block-start: env(safe-area-inset-top, 0px);
  }
  .piece-sheet__close {
    position: absolute;
    inset-block-start: calc(8px + env(safe-area-inset-top, 0px));
    inset-inline-end: max(8px, env(safe-area-inset-right, 0px));
    z-index: 2;
    display: grid;
    place-items: center;
    inline-size: 44px;
    block-size: 44px;
  }
  .piece-sheet__close span {
    grid-area: 1 / 1;
    inline-size: 22px;
    block-size: 1px;
    background: currentColor;
    transform: rotate(45deg);
  }
  .piece-sheet__close span + span { transform: rotate(-45deg); }

  .piece-sheet__media {
    position: relative;
    display: block;
    padding: 48px 32px 24px;
    background: var(--paper);
    cursor: zoom-in;
  }
  .piece-sheet__media img { inline-size: 100%; aspect-ratio: 1; object-fit: contain; }
  /* A small "+" in a ring: the photograph zooms. */
  .piece-sheet__zoom {
    position: absolute;
    inset-block-end: 14px;
    inset-inline-end: 14px;
    inline-size: 36px;
    block-size: 36px;
    border: 1px solid var(--line);
    border-radius: 50%;
    background:
      linear-gradient(currentColor, currentColor) center / 12px 1px no-repeat,
      linear-gradient(currentColor, currentColor) center / 1px 12px no-repeat;
  }

  .piece-sheet__info {
    display: grid;
    gap: 16px;
    align-content: start;
    padding: 28px var(--gutter) 0;
  }
  .piece-sheet__type {
    font-size: var(--t-label);
    font-weight: 600;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-muted);
  }
  .piece-sheet__title {
    margin-block-start: -6px;
    font-size: min(var(--t-h2), 44px);
  }
  .piece-sheet__price { font-size: var(--t-facts); font-weight: 500; }
  .piece-sheet__about { color: var(--text-muted); }
  .piece-sheet__specs { margin-block-start: 8px; border-block-start: 1px solid var(--divider); }
  .piece-sheet__specs div {
    display: grid;
    grid-template-columns: 124px minmax(0, 1fr);
    gap: 12px;
    padding-block: 12px;
    border-block-end: 1px solid var(--divider);
  }
  .piece-sheet__specs dt {
    font-size: var(--t-label);
    font-weight: 600;
    line-height: 1.9;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-muted);
  }
  .piece-sheet__note { font-size: var(--t-caption); line-height: 1.6; color: var(--text-muted); }
  .piece-sheet__cta {
    position: sticky;
    inset-block-end: 0;
    margin-inline: calc(-1 * var(--gutter));
    padding: 12px var(--gutter) calc(12px + env(safe-area-inset-bottom, 0px));
    background: var(--bg);
    box-shadow: 0 -1px 0 var(--divider);
  }
  .piece-sheet__cta .btn { inline-size: 100%; }

  @media (min-width: 834px) {
    .piece-sheet[open] { display: grid; place-items: center; padding: 40px; }
    .piece-sheet__panel {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      inline-size: min(1040px, 100%);
      min-block-size: 0;
      padding-block-start: 0;
      box-shadow: 0 30px 80px -40px rgb(16 14 12 / 0.6);
    }
    .piece-sheet__close { inset-block-start: 10px; inset-inline-end: 10px; }
    .piece-sheet__media { display: grid; place-items: center; padding: 40px; }
    .piece-sheet__info { padding: 48px 40px 40px; }
    .piece-sheet__cta {
      position: static;
      margin: 8px 0 0;
      padding: 0;
      background: none;
      box-shadow: none;
    }
  }

  @media (prefers-reduced-motion: no-preference) {
    .piece-sheet[open] .piece-sheet__panel { animation: sheet-in .45s cubic-bezier(.2, .7, .2, 1); }
    .piece-sheet[open]::backdrop { animation: sheet-fade .3s ease; }
  }
  @media (min-width: 1080px) {
    .piece-sheet__panel { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }
  }
  @keyframes sheet-in { from { opacity: 0; transform: translateY(18px); } }
  @keyframes sheet-fade { from { opacity: 0; } }

  /* ---- Footer -------------------------------------------------------------- */
  .site-footer { padding-block: 44px; }
  /* Keep the 44px target without letting it push the footer taller. */
  .site-footer .wordmark { margin-block: -9px; }
  .site-footer__inner { display: grid; gap: 16px; }
  .site-footer__inner .wordmark { justify-self: start; }
  .site-footer__meta { font-size: var(--t-label); line-height: 1.6; color: var(--text-subtle); }

  @media (min-width: 834px) {
    .site-footer { padding-block: 0; }
    .site-footer__inner {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--gap-grid);
      min-block-size: clamp(120px, 109px + 1.32vw, 128px);
    }
    .site-footer__meta { font-size: var(--t-action); font-weight: 500; letter-spacing: var(--ls-caps); text-transform: uppercase; }
  }
}

/* ========================================================================== */
@layer states {

  /* Hover is an enhancement for devices that have it. :active is not. */
  @media (hover: hover) and (pointer: fine) {
    .btn:hover { transform: translateY(-1px); }
    .btn:hover::after { opacity: 1; }
    .btn[data-surface="paper-light"]:hover { background: #FFFFFF; }

    .link-arrow:hover, .site-nav a:hover { background-size: 100% 1px; }
    .link-arrow:hover .arrow { transform: translateX(4px); }

    .piece__link:hover { background: #FFFFFF; }
    .piece__link:hover .piece__media img { transform: scale(1.035); }
    .piece__link:hover .piece__cta { background-size: 100% 1px; }
    .piece__link:hover .piece__cta .arrow { transform: translateX(4px); }
    .piece__link:hover .piece__materials { color: var(--text); }

    .to-top:hover { background: #241F1B; }

    .girls__open:hover img { opacity: .88; }
    .field__input:hover { border-block-end-color: var(--text-muted); }
    .field--files .link-arrow:hover { background-size: 100% 1px; }
  }

  .btn:active { transform: translateY(0) scale(.988); }
  .btn:active::after { opacity: 0; }
  .to-top:active { transform: scale(.97); }
  .link-arrow:active, .site-nav a:active { background-size: 100% 1px; }
  .piece__link:active .piece__media img { transform: scale(.985); }

  :focus-visible {
    outline: 1px solid currentColor;
    outline-offset: 4px;
  }
  /* A button is its own surface, so currentColor is its label colour — the
     ring has to take the colour of the section around it instead. */
  .btn:focus-visible { outline-offset: 3px; outline-color: var(--ink); }
  [data-surface="ink"] .btn:focus-visible { outline-color: var(--paper-light); }
  .piece__link:focus-visible { outline-color: var(--text); outline-offset: 6px; background: #FFFFFF; }
  .piece__link:focus-visible .piece__media img { transform: scale(1.035); }
  .piece__link:focus-visible .piece__cta { background-size: 100% 1px; }
  .link-arrow:focus-visible, .site-nav a:focus-visible { background-size: 100% 1px; }
  .girls__open:focus-visible { outline-offset: 3px; }
  /* A field shows focus with its own line, like the rest of the form. */
  .field__input:focus { outline: none; border-block-end-color: var(--text); }
  .field__input[aria-invalid="true"]:focus { border-block-end-color: var(--error); }
  .field__file:focus-visible + .link-arrow { outline: 1px solid currentColor; outline-offset: 4px; background-size: 100% 1px; }
  .piece-sheet__media:focus-visible { outline-offset: -6px; }
  /* The card takes focus when it opens, so a reader starts at its top. */
  .piece-sheet__panel:focus { outline: none; }
  .enquiry__status a { text-underline-offset: 3px; }

  [hidden] { display: none !important; }
}

/* ========================================================================== */
@layer utilities {
  /* Copy that differs between the phone and the wider frames, as drawn. */
  @media (max-width: 833.98px) { .only-wide { display: none; } }
  @media (min-width: 834px)    { .only-narrow { display: none; } }
}

/* ==========================================================================
   PhotoSwipe, on the site's light paper: the pieces are cut-outs, and
   on black they looked pasted on. Unlayered and doubled up, because its
   own stylesheet is unlayered too and loads later (app.js adds it).       */
.pswp.pswp {
  --pswp-bg: #FDFBF7;
  --pswp-placeholder-bg: #F4F0EA;
  --pswp-icon-color: #181512;
  --pswp-icon-color-secondary: #FDFBF7;
  --pswp-icon-stroke-color: #FDFBF7;
  --pswp-icon-stroke-width: 2px;
  --pswp-error-text-color: #6E6861;
  --pswp-preloader-color: rgb(24 21 18 / 0.15);
  --pswp-preloader-color-secondary: rgb(24 21 18 / 0.7);
}
.pswp.pswp .pswp__counter {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.1em;
  opacity: 1;
  color: #6E6861;
  text-shadow: none;
}
