/* Bareface product configurator. Measurements from the "Product Page Configurator"
   canvas (DW9, DW10, A10, DA2–DA5). Colours come from the site's Webflow palette variables
   (Chris, 2026-10-05), with the hex as a fallback. Type is the page's own Inter. */

/* Choose options and the panels live outside the mount (on body), so they carry the tokens too. */
.bfc, .bfc_choose, .bfc_panel {
  --bfc-ink: var(--_color---color-primary-black, #1B1B1B);
  --bfc-grey: var(--_color---color-gray-600, #5D5F69);
  --bfc-quiet: var(--_color---color-gray-500, #868994);
  --bfc-line: var(--_color---color-gray-200, #E1E2E5);
  --bfc-ground: var(--_color---color-gray-50, #F7F7F7);
  /* The disabled pair has no palette variable yet. */
  --bfc-off-bg: #F4F4F5;
  --bfc-off-ink: #9A9CA5;
}
.bfc {
  display: flex;
  flex-direction: column;
  gap: 32px;
  color: var(--bfc-ink);
  font-size: 12px;
  line-height: 18px;
}
/* Stood down (gift card, or a page that keeps its own form): display:flex above would otherwise beat [hidden]. */
.bfc[hidden] { display: none; }
.bfc.is-failed::before {
  content: "Something went wrong loading the options. Refresh the page, or email studio@barefaceportraits.com.";
  color: var(--bfc-grey);
}
/* Desktop, Timeline or Files open (canvas C5; Chris, 2026-10-07): only the name, the price and the choice show, 24px
   under the price. The perks and Portrait Details / Commission Process links come back on Back or a pick.
   The configurator sets html.bfc-viewing, on desktop only. */
html.bfc-viewing .product-header_product-details .margin-bottom:has(> .product_feature_outer_wrapper),
html.bfc-viewing .product-header_product-details .product-inner-footer-wrapper { display: none; }
/* Desktop: the column opens downward only (Chris, 2026-10-20). The Designer centres the buy column in the screen; while
   the configurator runs, the script pins it at the top it has when folded, so the options grow below and the space under
   the header stays. Code because the drop depends on the column's height. The script sets html.bfc-anchored and --bfc-drop. */
@media screen and (min-width: 992px) {
  html.bfc-anchored .product-header_product-details { align-items: flex-start; }
  html.bfc-anchored .product-header_product-details > .product_inner { margin-top: var(--bfc-drop, 0px); }
}
/* Open on desktop: 88px between Add to cart and the links below (Chris, 2026-10-01). */
.bfc.is-desktop { margin-bottom: 48px; }
.bfc.is-desktop.is-open { margin-bottom: 88px; }

.bfc button { font: inherit; color: inherit; cursor: pointer; }
/* The reset above also cleared the solid buttons' weight (Add to cart and the desktop fold read 400); put it back.
   All solid buttons share one weight: 500 since 2026-10-15 (was 600), once the site dropped antialiased smoothing. */
.bfc .bfc_button, .bfc .bfc_fold-button { font-weight: 500; }
.bfc_icon { display: inline-flex; flex-shrink: 0; }
.bfc_icon svg { display: block; }
.bfc_icon.is-up svg { transform: rotate(180deg); }
.bfc_icon.is-right svg { transform: rotate(-90deg); }
.bfc_icon.is-left svg { transform: rotate(90deg); }

.bfc_group { display: flex; flex-direction: column; gap: 10px; }
.bfc_label-row { display: flex; justify-content: space-between; align-items: baseline; }
/* Series (B′ canvas, 2026-10-05): an 11px label on a 24px row, 8px above the series box. */
.bfc_group.is-series { gap: 8px; }
.bfc_group.is-series .bfc_label-row { height: 24px; }
.bfc_group.is-series .bfc_label { font-size: 11px; }
/* "More than 10?" also carries the site's .text-style-link (its underline and hover); this keeps it grey and 12px. */
.bfc_label-link.text-style-link { color: var(--bfc-grey); font-size: 12px; }
/* Tracking follows the site's Letter Spacing variables (Webflow Typography collection, House of Spoils scale, 2026-10-15):
   Text 0.013rem on sentence labels, Caps 0.025rem on anything in capitals. The fallbacks hold if a variable is renamed. */
.bfc_label { font-size: 12px; font-weight: 500; line-height: 18px; letter-spacing: var(--_typography---letter-spacing--text, 0.013rem); color: var(--bfc-ink); }
.bfc_inline-link, .bfc_text-link {
  font-size: 12px; line-height: 15px; color: var(--bfc-grey);
  text-decoration: underline; text-underline-offset: 3px;
}
.bfc_text-link { color: var(--bfc-ink); background: none; border: 0; padding: 0; }

/* Series: the live variant row, stacked. A 1px grid of line colour; selected is a 1px black ring. */
.bfc_series-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1px; padding: 1px; background: var(--bfc-line); }
/* 12px 16px padding on a 50px minimum, so a row can grow if its text wraps (B′ canvas, 2026-10-05). */
.bfc_series-option {
  min-height: 50px; box-sizing: border-box; padding: 12px 16px; border: 0; background: #FFFFFF;
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; text-align: left;
}
.bfc_series-option.is-selected { box-shadow: 0 0 0 1px #000000; position: relative; z-index: 1; }
/* A pick changes its ring over 300ms ease-in-out, as prada.com's size tabs. */
.bfc_series-option { transition: box-shadow .3s ease-in-out; }
.bfc_series-name { font-weight: 500; line-height: 16px; }
/* Counts in the palette's gray-500, prices in ink (B′ canvas, 2026-10-05). */
/* The portrait count reads in the darker Gray 600, as on the canvas (Chris, 2026-10-12; was Gray 500). */
.bfc_series-count { color: var(--bfc-grey); line-height: 16px; text-align: center; }
.bfc_series-price { color: var(--bfc-ink); line-height: 16px; text-align: right; }

/* The Color row (Reserve Edition; canvas ReservePage, PhoneReserve, PhSheet): an 11px label on a 24px row with the chosen
   color's name at the right, then seven adjoining cells 50px tall (1px Gray 200 frame, black on the one chosen) each with
   a 20px dot. Same label row as Series. No House Colors / Your Brand tabs at launch. */
.bfc_group.is-house { gap: 8px; }
.bfc_group.is-house .bfc_label-row { height: 24px; }
.bfc_group.is-house .bfc_label { font-size: 11px; }
.bfc_house-name { font-size: 12px; line-height: 18px; color: var(--bfc-grey); }
.bfc_house-list { display: flex; }
.bfc_house-cell {
  flex: 1 1 0; min-width: 0; height: 50px; margin-left: -1px; padding: 0; box-sizing: border-box;
  border: 1px solid var(--bfc-line); background: #FFFFFF; position: relative; z-index: 1;
  display: flex; align-items: center; justify-content: center;
  transition: border-color .3s ease-in-out;
}
.bfc_house-cell:first-child { margin-left: 0; }
.bfc_house-cell.is-selected { border-color: #000000; z-index: 2; }
.bfc_house-dot { display: block; width: 20px; height: 20px; border-radius: 50%; }

/* ---- Your Brand (YOUR-BRAND-BUILD-PLAN Task 10; boards ReservePage, PhoneReserve, PhSheet) --------------------------------------
   Where Your Brand is on, the Color label gives way to two tabs, House Colors and Your Brand: 12px medium on an 18px line, 28px apart,
   10px above a 1px Gray 200 rule, Gray 500 until chosen, then ink. Under the chosen one a 2px ink line (one 1px-wide line the script
   moves and scales under it) slides across over 200ms cubic-bezier(.4,0,.2,1); until the script has measured it, the chosen tab's
   own underline shows. The House Color's name (or "Studio mix · <code>") sits at the right, on the tabs' baseline. The pane under
   them is 16px down and fades in over 300ms cubic-bezier(0,0,.2,1) when the tab changes. Classes the script sets at runtime. */
.bfc_group.is-house.has-tabs { gap: 16px; }
.bfc_tabs-row { display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; border-bottom: 1px solid var(--bfc-line); }
.bfc_tabs { display: flex; gap: 28px; position: relative; flex-shrink: 0; }
.bfc .bfc_tab {
  margin: 0 0 -1px; padding: 0 0 10px; border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: none;
  font-size: 12px; font-weight: 500; line-height: 18px; letter-spacing: var(--_typography---letter-spacing--text, 0.013rem);
  color: var(--bfc-quiet); transition: color .2s linear;
}
.bfc .bfc_tab.is-on { color: var(--bfc-ink); }
.bfc_tabs:not(.has-line) .bfc_tab.is-on { border-bottom-color: var(--bfc-ink); }
.bfc_tab-line { position: absolute; left: 0; bottom: -1px; width: 1px; height: 2px; background: var(--bfc-ink); transform-origin: 0 0; pointer-events: none; }
.bfc_tabs:not(.has-line) .bfc_tab-line { opacity: 0; }
.bfc_tab-line.is-moving { transition: transform .2s cubic-bezier(.4,0,.2,1); }
.bfc_tabs-row .bfc_house-name { min-width: 0; padding-bottom: 10px; text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@keyframes bfcPaneIn { from { opacity: 0; } to { opacity: 1; } }
.bfc_pane { display: flex; flex-direction: column; }
.bfc_pane.is-in { animation: bfcPaneIn .3s cubic-bezier(0,0,.2,1); }
/* Your Brand with no code: a grey line, then Add Your Brand Color, an outlined 50px button 16px under it (not in capitals). With a
   code: a 50px ink-ringed box, 16px in, holding the 20px chip (blank and ringed for a Pantone), the code and Change at the right. */
.bfc_brand-intro { margin: 0; color: var(--bfc-grey); }
.bfc .bfc_brand-add {
  margin-top: 16px; width: 100%; height: 50px; box-sizing: border-box; padding: 0 16px; border: 1px solid var(--bfc-ink); border-radius: 0;
  background: #FFFFFF; color: var(--bfc-ink); font-size: 12px; font-weight: 500; line-height: 18px; letter-spacing: 0.2px;
}
.bfc_brand-saved { height: 50px; box-sizing: border-box; padding: 0 16px; border: 1px solid var(--bfc-ink); display: flex; align-items: center; gap: 12px; }
.bfc_brand-chip { display: block; width: 20px; height: 20px; flex-shrink: 0; border-radius: 50%; }
.bfc_brand-chip.is-blank { background: #FFFFFF; box-shadow: inset 0 0 0 1px rgba(27, 27, 27, 0.12); }
.bfc_brand-code { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Change: the 18px link with 15px of padding above and below, so the tap target is the box's height. */
.bfc .bfc_brand-change {
  margin: 0 0 0 auto; padding: 15px 0; flex-shrink: 0; border: 0; background: none;
  font-size: 12px; line-height: 18px; color: var(--bfc-grey); text-decoration: underline; text-underline-offset: 3px;
}
/* The fold Your Brand closes (the boards' buy section: Series, the fold button and the options). Its row eases 1fr to 0fr over 600ms
   cubic-bezier(.4,0,.2,1); the content fades out over 400ms at once and is hidden once the row has shut (so nothing in it can take
   the focus), and fades in over 350ms after 150ms when it opens. Its -32px (-24px on phones) cancels the column's gap, and its inner
   32px (24px) puts it back, so a shut fold takes no room. The visibility is only ever hidden here, never set visible, so the phone's
   resting and dropped column (which hides the mount) still hides it. */
.bfc_buy { margin-top: -32px; display: grid; grid-template-rows: 1fr; transition: grid-template-rows .6s cubic-bezier(.4,0,.2,1); }
.bfc_buy.is-shut { grid-template-rows: 0fr; }
.bfc_buy-clip { min-height: 0; overflow: clip; overflow-clip-margin: 4px; transition: opacity .35s cubic-bezier(.4,0,.2,1) .15s, visibility 0s; }
.bfc_buy.is-shut .bfc_buy-clip { opacity: 0; visibility: hidden; transition: opacity .4s cubic-bezier(.4,0,.2,1), visibility 0s linear .6s; }
.bfc_buy-inner { display: flex; flex-direction: column; gap: 32px; padding-top: 32px; }
@media (max-width: 991px) {
  .bfc.is-phone .bfc_buy { margin-top: -24px; }
  .bfc.is-phone .bfc_buy-inner { gap: 24px; padding-top: 24px; }
}
@media (prefers-reduced-motion: reduce) {
  .bfc .bfc_tab, .bfc_tab-line.is-moving, .bfc_buy, .bfc_buy-clip, .bfc_buy.is-shut .bfc_buy-clip { transition: none; }
  .bfc_pane.is-in { animation: none; }
}

/* The fold (desktop and phones). Black when closed, a pale bar once open. */
.bfc_fold { display: flex; flex-direction: column; gap: 12px; }
.bfc_fold-button, .bfc_button {
  width: 100%; height: 52px; padding: 0 16px; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-size: 12px; font-weight: 500; letter-spacing: var(--_typography---letter-spacing--caps, 0.025rem); text-transform: uppercase;
  background: var(--bfc-ink); color: #FFFFFF !important; border: 1px solid var(--bfc-ink);
}
.bfc_fold-button.is-open { background: var(--bfc-off-bg); border-color: var(--bfc-off-bg); color: var(--bfc-ink) !important; }
/* The fold opens like prada.com's FAQ accordion (.faq-item__grid-container, read from their stylesheet 2026-10-05):
   the row grows 0fr to 1fr over .6s cubic-bezier(.4,0,.2,1) both ways; the options fade in .35s after a .15s delay on
   open and out over .4s at once on close; the chevron turns and the button eases to the pale bar on the same .6s.
   The -32px cancels the column gap, so a closed row takes no space; the margin under the column eases with it. */
.bfc_fold-button { transition: background-color .6s cubic-bezier(.4,0,.2,1), border-color .6s cubic-bezier(.4,0,.2,1), color .6s cubic-bezier(.4,0,.2,1); }
.bfc_fold-button .bfc_icon svg { transition: transform .6s cubic-bezier(.4,0,.2,1); }
.bfc_acc { margin-top: -32px; display: grid; grid-template-rows: 0fr; transition: grid-template-rows .6s cubic-bezier(.4,0,.2,1); }
.bfc_acc.is-open { grid-template-rows: 1fr; }
.bfc_acc-wrap { min-height: 0; overflow: clip; overflow-clip-margin: 4px; opacity: 0; transition: opacity .4s cubic-bezier(.4,0,.2,1); }
.bfc_acc.is-open .bfc_acc-wrap { opacity: 1; transition-delay: .15s; transition-duration: .35s; }
.bfc_acc .bfc_options { padding-top: 32px; }
.bfc.is-desktop { transition: margin-bottom .6s cubic-bezier(.4,0,.2,1); }
@media (prefers-reduced-motion: reduce) {
  .bfc_fold-button, .bfc_fold-button .bfc_icon svg, .bfc_acc, .bfc_acc-wrap, .bfc.is-desktop { transition: none; }
}
/* The fold reads "Select Branding, Timeline & Files": each word capitalized, not all caps, no tracking; weight 600 like
   the other solid buttons (set with the reset fix above). */
.bfc_fold-button { text-transform: none; letter-spacing: 0; }
.bfc_button[disabled], .bfc_button.is-busy { opacity: 0.6; cursor: default; }
.bfc_button.is-off { background: var(--bfc-off-bg); border-color: var(--bfc-off-bg); color: var(--bfc-off-ink) !important; cursor: default; }

.bfc_options { display: flex; flex-direction: column; gap: 24px; }
/* Timeline, Files (and Finish once Branded is on): two-line rows in the Series rows' 1px Gray 200 frame (canvas C2),
   16px vertical padding on a 50px minimum (Chris, 2026-10-05). */
.bfc_group.is-row { gap: 8px; }
.bfc_row-box { display: grid; grid-template-columns: minmax(0, 1fr); padding: 1px; background: var(--bfc-line); }
.bfc_row {
  width: 100%; min-height: 50px; box-sizing: border-box; padding: 16px 8px 16px 16px; border: 0; background: #FFFFFF;
  display: flex; align-items: center; justify-content: space-between; gap: 16px; text-align: left;
}
.bfc_row-text { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bfc_row-value { display: flex; align-items: center; gap: 8px; font-weight: 500; line-height: 16px; }
/* Timeline and Files sub-lines in Gray 600, like the Series counts (Chris, 2026-10-12; was Gray 500). */
.bfc_row-sub { line-height: 16px; color: var(--bfc-grey); }
.bfc_row-end { flex-shrink: 0; display: flex; align-items: center; gap: 2px; }
.bfc_row-up { line-height: 16px; white-space: nowrap; color: var(--bfc-ink); }
.bfc_swatch-dot { width: 10px; height: 10px; flex-shrink: 0; display: inline-block; }
.bfc_photos { margin: 0; color: var(--bfc-grey); }

/* A choice opened in place in the buy column (phones, tablets and desktop): a back arrow and the name,
   then the choices as stacked cards. Picking one goes straight back to the rows. */
.bfc_view { display: flex; flex-direction: column; gap: 16px; }
.bfc_view-head { display: flex; align-items: center; margin-left: -14px; }
.bfc_view-head .bfc_back { margin: 0; }
.bfc_view-title { margin: 0; flex-grow: 1; font-size: 13px; font-weight: 500; line-height: 18px; color: var(--bfc-ink); letter-spacing: 0; }
.bfc_view .bfc_panel-intro { margin: 0; font-size: 12px; line-height: 18px; color: var(--bfc-grey); }
.bfc_view .bfc_cards { gap: 8px; }
.bfc_view .bfc_card { padding: 20px; transition: box-shadow .3s ease-in-out; }
.bfc_view .bfc_card-text { gap: 4px; }

/* Panels. The overlay matches the site's slide-outs: rgba(35,35,35,.2) under a 5px blur.
   Branded panels blur only the strip of details column between the gallery and the panel,
   so the portrait stays sharp while the colour is chosen. */
.bfc_overlay {
  position: fixed; inset: 0; z-index: 998;
  background: rgba(35, 35, 35, 0.2); -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
  opacity: 0; transition: opacity 500ms cubic-bezier(.4, 0, .2, 1);
}
.bfc_overlay.is-in { opacity: 1; transition-duration: 500ms; }
.bfc_overlay.is-strip { left: 50%; right: 520px; }
.bfc_panel {
  position: fixed; z-index: 999; background: #FFFFFF; color: #1B1B1B; box-sizing: border-box;
  display: flex; flex-direction: column; outline: none;
  font-size: 12px; line-height: 18px;
}
.bfc_panel button { font: inherit; color: inherit; cursor: pointer; }
.bfc_panel.is-side {
  top: 0; right: 0; bottom: 0; width: 520px; max-width: 100vw; padding: 40px 32px 32px;
  transform: translateX(100%); transition: transform 500ms cubic-bezier(.4, 0, .2, 1);
}
.bfc_panel.is-sheet {
  left: 0; right: 0; bottom: 0; max-height: calc(100% - 90px); padding: 0 0 24px;
  transform: translateY(100%); transition: transform 500ms cubic-bezier(.4, 0, .2, 1);
}
/* Open and close timing is the page's Portrait Details panel (Webflow interactions a-86 / a-80): 500ms each way,
   cubic-bezier(.4,0,.2,1), overlay fading alongside (Chris, 2026-10-12: every panel opens at 0.5s, was 0.7s in).
   Kept in step with closePanel's 500ms removal. */
.bfc_panel.is-in { transform: none; transition-duration: 500ms; }
.bfc_panel-head { display: flex; align-items: center; flex-shrink: 0; }
.bfc_panel.is-side .bfc_panel-head { margin-bottom: 20px; }
.bfc_panel.is-sheet .bfc_panel-head { height: 56px; padding: 0 12px 0 20px; margin-bottom: 8px; }
.bfc_panel-title { margin: 0; flex-grow: 1; font-weight: 400; color: #000000; }
/* One panel header everywhere (Chris, 2026-10-12): the title as Portrait details sets it, 13px medium, not 24px. */
.bfc_panel.is-side .bfc_panel-title { font-size: 13px; font-weight: 500; line-height: 15.6px; letter-spacing: 0.24px; color: var(--bfc-ink); }
.bfc_panel.is-sheet .bfc_panel-title { font-size: 13px; font-weight: 500; line-height: 18px; color: #1B1B1B; }
.bfc_close, .bfc_back { width: 44px; height: 44px; padding: 0; border: 0; background: none; display: flex; align-items: center; justify-content: center; }
.bfc_panel.is-side .bfc_close { position: absolute; top: 12px; right: 12px; }
/* Phone drawers and sheets: the close sits 12px from the top and right, as on every Webflow panel, so the X lands in the
   same spot everywhere (Chris, 2026-10-12; the heads' right padding is 12px for it). The title keeps its place. */
.bfc_panel.is-drawer .bfc_close, .bfc_panel.is-sheet .bfc_close { align-self: flex-start; margin-top: 12px; }
.bfc_back { margin: -4px 0 -4px -14px; }
.bfc_panel-body { flex-grow: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 24px; }
.bfc_panel.is-sheet .bfc_panel-body { padding: 0 20px; gap: 20px; }
.bfc_panel-foot { display: flex; gap: 10px; padding-top: 24px; flex-shrink: 0; }
.bfc_panel.is-sheet .bfc_panel-foot { padding: 16px 20px 0; }
.bfc_panel .bfc_button {
  width: 100%; height: 52px; display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 500; letter-spacing: var(--_typography---letter-spacing--caps, 0.025rem); text-transform: uppercase;
  background: #1B1B1B; color: #FFFFFF; border: 1px solid #1B1B1B;
}
.bfc_panel .bfc_button.is-off { background: #F4F4F5; border-color: #F4F4F5; color: #9A9CA5; cursor: default; }
.bfc_panel-intro { margin: 0; font-size: 13px; line-height: 22px; color: #5D5F69; }
.bfc_panel.is-sheet .bfc_panel-intro { font-size: 12px; line-height: 18px; }
.bfc_panel .bfc_label { font-size: 12px; font-weight: 500; line-height: 18px; letter-spacing: var(--_typography---letter-spacing--text, 0.013rem); }
.bfc_panel .bfc_group { display: flex; flex-direction: column; gap: 10px; }
.bfc_panel .bfc_text-link { font-size: 12px; line-height: 15px; color: #1B1B1B; background: none; border: 0; padding: 0; text-decoration: underline; text-underline-offset: 3px; }

/* The page behind an open panel does not scroll, as with the site's own slide-outs. */
body.bfc-panel-open { overflow: hidden; }

/* Phones and tablets: Timeline, Files and the team quote open as prada.com's Select size drawer (recorded 2026-10-05,
   Chris: in place it felt crowded). It takes the whole screen, header included, sliding up from the bottom over 500ms
   cubic-bezier(.4,0,.2,1) both ways (their .drawer-container) while the backdrop fades in over 800ms
   cubic-bezier(.42,0,0,1). The title and close stay pinned at the top (their sticky header); the rest scrolls inside,
   and the page behind holds still (their html overflow: hidden). */
html.bfc-drawer-open { overflow: hidden; }
/* The backdrop is the site's grey blur, the same behind every panel (Chris, 2026-10-12; was Prada's 70% black). */
.bfc_overlay.is-drawer { z-index: 1000; transition: opacity 800ms cubic-bezier(.42, 0, 0, 1); }
.bfc_overlay.is-drawer.is-in { transition-duration: 800ms; }
.bfc_panel.is-drawer {
  z-index: 1001; inset: 0; height: 100%; padding: 0;
  transform: translateY(100%); transition: transform 500ms cubic-bezier(.4, 0, .2, 1);
}
.bfc_panel.is-drawer.is-in { transform: none; transition-duration: 500ms; }
.bfc_panel.is-drawer .bfc_panel-head { height: 64px; padding: 0 12px 0 20px; background: #FFFFFF; }
.bfc_panel.is-drawer .bfc_panel-title { font-size: 13px; font-weight: 500; line-height: 18px; color: var(--bfc-ink); letter-spacing: 0; }
.bfc_panel.is-drawer .bfc_panel-body { padding: 8px 20px calc(32px + env(safe-area-inset-bottom, 0px)); gap: 16px; overscroll-behavior: contain; }
.bfc_panel.is-drawer .bfc_panel-intro { font-size: 12px; line-height: 18px; color: var(--bfc-grey); }
.bfc_panel.is-drawer .bfc_cards { gap: 8px; }
.bfc_panel.is-drawer .bfc_card { padding: 20px; transition: box-shadow .3s ease-in-out; }
/* The quote's Request a quote row stays pinned to the bottom of the drawer (Designer: sticky, bottom 0), as their Size
   Chart row, with the safe area under it so the Terms / Privacy Policy underlines stay on screen. */
.bfc_panel.is-drawer[data-panel-name="quote"] .bfc_panel-body { padding-bottom: 0; }
.bfc_panel.is-drawer .team-quote_submit-wrap { padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }

/* "Your brand color" (Your Brand, Task 10; boards ReservePage start="mix", PhoneReserve, PhSheet). The panel's chrome is every panel's
   (desktop: the 520px side panel from the right over the full-screen blur, 500ms cubic-bezier(.4,0,.2,1); phones and tablets: the
   full-screen drawer); the body is the boards': the 13px intro, an 11px label 36px down, the 44px field 8px under it (12px type on
   18px, 14px in, 40px with the chip of a hex), the error and the note 8px under that, How it works and the sample 40px apart, the three
   4:5 mixes 12px apart, the $40 line 40px down and Save Brand Color 12px under it (48px, not in capitals). Phones: 32px steps, the
   mixes 8px apart, a 52px Save. The phone drawer slides in from the right, as the boards draw it, and its backdrop fades over 500ms.
   The error red is the boards' #B3261E (the palette's Color - Error is too light for 12px text). */
.bfc_panel[data-panel-name="brand"] .bfc_panel-body { gap: 0; }
.bfc_brandp-intro { margin: 0; font-size: 13px; line-height: 22.1px; letter-spacing: 0.208px; color: var(--bfc-ink); }
.bfc_brandp-label { margin-top: 36px; font-size: 11px; font-weight: 500; line-height: 18px; color: var(--bfc-ink); }
.bfc_brandp-field { margin-top: 8px; position: relative; display: flex; flex-direction: column; }
.bfc_brandp-chip { position: absolute; left: 14px; top: 14px; width: 16px; height: 16px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(27, 27, 27, 0.12); pointer-events: none; }
.bfc_brandp-input {
  height: 44px; box-sizing: border-box; margin: 0; padding: 0 14px; border: 1px solid var(--bfc-line); border-radius: 0; background: #FFFFFF;
  font: inherit; font-size: 12px; line-height: 18px; color: var(--bfc-ink); outline: none; -webkit-appearance: none; appearance: none;
}
.bfc_brandp-input::placeholder { color: var(--bfc-quiet); opacity: 1; }
.bfc_brandp-field.has-chip .bfc_brandp-input { padding-left: 40px; }
.bfc_brandp-input:focus { border-color: var(--bfc-ink); }
.bfc_brandp-input[aria-invalid="true"] { border-color: #B3261E; }
.bfc_brandp-error { margin-top: 8px; font-size: 12px; line-height: 18px; color: #B3261E; }
.bfc_brandp-note { margin-top: 8px; font-size: 12px; line-height: 18px; color: var(--bfc-grey); }
.bfc_brandp-how, .bfc_brandp-sample { margin-top: 40px; font-size: 11px; font-weight: 500; line-height: 18px; color: var(--bfc-ink); }
.bfc_brandp-sample { display: flex; align-items: center; gap: 8px; }
.bfc_brandp-dot { display: block; width: 10px; height: 10px; flex-shrink: 0; border-radius: 50%; background: #1F2A44; }
.bfc_brandp-steps { margin-top: 12px; display: grid; grid-template-columns: 24px minmax(0, 1fr); row-gap: 10px; font-size: 13px; line-height: 19.5px; color: var(--bfc-ink); }
.bfc_brandp-steps > span:nth-child(2n+1) { color: var(--bfc-grey); }
.bfc_brandp-mixes { margin-top: 12px; display: flex; gap: 12px; }
.bfc_brandp-mix { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
.bfc_brandp-mix img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; background: var(--bfc-ground); }
.bfc_brandp-mix span { font-size: 12px; line-height: 18px; color: var(--bfc-grey); }
.bfc_brandp-mix img + span { margin-top: 8px; }
.bfc_brandp-adds { margin-top: 40px; font-size: 12px; line-height: 18px; color: var(--bfc-grey); }
.bfc_panel .bfc_brandp-save {
  margin-top: 12px; flex-shrink: 0; width: 100%; height: 48px; padding: 0 16px; border: 0; border-radius: 0;
  background: var(--bfc-ink); color: #FFFFFF; font-size: 12px; font-weight: 500; line-height: 18px; letter-spacing: 0.2px; text-transform: none;
}
.bfc_panel .bfc_brandp-save.is-off { background: var(--bfc-off-bg); color: var(--bfc-off-ink); cursor: default; }
.bfc_overlay.is-drawer.is-brand, .bfc_overlay.is-drawer.is-brand.is-in { transition: opacity 500ms cubic-bezier(.4, 0, .2, 1); }
.bfc_panel.is-drawer.is-brand { transform: translateX(100%); }
.bfc_panel.is-drawer.is-brand.is-in { transform: none; }
.bfc_panel.is-drawer.is-brand .bfc_brandp-label, .bfc_panel.is-drawer.is-brand .bfc_brandp-how,
.bfc_panel.is-drawer.is-brand .bfc_brandp-sample, .bfc_panel.is-drawer.is-brand .bfc_brandp-adds { margin-top: 32px; }
.bfc_panel.is-drawer.is-brand .bfc_brandp-mixes { gap: 8px; }
.bfc_panel.is-drawer.is-brand .bfc_brandp-save { height: 52px; }

/* Choice cards: a 1px ring, black when selected. */
.bfc_cards { display: flex; flex-direction: column; gap: 12px; }
.bfc_card {
  width: 100%; display: flex; gap: 14px; padding: 24px; border: 0; background: #FFFFFF; text-align: left;
  box-shadow: inset 0 0 0 1px #E1E2E5;
}
.bfc_card.is-selected { box-shadow: inset 0 0 0 1px #000000; }
.bfc_card-image { width: 72px; height: 90px; object-fit: cover; object-position: center 70%; display: block; flex-shrink: 0; background: #F7F7F7; }
.bfc_card-text { flex-grow: 1; display: flex; flex-direction: column; gap: 4px; }
.bfc_card.has-image .bfc_card-text { justify-content: center; }
.bfc_card-top { display: flex; justify-content: space-between; gap: 12px; }
.bfc_card-name { font-weight: 500; }
.bfc_card-price, .bfc_card-desc { color: #5D5F69; }

/* Colour code field: a chip of the colour, then the code. */
.bfc_field { display: flex; flex-direction: column; gap: 8px; }
.bfc_code { display: flex; align-items: center; height: 52px; border: 1px solid #E1E2E5; background: #FFFFFF; }
.bfc_code:focus-within { border-color: #000000; }
.bfc_code-chip { width: 50px; height: 50px; flex-shrink: 0; border-right: 1px solid #E1E2E5; }
.bfc_code-input { flex-grow: 1; min-width: 0; height: 50px; border: 0; padding: 0 14px; font: inherit; letter-spacing: 0.2px; background: transparent; color: #1B1B1B; outline: none; }
.bfc_code-msg { margin: 0; color: #1B1B1B; }
.bfc_code-msg:empty { display: none; }

.bfc_swatches { display: flex; justify-content: space-between; }
.bfc_swatch { width: 56px; height: 56px; padding: 0; border: 0; position: relative; overflow: hidden; }
.bfc_panel.is-sheet .bfc_swatch { width: 50px; height: 50px; }
.bfc_swatch-fill { position: absolute; left: 0; right: 0; bottom: 0; height: 44%; }
.bfc_swatch.is-selected { outline: 1px solid #000000; outline-offset: 3px; }
.bfc_swatch-caption { color: #5D5F69; }
.bfc_swatch-caption.is-named { color: #1B1B1B; }

.bfc_site { display: flex; height: 52px; border: 1px solid #E1E2E5; }
.bfc_site:focus-within { border-color: #000000; }
.bfc_site-input { flex-grow: 1; min-width: 0; border: 0; padding: 0 16px; font: inherit; background: transparent; outline: none; color: #1B1B1B; }
.bfc_site-go { border: 0; background: none; padding: 0 16px; font-weight: 500; text-transform: uppercase; letter-spacing: var(--_typography---letter-spacing--caps, 0.025rem); }
.bfc_site-list { display: flex; flex-direction: column; gap: 8px; }
.bfc_site-color { height: 56px; display: flex; align-items: center; gap: 14px; padding: 0 16px 0 8px; border: 0; background: #FFFFFF; box-shadow: inset 0 0 0 1px #E1E2E5; text-align: left; }
.bfc_site-color.is-selected { box-shadow: inset 0 0 0 1px #000000; }
.bfc_site-chip { width: 40px; height: 40px; flex-shrink: 0; }
.bfc_site-role { flex-grow: 1; }
.bfc_site-hex { color: #5D5F69; }

.bfc :focus-visible, .bfc_panel :focus-visible { outline: 1px solid #000000; outline-offset: 2px; }
/* After a tap or click (html.bfc-pointer, set by the script), no ring on the focus the configurator moves for keyboards
   and screen readers: iOS Safari rings it, which drew a box round the quote's back arrow and a second outline round the
   chosen series. Keyboard use brings the rings back. A page-state class the Designer can't target. */
html.bfc-pointer .bfc :focus-visible, html.bfc-pointer .bfc_panel :focus-visible, html.bfc-pointer .bfc_handle:focus-visible,
html.bfc-pointer .bfc_choose :focus-visible, html.bfc-pointer .team-quote_count:has(input:focus-visible) { outline: none; }

@media (prefers-reduced-motion: reduce) {
  .bfc_overlay, .bfc_panel, .bfc_overlay.is-drawer, .bfc_panel.is-drawer { transition: none; }
}


/* Team quote panel ("More than 10?", canvas Quote 1 and Quote 3, 2026-10-05). The fields are the Designer's native
   "Team Quote" form, styled there; what follows are the states the Designer can't express. Colours are palette
   variables through the --bfc-* tokens (the live Teams form's off-palette #4E555A / #6E7077 greys became gray-600). */
.bfc_panel[data-panel-name="quote"].is-side .bfc_panel-head { margin-bottom: 8px; }
.bfc_quote-intro { margin: 0 0 8px; font-size: 12px; line-height: 18px; color: var(--bfc-grey); }
.bfc_quote-style { display: flex; flex-direction: column; }
.bfc_quote-card { display: flex; align-items: center; gap: 20px; padding: 12px 16px 12px 12px; background: var(--bfc-ground); }
.bfc_quote-shot { width: 88px; height: 110px; object-fit: cover; display: block; flex-shrink: 0; }
.bfc_quote-text { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bfc_quote-name { font-weight: 500; color: var(--bfc-ink); }
.bfc_quote-sub { color: var(--bfc-grey); }
.bfc_quote-change { flex-shrink: 0; font-size: 12px; line-height: 15px; }
/* The Change strip: the reorder sheet's (reorder-sheet.js .rs-strip). Height grows 0fr to 1fr over .45s, the tiles
   fade in .12s behind it; the last tile fades out to read as more to the right. */
.bfc_quote-stripwrap { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .45s cubic-bezier(.4,0,.2,1); }
.bfc_quote-stripwrap.is-open { grid-template-rows: 1fr; }
.bfc_quote-stripinner { min-height: 0; overflow: hidden; opacity: 0; transition: opacity .3s cubic-bezier(.4,0,.2,1); }
.bfc_quote-stripwrap.is-open .bfc_quote-stripinner { opacity: 1; transition-delay: .12s; }
.bfc_quote-striplab { margin-top: 18px; color: var(--bfc-grey); }
.bfc_quote-strip { margin-top: 8px; display: flex; gap: 14px; overflow-x: auto; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 64px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 64px), transparent); }
.bfc_quote-strip::-webkit-scrollbar { display: none; }
.bfc_panel.is-sheet .bfc_quote-strip { gap: 12px;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); }
.bfc_quote-tile { flex: none; width: 104px; padding: 0; border: 0; background: none; text-align: left; }
.bfc_quote-tile-shot { display: block; width: 104px; height: 132px; box-sizing: border-box; border: 1px solid var(--bfc-ground); background: var(--bfc-ground); overflow: hidden; transition: border-color .3s ease-in-out; }
.bfc_quote-tile-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bfc_quote-tile:hover .bfc_quote-tile-shot { border-color: var(--bfc-quiet); }
.bfc_quote-tile-name { display: block; margin-top: 8px; color: var(--bfc-grey); transition: color .2s; }
.bfc_quote-tile:hover .bfc_quote-tile-name { color: var(--bfc-ink); }
.bfc_quote-change:focus-visible, .bfc_quote-tile:focus-visible { outline: 1px solid var(--bfc-ink); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .bfc_quote-stripwrap, .bfc_quote-stripinner { transition: none; } }

/* Floating labels, as the live Teams form (bf-float-field): the label sits centred at full size and rises to the top
   left on focus or once filled. :focus / :placeholder-shown / :valid states have no Designer setting. The note box
   (textarea, is-note) starts its label on the first line instead of the middle (Designer: top 28px). */
.team-quote_label { transform: translateY(-50%); z-index: 2; transition: top .2s ease, font-size .2s ease, color .2s ease, transform .2s ease; }
.team-quote_input:focus { outline: none; }
.team-quote_field:focus-within { border-color: var(--bfc-ink); }
.team-quote_input::placeholder { color: transparent; }
select.team-quote_input { -webkit-appearance: none; appearance: none; padding-right: 40px; }
select.team-quote_input:invalid { color: transparent; }
select.team-quote_input option { color: var(--bfc-ink); }
.team-quote_input:focus ~ .team-quote_label,
input.team-quote_input:not(:placeholder-shown) ~ .team-quote_label,
textarea.team-quote_input:not(:placeholder-shown) ~ .team-quote_label,
select.team-quote_input:valid ~ .team-quote_label { top: 8px; transform: none; font-size: 10px; color: var(--bfc-grey); }
.team-quote_field.is-select .team-quote_label { right: 36px; }
/* The select's chevron, the configurator's own, drawn behind the field (a pseudo-element the Designer can't place). */
.team-quote_field.is-select::after { content: ""; position: absolute; right: 16px; top: 50%; width: 10px; height: 6px; margin-top: -3px; pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10.43 5.13' fill='none'%3E%3Cpath d='M0.5 0.5L4.54759 4.36361C4.91579 4.71508 5.51278 4.71508 5.88098 4.36361L9.92857 0.5' stroke='%231B1B1B' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / contain; }
/* "How many portraits": the live Teams form's form_radio-btn states. Checked is black border and text on white. */
.team-quote_count { transition: border-color .2s, color .2s; }
.team-quote_count:has(input:checked) { border-color: var(--_color---color-black, #000000); color: var(--_color---color-black, #000000); }
.team-quote_count:has(input:focus-visible) { outline: 1px solid var(--_color---color-black, #000000); outline-offset: 2px; }
.team-quote_submit:focus-visible { outline: 1px solid var(--bfc-ink); outline-offset: 2px; }
/* Webflow adds an empty, classless div after the submit for its Turnstile check. As a form row it took the form's row
   gap (24px, team-quote_form) under the pinned button; pull that back so the button and terms sit on the panel's bottom
   edge. Keep this equal to the Designer gap. The div is injected at runtime, so the Designer can't style it. */
.team-quote_form > .team-quote_submit-wrap + div:not([class]) { margin-top: -24px; }
/* "How many portraits": Webflow publishes each button as <label for="">, and an empty for links the label to nothing,
   so taps on the text never reached the radio. The Designer now stretches the invisible radio over the whole button
   (team-quote_count-input); this drops its native appearance so iOS Safari doesn't keep a small native box. The Designer
   has no appearance setting. */
.team-quote_count-input { -webkit-appearance: none; appearance: none; }
/* Inline errors (canvas Quote 4): the configurator checks the quote form itself, so a missing answer or a free-mail
   address shows a red line under the question instead of the browser's pop-up. The field and its label turn the palette's
   Color - Error; the line is added and removed at runtime, so these states have no Designer element to style. */
.team-quote_field.is-error, .team-quote_field.is-error:focus-within { border-color: var(--_color---color-error, #E22222); }
.team-quote_field.is-error .team-quote_label { color: var(--_color---color-error, #E22222); }
.team-quote_error-msg { margin: 0; font-size: 12px; line-height: 18px; color: var(--_color---color-error, #E22222); }


/* ---- C on phones and tablets, after prada.com's bottom sheet (canvas C1–C3, C8; Chris 2026-10-05) -----------------
   Two states. Resting (html.bfc-closed): the portrait fills the screen, the page's buy column peeks from the bottom
   with the bar, the name, the live total and Choose options; the page holds still, as prada.com's does. Open
   (html.bfc-open): the gallery gives way, the column sits under the header with Series, the rows, Add to cart, the
   perks and the panel links, and the page scrolls as one down to the footer. The configurator sets these classes
   (runtime states the Designer can't target), so the gift card and a configurator that stands down keep the
   Designer's plain layout. */
:root { --bfc-peek: 188px; }
@media (max-height: 700px) { :root { --bfc-peek: 172px; } }
/* The Reserve Edition's resting sheet also carries the Reserve Edition label, 21px between the name and the price, so its peek is 21px taller (2 Nov 2026:
   with the plain peek the room under Choose options was gone, and on a screen under 700px tall the button ran 1px past it, under a bottom toolbar).
   Choose options keeps plain Portrait Plus's room under it: 36px, or 20px on a short screen. --bfc-plus is the difference; the hero framing adds it back
   so the head stays where plain Portrait Plus's is. The drop sets its own peek (the script, to the color row) and takes none. */
html:has([data-bf-reserve]) { --bfc-plus: 21px; --bfc-peek: calc(188px + var(--bfc-plus)); }
@media (max-height: 700px) { html:has([data-bf-reserve]) { --bfc-peek: calc(172px + var(--bfc-plus)); } }
html.bfc-drop { --bfc-plus: 0px; }
@media (max-width: 991px) {
  html.bfc-closed, html.bfc-closed body { overflow: hidden; }
  /* The page never bounces past its ends while the column is in use, as prada.com's scroller (overscroll-behavior: none);
     with the script's pull-down handling this keeps Chrome's and Safari's pull-to-refresh out of the way. */
  html.bfc-peek, html.bfc-peek body { overscroll-behavior-y: none; }
  html.bfc-open .product-media-column { display: none; }
  html.bfc-open .product-header_component { padding-top: 64px; }
  /* The product template's header is see-through over the portrait for its first 700px of scroll (data-nav-mode
     hero-light); with the portrait gone the column would show through it, so the open state takes the header's own
     past-the-hero look straight away. */
  html.bfc-open .navbar_component:not(.is-hidden) { background-color: var(--_color---color-white, #FFFFFF); color: #000000; }
  html.bfc-open .navbar_component .cart-count { background-color: #000000; color: #FFFFFF; }
  /* Position only (for the bar), no z-index: a z-index here would trap the column's own slide-out panels (Portrait
     Details, Commission Process) under the header and the cards below wherever the head's :has() lift doesn't
     re-apply when a panel opens (seen on iOS Safari, 2026-10-05). */
  html.bfc-peek .product-header_product-details { position: relative; background: #FFFFFF; }
  /* The bar: a 28px tap band at the top of the column holding prada.com's grabber, 32x3 Gray 500. */
  .bfc_handle { position: absolute; left: 0; right: 0; top: 0; z-index: 2; height: 28px; padding: 0; border: 0; background: none;
    display: flex; align-items: center; justify-content: center; cursor: pointer; }
  .bfc_handle-bar { display: block; width: 32px; height: 3px; border-radius: 2px; background: var(--_color---color-gray-500, #868994); }
  .bfc_handle:focus-visible { outline: 1px solid #000000; outline-offset: -4px; }
  /* Choose options, 24px under the price (its row keeps a 20px margin); folds away on open over 200ms, as Select size. */
  .bfc_choose { height: 52px; margin-top: 4px; overflow: hidden; transition: height .2s cubic-bezier(.4, 0, .2, 1), margin .2s cubic-bezier(.4, 0, .2, 1); }
  .bfc_choose .bfc_button { cursor: pointer; font-family: inherit; }
  html.bfc-open .bfc_choose { height: 0; margin-top: -20px; }
  /* The options, perks and links wait unseen while the page rests, and fade in on open (150ms, after the slide starts). */
  html.bfc-peek .product-header_product-details .bfc,
  html.bfc-peek .product-header_product-details .margin-bottom:has(> .product_feature_outer_wrapper),
  html.bfc-peek .product-header_product-details .product-inner-footer-wrapper { transition: opacity .15s cubic-bezier(.4, 0, .2, 1) .1s; }
  html.bfc-closed .product-header_product-details .bfc,
  html.bfc-closed .product-header_product-details .margin-bottom:has(> .product_feature_outer_wrapper),
  html.bfc-closed .product-header_product-details .product-inner-footer-wrapper { opacity: 0; visibility: hidden; transition: none; }
  /* "Read the story" from the resting sheet (v43). The Portrait Details drawer is position: fixed but sits inside the footer wrapper, which the
     rest state hides just above with opacity 0, and opacity on an ancestor cannot be undone by a child: the drawer opened and nothing showed.
     While the script holds the drawer open from the rest state (html.bfc-story, set by the story link, released when the drawer closes), the
     wrapper shows and everything in it but the drawer's own group is hidden again, so the page behind the drawer is as it rests. */
  html.bfc-closed.bfc-story .product-header_product-details .product-inner-footer-wrapper { opacity: 1; visibility: visible; }
  html.bfc-closed.bfc-story .product-header_product-details .product-inner-footer-wrapper > :not(.button-group:has(> .portrait-modal_component)),
  html.bfc-closed.bfc-story .product-header_product-details .product-inner-footer-wrapper .button-group:has(> .portrait-modal_component) > :not(.portrait-modal_component) { opacity: 0; visibility: hidden; }
  /* The open column (Chris 2026-10-05): the perks stay under the title and price (seen once the column opens); Portrait
     Details and Commission Process sit 32px (2rem) under Add to cart and 32px apart, each with 4px of padding above
     and below. */
  html.bfc-peek .product-header_product-details .product-inner-footer-wrapper { margin-top: 32px; padding-bottom: 32px; display: flex; flex-direction: column; align-items: flex-start; gap: 32px; }
  html.bfc-peek .product-inner-footer-wrapper .text-style-link { padding-top: 4px; padding-bottom: 4px; }
  .bfc.is-phone { gap: 24px; }
  /* Phones fold Timeline & Files behind the fold button, as desktop does (2026-11-01; PhoneReserve). The button sits 32px
     under Series (the column's 24px gap plus 8px); the closed row cancels the 24px gap, and the options open 24px under it. */
  .bfc.is-phone .bfc_fold { margin-top: 8px; }
  .bfc.is-phone .bfc_acc { margin-top: -24px; }
  .bfc.is-phone .bfc_acc .bfc_options { padding-top: 24px; }
  /* The drop (PhSheetDrop): a House Color tapped in the open column puts it back down to the portrait, shorter than the
     peek. The name and price, then the color row: Choose options folds away, the perks leave, and everything in the mount
     but the color row waits out of sight. The script resizes --bfc-peek to end at the color row. */
  html.bfc-drop .bfc_choose { height: 0; margin-top: -20px; }
  html.bfc-drop .product-header_product-details .margin-bottom:has(> .product_feature_outer_wrapper) { display: none; }
  html.bfc-closed.bfc-drop .product-header_product-details .bfc { opacity: 1; visibility: visible; }
  html.bfc-closed.bfc-drop .product-header_product-details .bfc > :not(.is-house) { visibility: hidden; }
  /* The quote form's Request a quote row is pinned to the bottom of the screen while the form scrolls (Designer: sticky,
     bottom 0). In the side panel the panel's own padding gives it room; in the phone column it sat on the screen's
     edge and the Terms / Privacy Policy underlines fell off the bottom (Chris, 2026-10-05). */
  html.bfc-peek .bfc_view .team-quote_submit-wrap { padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
}
/* The gallery frames end where the peek starts, less the 9px strip with the site's bars (option B, as live). Upright
   only, so a phone turned sideways keeps today's 4:5 frames. */
@media (max-width: 991px) and (orientation: portrait) {
  html.bfc-pending .product-gallery_frame, html.bfc-peek .product-gallery_frame {
    aspect-ratio: auto; height: calc(100vh - var(--bfc-peek) - 9px); height: calc(100svh - var(--bfc-peek) - 9px);
  }
}

/* ---- prada.com motion (read from their stylesheet and recorded on their phone product page, 2026-10-05) ---------- */
/* Loading: skeleton boxes with a 2s white sweep (.skeleton__box). Their greys sit between the palette's Gray 200 and
   Gray 50, so the palette pair is used. */
@keyframes bfcShimmer { to { transform: translate(100%); } }
.bfc_sk { position: relative; overflow: hidden; max-width: 100%;
  background: linear-gradient(90deg, var(--_color---color-gray-200, #E1E2E5), var(--_color---color-gray-50, #F7F7F7) 94.79%); }
.bfc_sk::after { content: ""; position: absolute; inset: 0; transform: translate(-100%);
  background-image: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .2) 20%, rgba(255, 255, 255, .5) 60%, rgba(255, 255, 255, 0));
  animation: bfcShimmer 2s infinite; }
.bfc_skeleton { display: flex; flex-direction: column; gap: 32px; }
.bfc_sk-stack { display: flex; flex-direction: column; gap: 14px; padding-top: 6px; }
.bfc_sk-rows { display: flex; flex-direction: column; gap: 1px; }
/* Smootify's own wait on the title and price (a 1s colour pulse, rounded) becomes the same sweep. Its selector is
   Smootify's; this one is more specific and leaves the configurator's own nodes alone. */
.product-header_product-details smootify-product:not(.loaded) :is(h1, p, span):not(.bfc *) {
  animation: none; position: relative; overflow: hidden; border-radius: 0;
  background: linear-gradient(90deg, var(--_color---color-gray-200, #E1E2E5), var(--_color---color-gray-50, #F7F7F7) 94.79%);
}
.product-header_product-details smootify-product:not(.loaded) :is(h1, p, span):not(.bfc *)::after {
  content: ""; position: absolute; inset: 0; transform: translate(-100%);
  background-image: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .2) 20%, rgba(255, 255, 255, .5) 60%, rgba(255, 255, 255, 0));
  animation: bfcShimmer 2s infinite;
}
/* Reveal: content fades .5 to 1 over .6s (.transition-fade-in). A choice swapped in place fades in after .15s. */
@keyframes bfcFadeIn { from { opacity: .5; } to { opacity: 1; } }
.bfc-in { animation: bfcFadeIn .6s forwards; }
@keyframes bfcSwap { from { opacity: 0; } to { opacity: 1; } }
.bfc-swap { animation: bfcSwap .35s .15s both; }
/* Phone hint (shift-up): the panel and its button lift 42px and settle, 2.5s after .75s. */
@keyframes bfcShiftUp { 0% { translate: 0 0; } 34%, 66% { translate: 0 -42px; } 100% { translate: 0 0; } }
.product-header_product-details.is-hint { animation: bfcShiftUp 2.5s .75s; }
@media (prefers-reduced-motion: reduce) {
  .bfc_choose, .bfc_series-option, .bfc_house-cell, .bfc_view .bfc_card { transition: none; }
  .bfc_sk::after, .bfc-in, .bfc-swap, .product-header_product-details.is-hint,
  .product-header_product-details smootify-product:not(.loaded) :is(h1, p, span):not(.bfc *)::after { animation: none; }
}

/* ---- Portrait Details folds (canvas PD1; built in the Designer as .portrait-modal_fold) -------------------------- */
/* Same motion as the fold above. Code only for what the Designer can't set: the 0fr row, the fade and the turn. */
/* The panel's description reads in ink, not the site's grey paragraph colour (canvas PD1). Code because the global p
   rule is what greys it, and the API can't reach the Designer's rich-text paragraph styling; fine to move there later. */
.portrait-modal_content-wrapper .w-richtext p { color: var(--_color---color-primary-black, #1B1B1B); }
.portrait-modal_fold-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .6s cubic-bezier(.4,0,.2,1); }
.portrait-modal_fold.is-open .portrait-modal_fold-body { grid-template-rows: 1fr; }
.portrait-modal_fold-content { min-height: 0; overflow: hidden; opacity: 0; transition: opacity .4s cubic-bezier(.4,0,.2,1); }
.portrait-modal_fold.is-open .portrait-modal_fold-content { opacity: 1; transition-delay: .15s; transition-duration: .35s; }
.portrait-modal_fold-toggle svg { transition: transform .6s cubic-bezier(.4,0,.2,1); }
.portrait-modal_fold.is-open .portrait-modal_fold-toggle svg { transform: rotate(180deg); }
.portrait-modal_fold-toggle:focus-visible { outline: 1px solid var(--_color---color-primary-black, #1B1B1B); outline-offset: 2px; }
html.bfc-pointer .portrait-modal_fold-toggle:focus-visible { outline: none; }
/* The perks under the price open their fold in the panel (role button, set by the configurator): a keyboard ring like
   the folds'. Their hover line is the Designer's .product_feature_link. */
.product_feature_link:focus-visible { outline: 1px solid currentColor; outline-offset: 2px; }
html.bfc-pointer .product_feature_link:focus-visible { outline: none; }

@media (prefers-reduced-motion: reduce) {
  .portrait-modal_fold-body, .portrait-modal_fold-content, .portrait-modal_fold-toggle svg { transition: none; }
}

/* ---- Related editions (Task 9; canvas FamPlus, FamReserve, PhFamPlus, PhFamReserve) ---------------------------------------
   Built by the script inside .product-inner-footer-wrapper, after Portrait Details and Commission Process, so it hides with
   them (html.bfc-viewing, and the phone's closed sheet). The wrapper is a flex column with a 32px gap: 68px of margin makes
   100px under Commission Process on desktop; 36px makes 68px on phones and tablets. Two 5:4 tiles 2px apart (aspect-ratio, so
   they stay 5:4 at every width): 219 x 175 in the 440px column, 174 x 139 on a 390 phone, the row capped at 440px. The picture
   is a 4:3 crop anchored to the bottom at 96.5% of the tile (169px of 175, 134 of 139), so the ground shows above the head. The Reserve tile's ground is the House Color and Classic's is #F7F7F7. Names centered, no price. */
.bfc_family { align-self: stretch; box-sizing: border-box; width: 100%; max-width: 440px; margin: 68px 0 72px; }
.bfc_family .bfc_family-title { margin: 0; padding: 0; font-size: 12px; font-weight: 500; line-height: 18px; letter-spacing: .208px; text-transform: none; color: #1B1B1B; }
.bfc_family-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 2px; margin-top: 14px; }
.bfc_family-tile { display: flex; flex-direction: column; min-width: 0; color: #1B1B1B; text-decoration: none; }
.bfc_family-tile:focus-visible { outline: 1px solid #1B1B1B; outline-offset: 2px; }
.bfc_family-pic { position: relative; aspect-ratio: 5 / 4; overflow: hidden; background: #F7F7F7; }
.bfc_family-pic img { position: absolute; left: 0; bottom: 0; display: block; width: 100%; height: 96.5%; object-fit: cover; object-position: 50% 100%; }
.bfc_family .bfc_family-name { margin-top: 14px; text-align: center; font-size: 12px; font-weight: 500; line-height: 16px; letter-spacing: 0; text-transform: none; }
@media (max-width: 991px) { .bfc_family { margin: 36px 0 0; } }

/* ---- Reserve hero framing (v44, Chris's iPhone: "the image being too tight at the top"; v45: "the portrait doesn't look quite centered"; v46: desktop without the strip) ----
   The hero is a 4:5 picture, a flat color ground with the sitter and a white garment, shown with object-fit: cover anchored at the bottom in a
   frame that is shorter than 4:5 on a phone (the frame ends where the sheet begins). Cover scales to the width and cuts the top: plain Portrait Plus's
   picture has 20.6% of its height above the head, the Reserve picture 10.2%, so the same crop cut the Reserve hair and ran it up behind the logo.
   The ground is one flat color, so the frame carries it (--bfc-ground, set with each pick; Blue until then) and the picture is placed in it instead:
   the head sits where plain Portrait Plus's does and the top of the hair is never cut off. Only on a Reserve page ([data-bf-reserve] is in its markup
   and in no other page's).
   Phones and tablets upright (v47; container units on the frame: W = its width, F = its height; the picture is 4:5, 0.1016 of it above the hair and 0.909 to
   the lowest hair, the hair 0.108 to 0.865 of its width, the head midpoint 50.1% across it, and its left edge is the garment's white from 75.65% of its height down):
     T    = where the hair top sits = max(84px, min(0.2056 F, F - 0.994 W)): plain Portrait Plus's head where that is at least 84px (the 64px header and 20px of air:
            Chris, on the color-open state, had it 71px from the logo), never higher
     w    = the picture's width: the largest whose WHOLE hair fits under T with 12px clear above the frame's foot, (F - 12 - T) / 1.0093, at most 1.27 W (so the hair is
            never cut at the sides). It may be narrower than the frame (v47: v45 never let it be, and after a color tap cut the hair tips and the garment); the garment
            may still meet the sheet below the hair, but no hair tip is cut in any state at any size
     top  = T - 0.127 w (the hair's top at T); left = (W - w) / 2: always centered, so the head midpoint is within 0.5% of the frame's center
   When the picture is narrower than the frame (a gap g = (W - w) / 2 at each side) the left gap would show ground where the garment should be, so the frame's ::before
   carries the garment to the frame's left edge: white, behind the picture, border-top-left-radius: 100% 100% (a quarter ellipse). v48: it is an ellipse TWICE as wide as
   the gap (W - w, so its crest is hidden under the picture), and its top is solved so that it emerges at the picture's left edge exactly on the shoulder's edge there:
   the edge's midpoint (half way from the ground to white) is at 75.16% of the picture's height at x = 0 (pure white starts at 75.65%) and the edge slopes about 45 degrees
   (0.7516 at x = 0, 0.7484 at x = 4 of 992). An ellipse of width 2g (centered g under the picture) has dropped to sqrt(1 - 0.5^2) = 0.866 of its height b at the join, where
   it slopes (b / 2g) x 0.5 / 0.866: 0.99 at 402 x 684 color-open (g = 27px, b = 93px), close to the edge's 1. v47's was g wide with a flat crest at the edge: a kink where it
   met the 45 degree line. y0 = T + 0.8125 w (75.16% of the
   picture's height from its top); the ellipse's height is (F - y0) / 0.866. Its width is 0 when there is no gap. The right side stays ground. */
html:has([data-bf-reserve]) .product-gallery_frame:has(> .product-gallery_image.is-hero-phone) {
  background-color: var(--bfc-ground, #87b4eb);
  transition: background-color .4s cubic-bezier(.4, 0, .2, 1);
}
@media (prefers-reduced-motion: reduce) {
  html:has([data-bf-reserve]) .product-gallery_frame:has(> .product-gallery_image.is-hero-phone) { transition: none; }
}
/* Desktop (v49, Chris on the live page, 2 Nov 2026: "It also crops the bottom of the portrait and the user has to scroll to see it, this is not the product
   page behaviour set by the other portraits"). The whole picture stands in the middle of the gallery's gray frame, as the other styles' portraits do: never cropped,
   never below the fold. It is contained in a centered box 68.9% of the frame each way (Chris's reference: 496 x 620 in the 720 x 900 frame at 1440 x 900), so in a
   frame wider than 4:5 (the sticky media column on a wide screen) it is that share of the frame's height, and in a narrower one that share of its width. The frame
   keeps the gallery's #F7F7F7: the ground color above is for phones and tablets, and both hero pictures sit in this one frame, so it is set back here. v46 to v48's
   cover from the top, its 2:1 cap and the ultrawide shoulder are gone. A color pick's crossfade copy takes the picture's computed box (swapPicture), so it lines up. */
@media (min-width: 992px) {
  html:has([data-bf-reserve]) .product-gallery_frame:has(> .product-gallery_image.is-hero) { background-color: #f7f7f7; }
  html:has([data-bf-reserve]) .product-gallery_frame > .product-gallery_image.is-hero {
    inset: 15.55% auto auto 15.55%; width: 68.9%; height: 68.9%; object-fit: contain; object-position: 50% 50%;
  }
}
@media (max-width: 991px) and (orientation: portrait) {
  @supports (width: 1cqw) {
    /* --bfc-t and --bfc-w hold unresolved tokens (the cq units are resolved where they are used: the picture and the shoulder, both inside the container) */
    html:has([data-bf-reserve]) .product-gallery_frame:has(> .product-gallery_image.is-hero-phone) {
      container-type: size;
      /* plain Portrait Plus's frame is --bfc-plus taller (its sheet has no Reserve Edition label), and T is its head */
      --bfc-t: max(84px, min(calc((100cqh + var(--bfc-plus, 0px)) * 0.2056), calc(100cqh + var(--bfc-plus, 0px) - 99.4cqw)));
      --bfc-w: min(127cqw, calc((100cqh - 12px - var(--bfc-t)) / 1.0093));
    }
    html:has([data-bf-reserve]) .product-gallery_frame > .product-gallery_image.is-hero-phone {
      position: absolute; right: auto; bottom: auto; max-width: none; max-height: none;
      width: var(--bfc-w); height: calc(var(--bfc-w) * 1.25);
      left: calc((100cqw - var(--bfc-w)) / 2);
      top: calc(var(--bfc-t) - 0.127 * var(--bfc-w));
      object-fit: fill; object-position: 0 0;
    }
    html:has([data-bf-reserve]) .product-gallery_frame:has(> .product-gallery_image.is-hero-phone)::before {
      content: ""; position: absolute; left: 0; bottom: 0; pointer-events: none; background: #fff; border-top-left-radius: 100% 100%;
      width: max(0px, calc(100cqw - var(--bfc-w)));
      height: max(0px, calc((100cqh - var(--bfc-t) - 0.8125 * var(--bfc-w)) / 0.866));
    }
    /* A tablet's frame is much taller than its gap is wide (about 130px of shoulder under a 22px gap), so the ellipse is only 1.25 times as wide as the gap (u = 0.2, dropped
       to 0.98 of its height at the join: slope about 1 there; at twice it would be about 2). */
    @media (min-width: 768px) {
      html:has([data-bf-reserve]) .product-gallery_frame:has(> .product-gallery_image.is-hero-phone)::before {
        width: max(0px, calc((100cqw - var(--bfc-w)) * 0.625));
        height: max(0px, calc((100cqh - var(--bfc-t) - 0.8125 * var(--bfc-w)) / 0.9798));
      }
    }
    /* The script solves the ellipse from the frame (fitShoulder: k gaps wide, k = (D - g) / (D - 2g)), so it meets the edge at a slope of 1 in the shorter frames
       the Reserve label and Your Brand's tab row make. --bfc-sk is its width over W - w (k / 2), --bfc-sh its height over D (k / sqrt(2k - 1)); without them, v48's. */
    html:has([data-bf-reserve]) .product-gallery_frame.bfc-shoulder:has(> .product-gallery_image.is-hero-phone)::before {
      width: max(0px, calc((100cqw - var(--bfc-w)) * var(--bfc-sk, 1)));
      height: max(0px, calc((100cqh - var(--bfc-t) - 0.8125 * var(--bfc-w)) * var(--bfc-sh, 1.1547)));
    }
  }
}

/* ---- The story drawer's gallery (v44, Chris's iPhone: "scrolls horizontally here, it shouldn't") ----------------------------------------------
   The Designer's strip is a scroll-snap row (.portrait-modal_story-gallery: overflow auto hidden, each slide flex 0 0 100%). Nothing in the drawer may
   scroll sideways: the strip stops being a scroller, with or without the script (without it the four slides stack, picture and caption each). With the
   script (reserveStory(), class .bfy) the slides share one grid cell as the ReservePage board draws it: the pictures stacked (4:3, full-bleed, cross-fading
   over 700ms) with the pause button on the corner of the stack, the timing lines in the row under them, the captions stacked in the row under those
   (fading over 500ms; the row is as tall as the tallest caption, so nothing below it moves). The slides themselves become display: contents.
   Full-bleed is the width of the drawer's scroller (.portrait-modal_content-wrapper, overflow: scroll), whose side padding is 32px, 20px under 480px and
   48px on a tablet: the gallery's negative margins and the captions' and lines' side padding take that padding (--bfy-pl / --bfy-pr, set by the script;
   32px, or 20px under 480px, until it runs), and the scroller itself may not scroll sideways on a Reserve page. */
html:has([data-bf-reserve]) .portrait-modal_content-wrapper { overflow-x: hidden; }
.portrait-modal_story .portrait-modal_story-gallery { display: flex; flex-direction: column; overflow: hidden; scroll-snap-type: none; margin-left: calc(-1 * var(--bfy-pl, 32px)); margin-right: calc(-1 * var(--bfy-pr, 32px)); }
@media (max-width: 479px) { .portrait-modal_story .portrait-modal_story-gallery { --bfy-pl: 20px; --bfy-pr: 20px; } }
.portrait-modal_story .portrait-modal_story-gallery .portrait-modal_story-caption { padding-left: var(--bfy-pl, 32px); padding-right: var(--bfy-pr, 32px); }
.portrait-modal_story .portrait-modal_story-gallery .portrait-modal_story-slide { flex: none; scroll-snap-align: none; }
.portrait-modal_story .portrait-modal_story-gallery.bfy { display: grid; grid-template-columns: minmax(0, 1fr); position: relative; }
.bfy .portrait-modal_story-slide { display: contents; }
.bfy .portrait-modal_story-pic { grid-area: 1 / 1; opacity: 0; visibility: hidden; transition: opacity 700ms ease, visibility 0s linear 700ms; }
.bfy .portrait-modal_story-slide.is-current > .portrait-modal_story-pic { opacity: 1; visibility: visible; transition-delay: 0s; }
.bfy .portrait-modal_story-caption { grid-area: 3 / 1; padding-top: 4px; opacity: 0; visibility: hidden; transition: opacity 500ms ease, visibility 0s linear 500ms; }
.bfy .portrait-modal_story-slide.is-current > .portrait-modal_story-caption { opacity: 1; visibility: visible; transition-delay: 0s; }
.bfy_lines { grid-area: 2 / 1; display: flex; gap: 6px; padding: 0 var(--bfy-pr, 32px) 0 var(--bfy-pl, 32px); }
.bfy_line { flex: 1 1 0; min-width: 0; height: 44px; margin: 0; padding: 0; border: 0; border-radius: 0; background: transparent; display: flex; align-items: center; cursor: pointer; -webkit-appearance: none; appearance: none; -webkit-tap-highlight-color: transparent; }
.bfy_track { position: relative; display: block; width: 100%; height: 2px; background: #E5E5E5; overflow: hidden; }
.bfy_fill { position: absolute; left: 0; top: 0; display: block; width: 0; height: 2px; background: #1B1B1B; }
.bfy_line:focus-visible { outline: 1px solid #1B1B1B; outline-offset: -4px; }
.bfy_pause { grid-area: 1 / 1; justify-self: end; align-self: end; z-index: 1; width: 44px; height: 44px; margin: 0 4px 4px 0; padding: 0; border: 0; border-radius: 0; background: transparent; display: flex; align-items: center; justify-content: center; cursor: pointer; -webkit-appearance: none; appearance: none; -webkit-tap-highlight-color: transparent; }
.bfy_disc { width: 28px; height: 28px; border-radius: 50%; background: rgba(255, 255, 255, .88); display: flex; align-items: center; justify-content: center; transition: background 200ms ease; }
.bfy_pause:hover .bfy_disc { background: #FFFFFF; }
.bfy_pause:focus-visible { outline: none; }
.bfy_pause:focus-visible .bfy_disc { outline: 1px solid #1B1B1B; outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .bfy .portrait-modal_story-pic, .bfy .portrait-modal_story-caption, .bfy_fill, .bfy_disc { transition: none !important; }
}

/* ---- Reserve cards in the lists other than the shop grid (v44) ------------------------------------------------------------------------------
   "You might also like" (and the cart's Bestsellers) draw the Reserve Edition's card with the other styles' card: a matte frame with the picture inset
   in it and the gray of the picture box showing around it. The Reserve picture is a full-bleed color, so it fills the box edge to edge, as on the shop
   grid (shop-browse: [data-bf-swatches] ...). The script marks the card ([data-bf-reserve-card], configurator reserveCards()). */
[data-bf-reserve-card] .product-card-frame-composition { inset: 0; height: 100%; }
[data-bf-reserve-card] .art-layer { height: 100%; }
[data-bf-reserve-card] .product-grid-image { width: 100%; height: 100%; object-fit: cover; }

/* ---- The Reserve Edition label's card (v47, Chris: "the card is cut at the top when the sheet is scrolled up with the color selector showing") ----------
   The Designer puts the card above the label, ending at the label's top, with its arrow (a 10px square turned 45 degrees on the card's lower edge) under it.
   When the whole card does not fit between the label and the header, configurator.js opens it under the label instead ([data-bf-below]): its top at the
   label's foot, the dark box 10px lower (the arrow's tip 3px under the label's text, as it is 3px over it above), the arrow on the box's top edge. */
[data-bf-reserve-card][data-bf-below] { top: 100%; bottom: auto; padding: 10px 0 0; }
[data-bf-reserve-card][data-bf-below] .reserve-label_arrow { top: -5px; bottom: auto; }

/* ---- The Reserve card's title in a list (v47, Chris, on You might also like at phone width: "The line height seems awfully tight, should be normal for this title") ----
   The cards' titles are 12px type on a 12px line (a Reserve card wraps "Portrait Plus -" / "Reserve Edition" on a phone, two lines touching). The Reserve card's is 18px, the
   site's leading for 12px text (1.5, as the body text's 24px on 16px: labels, intros and house names all use 12px on 18px). The block is pulled up 3px (the 6px of extra
   leading, half of it above the first line) so the first line stays level with its neighbors' titles, and it gives back 6px below, so a one-line title keeps the price where
   the other cards have it (12px + 8px = 18px + 2px); a wrapped one adds the second line. */
[data-bf-reserve-card] .margin-custom4 { position: relative; top: -3px; margin-bottom: calc(.5rem - 6px); }
[data-bf-reserve-card] .margin-custom4, [data-bf-reserve-card] .product_title-wrapper, [data-bf-reserve-card] .product_title-wrapper > * { line-height: 18px; }
