Setting Up Your Shopify theme for bookings
As a Shopify store owner offering experiential products like tours or workshops, you may need to customize your product pages to suit booking-style purchases better. This guide will walk you through setting up your store for experiential bookings using Experiences by Shopify.
Create a Custom Product Template in the theme editor
Go to your Shopify admin panel and navigate to "Online Store" > "Themes".
Click "Customize" on your current theme.
In the theme editor, click on "Home Page" > "Product".
Create a new product template by clicking "Add new layout" and name "Experiences new" (or any name you prefer).
This new template will be based on your default product layout, allowing you to customize it for your experiential products.
Add the Experiences app block to the new Product Page template
1. Ensure your new Experiences-based template is active in the theme editor.
2. Add the Experiences booking widget:
- Click "Add block"
- Go to the "Apps" section
- Select the "Book now button" (Experiences booking widget)
3. Arrange the booking widget on your page as desired. You may want to place it above the product description for visibility.
4. Customize the appearance:
- Adjust the button color to match your brand (e.g., #FF0000 for red, for example)
- Choose whether to show multiple time slots or just the next available slot
5. Hide unnecessary elements for bookable products:
- Price (if it's displayed in the booking widget)
- Variant picker
- Quantity selector
- Buy button
Applying the Template to Experiential Products
1. Go to the Shopify product page for one of your experiential products.
2. Scroll down to "Theme template" in the product settings.
3. Select your newly created template from the dropdown menu.
4. Save the changes.
Customizing the Booking Experience
The Experiences booking widget offers several customization options:
- Choose to display the next available time slot, the next three slots, or all available slots
- Customize the button text (e.g., "Book Now" or "See Other Options")
- When a customer clicks on a specific date, they'll be taken directly to that booking slot
Remember, using the theme editor, you can always adjust the placement of the booking widget and other elements on your product page.
Following these steps will streamline your customers' booking experience while maintaining the look and feel of your Shopify store. If you need further assistance or want to explore more advanced customizations, consider contacting Shopify's support team or contact us to learn about agencies specializing in bookable retail experiences.
App block styling CSS reference
If you want to inject custom CSS to style the app block, please use the CSS styles below. When you select the Experiences Book Now app block in the Shopify theme editor, you can place your CSS code in the box under "Advanced Settings -Custom Style Overrides" in the customization panel.
/***********************************************************
* Reset
***********************************************************/
.expapp {
line-height: 1;
}
.expapp *,
.expapp *::before,
.expapp *::after {
box-sizing: border-box;
--webkit-box-sizing: border-box;
--moz-box-sizing: border-box;
}
.expapp img {
display: block;
max-width: 100%;
border: 0;
}
.expapp button {
margin: 0;
padding: 0;
border: 0;
background: transparent;
font-size: 100%;
vertical-align: baseline;
line-height: inherit;
user-select: none;
cursor: pointer;
}
@media (prefers-reduced-motion: reduce) {
.expapp *,
.expapp *::before,
.expapp *::after {
transition: none !important;
}
}
/***********************************************************
* Global / Common Elements
***********************************************************/
.expapp {
--expapp-primary-color: #000;
--expapp-on-primary-color: #fff;
--expapp-error-color: #d04f51;
--expapp-on-error-color: #fff;
--expapp-border-color: #ccc;
--expapp-border-radius: 0.25em;
}
/*
* Common style applied to all error messages.
*/
.expapp-error {
border: 1px solid var(--expapp-error-color);
border-radius: 0;
padding: 1em;
color: var(--expapp-error-color);
background: transparent;
}
/**
* Style applied to all standard button types. This does not
* include calendar buttons or increment/decrement buttons
* (like when choosing the number of product variants to purchase).
*/
button.expapp-button {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
height: 2.5em;
padding: 0 1.5em;
font-family: inherit;
font-size: 1em;
font-weight: bold;
line-height: 1;
background: var(--expapp-primary-color);
color: var(--expapp-on-primary-color);
border: 0;
border-radius: var(--expapp-border-radius);
cursor: pointer;
}
/**
* Style applied to all "back" buttons in the workflow.
*/
button.expapp-button-back,
button.expapp-button-dismiss {
color: inherit;
background: transparent;
border: solid 1px var(--expapp-border-color);
}
/**
* Style applied to all "continue" buttons in the workflow.
*/
button.expapp-button-continue {
color: var(--expapp-on-primary-color);
background: var(--expapp-primary-color);
}
/**
* Style applied to all "disabled" buttons in the workflow.
*/
button.expapp-button[disabled] {
opacity: 0.75;
cursor: not-allowed;
}
/**
* Applies to all "Back" + "Continue" button pairs seen throughout
* the booking workflow.
*/
.expapp-buttons {
margin-top: 3em;
display: grid;
grid-template-columns: 1fr 2fr;
align-items: center;
gap: 1em;
}
/***********************************************************
* Book Now Area
***********************************************************/
/**
* Controls the styles for the main "Book Now" or "View More"
* button that is displayed if the experience has more timeslots
* to show than the "bookNowArea.previewFetchCount" Javascript
* option is set to.
*/
button.expapp-booknow-button {}
/**
* Encompasses the area that contains the location, price, and duration
* of the experience. This area is displayed immediately above the
* timeslot previews and the "Book Now" button.
*/
.expapp-booknow-info {
display: flex;
flex-direction: column;
gap: 1em;
/* padding: 1em; */
}
/**
* Defines the style of the location, price, and duration information.
* You can choose to split these up if you want to style them each
* differently.
*/
.expapp-booknow-info-location,
.expapp-booknow-info-price,
.expapp-booknow-info-duration {
font: inherit;
font-size: 1em;
color: inherit;
margin: 0;
}
.expapp-booknow-info-location:before,
.expapp-booknow-info-price:before,
.expapp-booknow-info-duration:before {
display: block;
margin-bottom: 0.5em;
font-weight: bold;
font-size: 0.875em;
color: inherit;
}
/**
* Set the desired label text for the location information header.
*/
.expapp-booknow-info-location:before {
content: "Location";
}
/**
* Set the desired label text for the price information header.
*/
.expapp-booknow-info-price:before {
content: "Price";
}
/**
* Set the desired label text for the duration information header.
*/
.expapp-booknow-info-duration:before {
content: "Duration";
}
/**
* Encompasses the area that contains the timeslot previews. This area
* will only show up if the experience has timeslots available AND the
* "bookNowArea.previewFetchCount" Javascript option is set to a value
* greater than 0.
*/
.expapp-timeslot-previews {
display: grid;
grid-template-columns: 1fr;
gap: 0;
border: 1px solid var(--expapp-border-color);
border-radius: var(--expapp-border-radius);
}
/**
* Styles an individual timeslot preview.
*/
.expapp-timeslot-previews .expapp-timeslot {
margin: 0;
border: 0;
border-bottom: 1px solid var(--expapp-border-color);
border-radius: 0;
}
.expapp-timeslot-previews .expapp-timeslot:last-child {
border-bottom: 0;
}
/***********************************************************
* Loader (Spinner)
***********************************************************/
/**
* Here we create a simple CSS loading indicator that helps inform
* the user that we're waiting for something to happen.
*/
.expapp-loader {
position: relative;
width: 3em;
height: 3em;
}
.expapp-loader:empty {
display: block;
}
.expapp-loader::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0.25em solid currentColor;
border-color: currentColor currentColor transparent transparent;
border-radius: 50%;
animation: expapp-loader-spin 1s linear infinite;
}
@keyframes expapp-loader-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/**
* Handles the loader when used within the final submit button on the
* order confirmation view.
*/
.expapp-button>.expapp-loader {
font-size: 0.5em;
}
/***********************************************************
* Modal
***********************************************************/
/**
* The modal container that fixes itself to fill the available
* viewport space. This is the outermost container that contains
* the modal box.
*/
.expapp-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
min-width: 100vw;
max-width: 100vw;
min-height: 100vh;
opacity: 0;
pointer-events: none;
overflow-x: hidden;
overflow-y: auto;
--webkit-overflow-scrolling: touch;
padding: 0;
padding-bottom: env(safe-area-inset-bottom);
background: rgba(0, 0, 0, 0.1);
transition: opacity 0.3s ease-in-out;
border: 0;
z-index: 3000000000;
}
/**
* This rule is applied to the modal container when it is open.
*/
.expapp-modal[open] {
opacity: 1;
pointer-events: all;
}
/**
* The modal box contains the actual content of the modal.
*/
.expapp-modal-box {
position: relative;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
min-height: 100%;
background: #fff;
padding: 3em;
border-radius: 0;
transition: transform 0.3s ease-in-out;
}
/**
* Here we specify the close button that will be displayed in the
* top left corner of the modal box (by default). The button also
* uses pure-CSS to create an "X" icon via the following pseudo
* elements: ::before and ::after.
*/
.expapp-modal-close {
position: fixed;
margin: 0;
padding: 0;
top: 1em;
left: 1em;
width: 1.5em;
height: 1.5em;
cursor: pointer;
}
.expapp-modal-close::before,
.expapp-modal-close::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 2px;
height: 100%;
background: currentColor;
}
.expapp-modal-close::before {
transform: translate(-50%, -50%) rotate(45deg);
}
.expapp-modal-close::after {
transform: translate(-50%, -50%) rotate(-45deg);
}
/**
* The inner contents of the modal use a sidebar/content layout
* that stacks on smaller devices.
*/
.expapp-modal-layout {
position: relative;
display: flex;
flex-direction: column;
justify-content: flex-start;
gap: 2em;
width: 90%;
max-width: 400px;
}
/**
* Styles the image that appears in the "sidebar" of the modal.
*/
img.expapp-modal-sidebar-image {
margin: 0 0 1em;
width: 100%;
height: auto;
}
/**
* Styles the name of the experience that appears in the "sidebar".
*/
h2.expapp-modal-sidebar-name {
margin: 0 0 1em;
font-size: 1.5em;
font-weight: bold;
}
/**
* Styles the date reminder that appears in the "sidebar".
*/
.expapp-modal-sidebar-date {
margin: 0 0 1em;
font-weight: bold;
}
@media (min-width: 800px) {
.expapp-modal-layout {
display: grid;
grid-template-columns: 2fr 3fr;
gap: 2em;
max-width: 960px;
}
.expapp-modal-sidebar {
position: sticky;
top: 3em;
max-height: calc(100vh - 6em);
overflow-x: hidden;
overflow-y: auto;
--webkit-overflow-scrolling: touch;
}
.expapp-modal-content {}
}
/***********************************************************
* Success Modal (Free/Reservation Experiences)
***********************************************************/
.expapp-modal.expapp-success-modal {
transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;
transform: translateY(3em);
background: #fff;
}
.expapp-modal.expapp-success-modal[open] {
transform: translateY(0);
}
.expapp-modal.expapp-success-modal .expapp-modal-box {
justify-content: center;
}
.expapp-modal.expapp-success-modal .expapp-modal-close {
display: none;
}
.expapp-success-modal-message {
margin-bottom: 2em;
font-size: 1.125em;
text-align: center;
width: 90%;
max-width: 700px;
}
.expapp-success-modal-message>h2 {
margin-bottom: 1em;
}
/***********************************************************
* Error Modal (Alert)
***********************************************************/
/**
* Error modals share the same classes as regular modals, but
* have the "expapp-error-modal" class added to them. This allows
* us to style them differently.
*/
.expapp-modal.expapp-error-modal {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.expapp-modal.expapp-error-modal .expapp-modal-box {
background: #fff;
padding: 3em;
border-radius: 10px;
width: 90%;
max-width: 600px;
min-height: 0;
transition: transform 0.3s ease-in-out;
transform: translateY(3em);
}
.expapp-modal.expapp-error-modal[open] .expapp-modal-box {
transform: translateY(0);
}
.expapp-modal.expapp-error-modal .expapp-modal-close {
display: none;
}
.expapp-error-modal-message {
margin-bottom: 2em;
font-size: 1.125em;
text-align: center;
}
/***********************************************************
* Calendar
***********************************************************/
/**
* The calendar appears in the sidebar when the "Timeslot Browser"
* is open. The calendar operates like pagination, allowing the user
* to navigate between months and select a specific day. Interacting
* with the calendar will update the timeslots and scroll position
* to reflect the selected month and/or day.
*/
.expapp-cal {
position: relative;
width: 100%;
max-width: 100%;
}
.expapp-cal-header {
display: grid;
grid-template-columns: 1fr auto 1.5fr auto;
gap: 1em;
margin: 0 0 1em;
}
.expapp-cal-goto-today {
padding: 0.5em 1em;
height: 2em;
cursor: pointer;
}
.expapp-cal-controls-left,
.expapp-cal-controls-right,
.expapp-cal-month-name {
display: flex;
justify-content: center;
align-items: center;
gap: 1em;
}
.expapp-cal-controls-right {
justify-content: flex-start;
}
.expapp-cal-controls-right {
justify-content: flex-end;
}
.expapp-cal-arrow-left,
.expapp-cal-arrow-right {
position: relative;
width: 2em;
height: 2em;
border: 0;
}
.expapp-cal-arrow-left:before,
.expapp-cal-arrow-right:before {
position: absolute;
top: 50%;
left: 50%;
content: "";
display: block;
width: 50%;
height: 50%;
border: 0;
border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor;
}
.expapp-cal-arrow-left:before {
transform: translate(-25%, -50%) rotate(135deg);
}
.expapp-cal-arrow-right:before {
transform: translate(-75%, -50%) rotate(-45deg);
}
.expapp-cal-month-name {
text-align: center;
}
.expapp-cal-weekdays,
.expapp-cal-week {
display: grid;
grid-template-columns: repeat(7, 1fr);
}
.expapp-cal-weekday {
display: flex;
justify-content: center;
align-items: center;
font-weight: normal;
font-size: 0.875em;
color: inherit;
}
.expapp-cal-day {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: transparent;
aspect-ratio: 1 / 1;
cursor: pointer;
border-radius: 50%;
user-select: none;
}
.expapp-cal-day-number {
color: inherit;
}
.expapp-cal-selected {
background: #000;
color: #fff;
}
.expapp-cal:not(.expapp-cal-no-selection) .expapp-cal-day.expapp-cal-selected:before {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
content: "";
background: transparent;
color: inherit;
opacity: 1;
}
.expapp-cal-day.expapp-cal-empty {
background: transparent;
color: inherit;
pointer-events: none;
}
.expapp-cal-day.expapp-disabled {
opacity: 0.5;
pointer-events: none;
}
/***********************************************************
* Timeslot Browser
***********************************************************/
.expapp-timeslots {
position: relative;
display: flex;
flex-direction: column;
}
.expapp-timeslots-date-group {
position: relative;
display: flex;
flex-direction: column;
gap: 1em;
}
h3.expapp-timeslots-date-heading {
position: sticky;
top: 0;
padding: 1.5em 0 1em;
font-size: 1.25em;
background: #fff;
z-index: 20;
}
.expapp-timeslots-loader {
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: row;
justify-content: center;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.75);
z-index: 100;
transition: opacity 0.3s ease-in-out;
opacity: 0;
pointer-events: none;
}
.expapp-timeslots-loading .expapp-timeslots-loader {
opacity: 1;
pointer-events: all;
}
.expapp-timeslots-loader .expapp-loader {
position: sticky;
top: 40vh;
}
/***********************************************************
* Timeslot
***********************************************************/
/**
* Styles an individual timeslot. Timeslots appear in the modal
* (via the "Timeslot Browser") and in the "Book Now" area as a
* "Timeslot Preview".
*/
.expapp-timeslot {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
align-items: center;
margin-bottom: 1.75em;
padding: 1.5em;
gap: 1em;
border-radius: 10px;
border: solid 1px var(--expapp-border-color);
}
.expapp-timeslot-info,
.expapp-timeslot-buttons {
display: flex;
width: 100%;
flex-direction: column;
justify-content: center;
}
.expapp-timeslot-info {
gap: 0.5em;
}
.expapp-timeslot-time {
font-size: 1.1em;
}
.expapp-timeslot-unit {
display: flex;
gap: 0.5em;
}
.expapp-timeslot-unit-price {
font-weight: bold;
}
.expapp-timeslot-unit-type {
opacity: 0.75;
}
.expapp-timeslot-buttons {
min-width: fit-content;
gap: 0.5em;
align-items: center;
}
.expapp-timeslot-button {
padding: 0.75em 1em;
font-size: 1em;
}
.expapp-timeslot-button+.expapp-timeslot-button {
padding: 0.5em 1em;
width: 100%;
font-size: 0.875em;
cursor: pointer;
font-weight: bold;
background: transparent;
color: inherit;
}
/***********************************************************
* Variant Selection
***********************************************************/
/**
* Styles the heading that appears above the variant selection form.
* By default, this says "Quantity", but this can be changed via the
* "variantSelection.heading" option in the Javascript configuration.
*/
.expapp-variants-heading {
font-size: 1.5em;
font-weight: bold;
}
/**
* Contains the variant selection form fields.
*/
.expapp-variants {
display: flex;
flex-direction: column;
gap: 2em;
margin-bottom: 3em;
}
/**
* Styles the variant selection field rows and the total price row. These
* share the same row layout, which is why they are styled together.
*/
.expapp-variant,
.expapp-variants-total {
display: grid;
grid-template-columns: 3fr 1fr 3fr;
align-items: center;
gap: 1em;
}
/**
* The variant name is the first column in the variant selection form. It is
* set to be truncated with an ellipsis if the text is too long to fit.
*/
.expapp-variant-name {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
/**
* When on mobile, we stack the variant information vertically.
*/
@media screen and (max-width: 640px) {
.expapp-variant {
display: flex;
}
.expapp-variant-name {
white-space: normal;
overflow: visible;
width: 100%;
}
.expapp-variant-price {
text-align: left;
flex: 1;
}
}
/**
* The variant price is the second column in the variant selection form.
*/
.expapp-variant-price {
text-align: center;
}
/**
* This rule is applied to the container for the "spinner box" that allows
* the user to either explicitly set the number of variants they want to
* purchase or to increment/decrement the number of variants.
*/
.expapp-variant-count {
display: flex;
flex-direction: row;
align-items: center;
gap: 1em;
}
/**
* Provides the common styles for the decrement and increment buttons in the
* variant count "spinner box".
*/
button.expapp-variant-count-decrement,
button.expapp-variant-count-increment {
width: 2.5em;
height: 2.5em;
padding: 0;
border: none;
background: var(--expapp-primary-color);
color: var(--expapp-on-primary-color);
text-align: center;
border-radius: 50%;
line-height: 0;
}
/**
* Styles the decrement button in the variant count "spinner box".
*/
button.expapp-variant-count-decrement:after {
content: "-";
font-size: 1.5em;
}
/**
* Styles the increment button in the variant count "spinner box".
*/
button.expapp-variant-count-increment:after {
content: "+";
font-size: 1.5em;
}
/**
* Styles the input field in the variant count "spinner box".
*/
input.expapp-variant-count-input {
width: 3em;
min-width: 0;
max-width: none;
flex: 1;
padding: 0;
text-align: center;
font-size: 1em;
height: 2.5em;
border: 1px solid var(--expapp-border-color);
border-radius: 0.25em;
}
.expapp-variant-count-input:focus {
outline: none;
}
/**
* Styles the total price row in the variant selection form.
*/
.expapp-variants-total {
margin-bottom: 3em;
font-weight: bold;
}
/***********************************************************
* Group Booking Indicator / Toggle
***********************************************************/
.expapp-order-group-toggle {
margin-bottom: 2em;
}
.expapp-order-group-toggle.expapp-disabled {
opacity: 0.5;
pointer-events: none;
}
.expapp-order-group-toggle>input {
display: none;
}
.expapp-order-group-toggle-label {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
gap: 1em;
cursor: pointer;
padding-left: 2em;
user-select: none;
width: fit-content;
}
.expapp-order-group-toggle-label:before,
.expapp-order-group-toggle-label:after {
position: absolute;
content: "";
display: block;
}
.expapp-order-group-toggle-label:before {
top: 50%;
left: 0;
transform: translate(0, -50%);
width: 1.5em;
height: 1.5em;
background: #fff;
border: 1px solid var(--expapp-border-color);
border-radius: var(--expapp-border-radius);
}
.expapp-order-group-toggle-label:after {
left: 0.25em;
width: 0.75em;
height: 1em;
border-color: currentColor;
border-style: solid;
border-width: 0 0.25em 0.25em 0;
transform: translate(0.125em, -0.125em) rotate(35deg) scale(0.75);
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
opacity: 0;
border-radius: 0 0 1px 0;
}
.expapp-order-group-toggle>input:checked+.expapp-order-group-toggle-label:after {
transform: translate(0.125em, -0.125em) rotate(35deg) scale(1);
opacity: 1;
}
/***********************************************************
* Forms (Attende/Order Details, Custom Fields)
***********************************************************/
/**
* Applied to the outermost form container for both the order
* details and attendee details forms.
*/
form.expapp-order-details,
form.expapp-attendee-details {
display: flex;
flex-direction: column;
gap: 2em;
}
/**
* Styles the header for the custom form view.
*/
.expapp-order-details-heading,
.expapp-attendee-details-heading {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
/**
* Styles the container for each form field in custom forms.
*/
.expapp-form-field {
display: flex;
flex-direction: column;
gap: 0.25em;
}
/**
* Styles the label for each form field.
*/
.expapp-form-field>label {
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
align-items: center;
gap: 1em;
font-weight: bold;
font-size: 0.875em;
}
.expapp-form-field:not(.expapp-required)>label:after {
content: "(Optional)";
opacity: 0.6;
font-size: 0.875em;
font-weight: normal;
}
/**
* Applies styles for the "Text", "Email", and "Phone" field types
* in custom forms.
*/
.expapp-form-field>input {
width: 100%;
padding: 0.5em;
font-size: 1em;
border: 1px solid var(--expapp-border-color);
border-radius: 0.25em;
}
/**
* Applies styles for the "Select" field type in custom forms.
*/
.expapp-form-field>select {
width: 100%;
padding: 0.5em;
font-size: 1em;
border: 1px solid var(--expapp-border-color);
border-radius: 0.25em;
}
/**
* Styles the counter that appears in the custom form header when
* a form is shown per attendee.
*/
.expapp-attendee-details-count {
font-size: 0.75em;
font-weight: normal;
opacity: 0.6;
}
/***********************************************************
* Order Overview (Confirmation & Sidebar)
***********************************************************/
.expapp-modal-sidebar .expapp-order-overview {
font-size: 0.875em;
}
.expapp-order-overview-entry,
.expapp-order-overview-entry-addon,
.expapp-order-overview-total {
position: relative;
display: flex;
justify-content: space-between;
margin-bottom: 0.5em;
}
.expapp-order-overview-entry-addon {
padding-left: 1.5em;
color: rgba(0, 0, 0, 0.75);
}
.expapp-order-overview-entry-label,
.expapp-order-overview-entry-addon-label {
max-width: 70%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.expapp-order-overview-entry-addon:before {
content: "+";
position: absolute;
top: 0.5em;
left: 0;
font-size: 1.5em;
line-height: 0;
opacity: 0.75;
}
.expapp-order-overview-total {
margin-top: 1em;
border-top: 1px solid var(--expapp-border-color);
padding-top: 1em;
font-weight: bold;
}
/* .expapp-order-overview-entry-highlighted {
font-weight: bold;
} */
/***********************************************************
* Order Confirmation
***********************************************************/
/**
* Applied to the outermost form container for both the order
* details and attendee details forms.
*/
form.expapp-confirmation,
.expapp-customer-info-form {
display: flex;
flex-direction: column;
gap: 2em;
}
.expapp-customer-info-form {
margin-top: 2em;
}
/***********************************************************
* Product Addons
***********************************************************/
.expapp-product-addons {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1em;
}
.expapp-product-addon {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
gap: 0.5em;
cursor: pointer;
padding: 1em;
border: solid 1px var(--expapp-border-color);
border-radius: 10px;
overflow: hidden;
user-select: none;
}
.expapp-product-addon-thumbnail {
width: 100%;
aspect-ratio: 3/2;
overflow: hidden;
}
.expapp-product-addon-thumbnail>img {
width: 100%;
height: auto;
object-fit: cover;
transition: transform 0.2s ease;
}
.expapp-product-addon-selected {
border: solid 2px var(--expapp-primary-color);
}
.expapp-product-addon:hover .expapp-product-addon-thumbnail>img,
.expapp-product-addon-selected .expapp-product-addon-thumbnail>img {
transform: scale(1.1);
}