/*reset*/
*,*::before,*::after{box-sizing:border-box}*{margin:0}@media (prefers-reduced-motion:no-preference){html{interpolate-size:allow-keywords}}body{line-height:1.5;-webkit-font-smoothing:antialiased}img,picture,video,canvas,svg{display:block;max-width:100%;height:auto;}input,button,textarea,select{font:inherit}p,h1,h2,h3,h4,h5,h6{overflow-wrap:break-word}p{text-wrap:pretty}h1,h2,h3,h4,h5,h6{text-wrap:balance}#root,#__next{isolation:isolate}

input[type="checkbox"] {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

:root {
/*brand colors*/
	--black:#1A1F24;
	--dark:#252C34;
	--light:#B69F75;
	--accent:#8E764A;
	--white:#F7F2E8;
	--scrim:rgba(37,44,52,.8);
	--error:#B54323; /* errors only: warm rust, noticeable without the glare of bright red */
/*structural sizing*/	
	--size-m: 1rem;
	--size-s: .75rem;
/*utility*/	
	--border-radius:0.278rem;

	--icon-lightbulb: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWxpZ2h0YnVsYi1pY29uIGx1Y2lkZS1saWdodGJ1bGIiPjxwYXRoIGQ9Ik0xNSAxNGMuMi0xIC43LTEuNyAxLjUtMi41IDEtLjkgMS41LTIuMiAxLjUtMy41QTYgNiAwIDAgMCA2IDhjMCAxIC4yIDIuMiAxLjUgMy41LjcuNyAxLjMgMS41IDEuNSAyLjUiLz48cGF0aCBkPSJNOSAxOGg2Ii8+PHBhdGggZD0iTTEwIDIyaDQiLz48L3N2Zz4=");
	/* Lucide's triangle-alert, drawn by the stylesheet on every error message so
	   server and script errors look the same. */
	--icon-alert: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E");
}

html{
	font-size:18px; /* base font size */
	color: var(--white);
}

body, input{
	font-size: 1rem; /* 18px */
	line-height: 1.333rem; /* 24px */
	font-family: "Crimson Pro", serif;
	font-optical-sizing: auto;
	font-weight: 400;
	font-style: normal;	
}

body{
	background-color: var(--dark);
	max-width: 30rem;
	margin: 0 auto;
}

/*typography*/


/* .h1 and .h2 mirror the h1 and h2 styling, so a tag can be chosen for its
   meaning and still take either look: an h2 with class="h1" for a section
   heading that keeps the gold rule, or an h3 with class="h2". Each class is
   added beside its tag in the rules below, so the two always match.
   Approved 3 October 2026. */
h1, .h1{
	font-size: 1.333rem; /* 24px */
	line-height: 1.778rem; /* 32 px*/
	border-bottom: 2px solid var(--accent);
    padding-bottom: .4rem;
    margin-bottom: 1rem;
    position: relative;
}

h1:after, .h1:after{
	content: '';
	display: block;
	width: 0.667rem;
	height: 0.667rem;
	border: 2px solid var(--accent);
	background-color: var(--dark);
	position: absolute;
	right: 0;
	bottom: -0.333rem;
	border-radius: 50%;
}

h2, .h2{
	font-size: 1.167rem; /* 21px */
	line-height: 1.667rem; /* 30 px*/
}

.text-title, h1, h2, .h1, .h2{
	font-family: "Playfair Display", serif;
	font-optical-sizing: auto;
	font-weight: 400;
	font-style: normal;	
}

.text-title{
	font-size: 2rem; /* 36px */
	line-height: 2.667rem; /* 48px */
}

.text-secondary, small{
	font-size: 0.833rem; /* 15px */
	line-height: 1.167rem; /* 21px */
}

h1, h2, .h1, .h2, p, ol, li, dl{
	margin: 1rem 0;
}

h1:first-child, .h1:first-child{
	margin-top: 0;
}

dt{
	font-weight: 800;
	margin-top: 1rem;
}

/*links*/

a, .icon-light{
	text-decoration: underline;
	color: var(--light);
	transition: color .2s ease;
}

a:hover, a:active, #nav-menu .icon-light:hover, a:hover *{
	color: var(--white);
}

/*FORMS*/

label{
	font-weight: 800;
	display: block;
	color: var(--light);
	margin: 0.333rem 0;
}

input,
select,
textarea{
	background-color: var(--white);
	border-radius: var(--border-radius);
	border:1px solid var(--accent);
	padding: .5rem .833rem;
	display: block;
	color: var(--black);
}

input[type="text"],
input[type="email"],
input[type="password"],
select,
textarea{
	width: 100%;
}

input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
select:focus,
textarea:focus{
	outline: 3px solid var(--light);
}

input[type="checkbox"],input[type="radio"]{
	background-color: var(--white);
	border:1px solid var(--accent);
	width: 1.333rem;
	height: 1.333rem;
	padding: 0;
	position: relative;
	transition: background-color .2s ease;
}

input[type="checkbox"]:checked,input[type="radio"]:checked{
	background-color: var(--accent);
}

input[type="checkbox"]:checked::after{
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 1rem;
	height: 1rem;
    background-color: var(--white);
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20,6 9,17 4,12'%3E%3C/polyline%3E%3C/svg%3E") no-repeat center;
    mask-size: contain;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20,6 9,17 4,12'%3E%3C/polyline%3E%3C/svg%3E") no-repeat center;
    -webkit-mask-size: contain;
}

input[type="checkbox"] + label{
	margin: 0;
}

textarea{
	height: 9rem;
}

fieldset{
	border: 0;
	margin:1rem 0;
	padding: 0;
}

fieldset legend{
	font-weight: 800;
}

.btn{
	font-weight: 800;
	text-transform: uppercase;
	text-align: center;
	background-color: var(--accent);
	background: linear-gradient(to right, #B69F75, #DFCDAD, #B69F75);
	border:1px solid var(--accent);
	color: var(--black);
	border-radius: var(--border-radius);
	position: relative;
	padding: .5rem .833rem;
	display: block;
	width:100%;
	font-size: 1rem; /* 18px */
	line-height: 1.333rem; /* 24px */
	transition: background-color .2s ease, transform .2s ease;
	box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.5);
	margin:1rem 0;
	text-decoration: none;
}

.btn:before, .btn:after{
	content: '';
	display: block;
	width: .833rem;
	height: 1rem;
	position: absolute;
	top: calc(50% - .5rem);
	left: .833rem;
	background-color: var(--accent);
	mask: url("../img/btn-decoration.svg") no-repeat center;
    mask-size: contain;
    -webkit-mask: url("../img/btn-decoration.svg") no-repeat center;
    -webkit-mask-size: contain;
}

.btn:after{
	left: auto;
	right: .833rem;
}

.btn:hover, .btn:active{
	background: linear-gradient(to right, #B69F75, var(--white), #B69F75);
	box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.5);
	transform: translateY(2px);
	color: var(--black);
}

.no-btn{
	border: 0;
    background: transparent;
    padding: 0;
    margin: 0;
    cursor: pointer;
}

.btn-tab{
	font-weight: 800;
	text-transform: uppercase;
	text-align: center;		
	color: var(--light);
	padding: .5rem .833rem;
	font-size: .78rem; /* 14px */
	line-height: 1.333rem; /* 24px */
	text-decoration: none;
	background: none;
    border: .056rem solid var(--light);
    margin-bottom: -1px;
}

.btn-tab.active{
	border-bottom:1px solid var(--dark);
	color: var(--white);
}

.tab-nav{
	border-bottom:1px solid var(--light);
}


/*icons*/

.icon{
	display: block;
	min-width: 1.333rem;
	min-height: 1.333rem;
}

.icon-l{
	min-width: 3rem;
	min-height: 3rem;
}

.icon-light{
	color: var(--light);
}


/*alerts*/
.alert-overlay{
	position: absolute;
	top:0;
	right: 0;
	bottom: 0;
	left:0;
	background: var(--scrim);
	z-index: 1000;
}

.alert-box{
	margin: 2rem;
	background-color: var(--white);
	color: var(--black);
	padding: 1.111rem;
	border-radius: var(--border-radius);
	border:1px solid var(--accent);
}

.alert-icon .icon{
	margin:0 auto;
	min-width: 2rem;
	min-height: 2rem;
}

/*///////////*/
.alert-overlay {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(0, 0, 0, 0.5);
}

.alert-box {
    position: relative;
    max-height: 90vh;
    overflow-y: auto;
}


/*tips*/

.tip{
	display: flex;
	align-items: flex-start;
	gap:.667rem;
	margin: 1rem 0;
}

/*layout*/

.container{
	padding: 1.111rem 1.111rem 0;
	transition: opacity .2s ease;
}

.checkbox-label{
	display: flex;
	gap:.5rem;
	margin: .5rem 0;
}

.nav-links{
	display: flex;
    justify-content: space-between;
    margin:1rem 0;
}

.form-group{
	margin:1rem 0;
}

.ingredients-grid{
	display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
}

.ingredients-grid .checkbox-label,
.tool-list .checkbox-label{
	margin:1rem 0;
}

.fixed-bottom{
	position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    background: var(--black);
    padding-left:1rem;
    padding-right: 1rem;
}


/*header nav*/

.nav-header{
	background: var(--black);
	position: relative;
}

.nav-header-links{
    display: flex;
    justify-content: space-between;
    align-items: center;
    list-style-type: none;
    margin: 0;
    padding:0;
    z-index: 600;
    position: relative;
    background: var(--black);
    height: 3rem;
}

.nav-header-links li{
	margin:0;
}

.nav-header-links .flex-grow a{
	position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
}

.nav-header-menu{
	list-style: none;
    padding: 0 1rem;
    margin: 0;
    position: absolute;
    top: 100%;
    background-color: var(--black);
    width: 100%;
    left: 0;
    right: 0;
    z-index: 500;
    border-bottom: 1px solid var(--light);
    transform: translateY(calc(1px - 100%));
    transition: transform .2s ease;
}

.open .nav-header-menu{
	transform: translateY(0);
}

.open + .container{
	opacity: .2;
	pointer-events: none;
}

.open .nav-header-menu {
    pointer-events: auto;
}

.nav-header.open .flex-grow a{
	pointer-events: none;
}

.nav-header-menu .menu-item{
	display: flex;
    gap: 0.5rem;
    text-decoration: none;
}

.nav-header-menu .menu-item .icon{
	color: inherit;
}

.spinner.make-cocktail .spinner-container{
    height: 100vh;
}

/*ensure 48px touch target area*/
#nav-menu,
#nav-credits{
	padding: 0.833rem;
	display: block;
}

#nav-credits{
	text-decoration: none;
	display: flex; 
}

#credit-count{
	font-size: 1.333rem;
	color: var(--white);
	margin-left: .333rem;
}

/*stepper*/

.step-by-step dt{
	display: flex;
    align-items: center;
    gap: 1rem;
}

.step-text{
	margin-left: 5rem;
}

.step-section{
	margin-bottom: 3rem;
}

.step{
	background-color: var(--light);
	display: block;
	min-width: 4rem;
	min-height: 4rem;
	border-radius: 100%;
	display: inline-flex;
    justify-content: center;
    align-items: flex-start;
    color: var(--black);
    padding-top: .27rem;
}

.step-one{
	position: relative;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap:2rem;
}

.step-one .inventory-item{
	width: 100%;
}

.stepper{
	display: flex;
    flex-direction: row;
    list-style-type: none;
    padding: 0;
    justify-content: space-between;
    align-items: center;
    position: relative;
}

.stepper li{
	position: relative;
	padding-top: 1.167rem;
}

.stepper li:before{
	content: '';
	display: block;
	width: .833rem;
	height: .833rem;
	rotate: 45deg;
	background-color: var(--white);
	border:1px solid var(--light);
	position: absolute;
	top:0;
	left: calc(50% - .416rem);
	z-index: 10;
}

.stepper .stepper-here:before,
.stepper .stepper-complete:before{
	background-color: var(--light);
}

.stepper .stepper-complete{
	color: var(--light);
}

.stepper:after{
	content: '';
	display: block;
	width: 100%;
	height: 1px;
	position: absolute;
	right: 0;
	left: 0;
	top: 1.333rem;
    border-bottom: 2px dotted var(--accent);
    z-index: 1;
}

.stepper li:nth-child(1):after,
.stepper li:nth-child(3):after{
	position: absolute;
    content: '';
    display: block;
    width: 100%;
    left: -50%;
    right: auto;
    height: 1rem;
    background: var(--dark);
    z-index: 5;
    top: 0;
}

.stepper li:nth-child(3):after{
    right: 0;
    left: auto;
    width: 50%;
}



/*photo preview*/

.photo-preview-area img{
	margin: 1rem auto;
	max-height: 50vh;
    border-radius: var(--border-radius);
    border:1px solid var(--light);
    background-color: var(--black);
}

/*cards*/

.card, .item-info{
	margin: 1rem auto;
    border-radius: var(--border-radius);
    border:1px solid var(--light);
    padding: 0 1rem;
}

.item-info{
	padding:0 1rem;
	background: var(--black);
}

.item dt{
	font-size: 0.833rem; /* 15px */
	line-height: 1.167rem; /* 21px */
	color: var(--light);
}

.item-name{
	font-size: 1.167rem; /* 21px */
	line-height: 1.667rem; /* 30 px*/
	font-weight: 800;

}

/*compnents*/

.spinner{
	position: relative;
}

.spinner-container{
	display: none;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-color: var(--scrim);    
    align-items: center;
    justify-content: center;
    z-index: 1000;
}

.spinner .spinner-container{
	display: flex;
}

.loader{
    animation: spin 1s linear infinite;
    width: 3rem;
    height: 3rem;
    color:var(--light);
}

@keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

/* A spinner centred on a normal page, below a message, such as the thanks
   page while credits arrive. */
.page-loader{
	display: flex;
	justify-content: center;
	margin: 1.5rem 0;
}


.complexity-slider {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin:1rem 0;
}

.slider-container {
    position: relative;
    width: 100%;
}

.complexity-range {
    width: 100%;
    -webkit-appearance: none;
    appearance: none;
    height: .5rem;
    background: var(--accent);
    outline: none;
    border-radius: var(--border-radius);
    padding:0;
}

.complexity-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 1.333rem;
    height: 1.333rem;
    background: var(--light);
    cursor: pointer;
    border-radius: 50%;
}

.complexity-range::-moz-range-thumb {
    width: 1.333rem;
    height: 1.333rem;
    background: var(--light);
    cursor: pointer;
    border-radius: 50%;
    border: none;
}

.slider-labels {
    display: flex;
    justify-content: space-between;
    font-size: 1rem;
    margin-top: 0.5rem;
}

.slider-value {
    text-align: center;
    font-weight: 800;
    margin-top: 0.5rem;
}

.mini-phone{
	border-radius: 10px;
	border:5px solid #000;
	border-bottom-width:30px;
	position: relative;
	margin-left: 1rem;
}

.focus-circle{
	width: 10rem;
	height: 10rem;
	border-radius: 100%;	
	position: absolute;
	top:2rem;
	left: 0;
	animation: spin 60s linear infinite;
	border: 5px dashed var(--light);	
}

/*utility*/

/* The scroll lock while a pop-up is open. It sits on the root so the page
   stops scrolling and the full-width header and footer stay unclipped.
   Replaces body.fixed{ overflow:hidden; }, which clipped the body to its
   30rem column once html took overflow-x:clip. Approved 3 October 2026. */
html:has(body.fixed){
	overflow:hidden;
}

.flex-grow{
	flex-grow: 1;
}

.color-light{
	color: var(--light);
}

.color-white{
	color: var(--white);
}

.stock-ingredients{
	display: flex;
    gap: 1rem;
    flex-direction: column;
    align-items: center;
}

.step-two{
	display: flex;
	gap:1rem;
	justify-content: center;
	flex-wrap: wrap;
}

.featured-image{
	position: relative;
}

.featured-image img{
	border-radius: 100%;
	border:1px solid var(--light);
	display: block;
	margin:0 auto;
}

.featured-image:after{
	content: '';
    width: 7rem;
    position: absolute;
    top: 0;
    right: 100%;
    bottom: 0;
    left: -.5rem;
    background-image: url(../img/featured-border.svg);
    background-size: contain;
    background-repeat: no-repeat;
}

.feature{
	margin-bottom: 2rem;
}

.home-img img{
	border-radius: calc(2 * var(--border-radius) );
	border:1px solid var(--light);
}


/*home page stuff*/

.homepage .container{
	display: flex;
	flex-direction: column;
	height: 100%;
}

.logo-full{
	background-image: url("../img/logo-full.svg");
	background-repeat: no-repeat;
    background-size: cover;
    height: 0;
    padding-bottom: 49%;
    background-position: 50% 0;
    font-size: 0;
    text-indent: -99rem;
    border: none;
}

.logo-full:after{
	display: none;
}

.logo-header{
	margin: 0.833rem auto;
}

.tagline{
	text-align: center;
	padding: 1rem;
	flex-grow: 1;
	align-items: center;
	display: flex;
}

.decoration-top{
	background-image: url("../img/decoration-top.svg");
    background-repeat: no-repeat;
    background-size: contain;
    height: 0;
    padding-bottom: 16%;
    background-position: 50% 0;
    margin: 0 auto;
}

.decoration-bottom{
	background-image: url("../img/decoration-top.svg");
    background-repeat: no-repeat;
    background-size: contain;
    height: 0;
    padding-bottom: 16%;
    background-position: 50% 0;
    margin: 0 auto;
    rotate:180deg;
}

.site-footer{
	text-align: center;
	background-color: var(--black);
	color: var(--white);
	padding: 1rem;
	font-size: var(--size-s);
	margin:0 -1rem;
}

/* Disabled buttons */
.btn:disabled,
.btn.is-disabled{
	opacity:.4;
	pointer-events:none;
	box-shadow:none;
}

/* Error messages. Approved 27 September 2026, replacing the gold inline text.
   .field-error is a badge under the field it belongs to.
   .form-error is a banner at the top of a form, for messages that belong to
   the whole form rather than one field, such as a failed log in.
   Both draw their own alert icon, so messages written by scripts match those
   from the server. Icon elements inside are hidden to avoid doubling up. */
.field-error,
.form-error{
	display:flex;
	gap:.5rem;
	align-items:flex-start;
	background-color:var(--error);
	color:var(--white);
	font-size:1rem;
	line-height:1.333rem;
	padding:.5rem .833rem;
	border-radius:var(--border-radius);
	margin:.333rem 0 0;
}

.form-error{
	padding:.833rem 1rem;
	margin:1rem 0;
}

.field-error::before,
.form-error::before{
	content:'';
	flex-shrink:0;
	width:1.333rem;
	height:1.333rem;
	background-color:currentColor;
	mask:var(--icon-alert) no-repeat center;
	mask-size:contain;
	-webkit-mask:var(--icon-alert) no-repeat center;
	-webkit-mask-size:contain;
}

.field-error .icon,
.form-error .icon{
	display:none;
}

/* Double-height separator before a grouped set of actions.
   Used where a wireframe pins buttons to the bottom of the screen: the
   buttons stay in flow and this holds the separation instead. */
.spacer{
	display:block;
	height:2.666rem;
	border:0;
	margin:0;
}

/* The hidden attribute needs to outrank the display values set above,
   so scripted show and hide works without inline styles. */
[hidden]{
	display:none !important;
}

/* The modal scrim is positioned absolutely, so on a page taller than the
   window it only covers the first screenful. Fixed positioning ties it to the
   viewport instead, whatever the scroll position. */
.alert-overlay{
	position:fixed;
}

/* Tabs read as clickable, so the cursor should agree. */
.btn-tab{
	cursor:pointer;
}

/* Shopping list rows. Top alignment keeps the trash icon level with the
   first line of the item name when a cocktail name sits beneath it. */
.shopping-item{
	align-items:flex-start;
}

/* The cocktails an item was added for, under its name. */
.shopping-list-for{
	color:var(--white);
	font-weight:400;
}

/* A steady pop-up width, so it keeps its size between states. The max-width
   holds the 2rem margins on phones narrower than the fixed width. */
.alert-box{
	width:22rem;
	max-width:calc(100% - 4rem);
}

/* Waiting pop-up: shown only when a wait passes 300ms. Narrower than the
   decision pop-ups, with everything centred: icon, message, spinner.
   The icon's min sizes override .icon-l, which the shared icon slot carries
   for the decision pop-ups. */
.alert-box.is-waiting{
	width:17rem;
	text-align:center;
}

.alert-box.is-waiting .waiting-icon{
	width:2.667rem;
	height:2.667rem;
	min-width:2.667rem;
	min-height:2.667rem;
	margin:0 auto;
	color:var(--black);
}

.alert-box.is-waiting .waiting-message:after{
	content:'...';
}

/* The waiting message always holds two lines of height, so the pop-up keeps
   its size as the bartender's lines rotate between one row and two.
   Approved 25 September 2026. */
.alert-box.is-waiting .waiting-message{
	min-height:2.667rem;
}

.alert-box.is-waiting .loader{
	margin:0 auto;
}

/* Plain button variant: .btn without the decorative marks, which crowd the
   label when a button is narrow. Used on every button inside a modal
   pop-up. Approved 25 September 2026. */
.btn-basic:before,
.btn-basic:after{
	display:none;
}

/* Choose Your Bartender, on Make A Cocktail. Approved 26 September 2026.
   Each row is a label wrapping a visually hidden radio button, so the whole
   row is the tap target and arrow keys still move between bartenders.
   Default, for narrow screens: no photos, with the button beneath each
   bartender's details. From 400px: the photo on the left with the button
   over its foot, and the details on the right. See docs/bartenders.md. */
.bartender-heading{
	font-family:"Playfair Display", serif;
	font-weight:400;
	font-size:1.333rem; /* 24px */
	line-height:1.778rem; /* 32px */
	text-align:center;
	width:100%;
	padding:0;
}

.bartender-option{
	position:relative;
	display:block;
	margin:1rem 0;
	color:var(--white);
	font-weight:400;
	cursor:pointer;
}

.bartender-option .bartender-input{
	position:absolute;
	top:0;
	left:0;
	width:1px;
	height:1px;
	margin:0;
	opacity:0;
	pointer-events:none;
}

.bartender-photo{
	display:none;
}

.bartender-details{
	display:block;
}

.bartender-name{
	display:block;
	font-weight:800;
	color:var(--light);
}

.bartender-blurb{
	display:block;
	margin:.5rem 0;
}

.bartender-cost{
	display:flex;
	align-items:center;
	gap:.5rem;
	font-weight:800;
	color:var(--light);
	transition:color .2s ease;
}

.bartender-cost .icon{
	color:var(--light);
}

.bartender-input:checked ~ .bartender-details .bartender-cost{
	color:var(--white);
}

/* Selected is the standard .btn. Unselected is a solid dark button, so its
   label stays legible over a photo. */
.bartender-button{
	margin:1rem 0 0;
}

.bartender-input:not(:checked) ~ .bartender-button{
	background:var(--black);
	color:var(--light);
	border-color:var(--light);
	box-shadow:none;
}

.bartender-option:hover .bartender-input:not(:checked) ~ .bartender-button{
	color:var(--white);
}

.bartender-input:focus-visible ~ .bartender-button{
	outline:3px solid var(--white);
}

.bartender-button-selected,
.bartender-input:checked ~ .bartender-button .bartender-button-select{
	display:none;
}

.bartender-input:checked ~ .bartender-button .bartender-button-selected{
	display:inline;
}

/* The photo layout. Adjust the breakpoint after testing. */
@media (min-width:400px){
	.bartender-option{
		display:grid;
		grid-template-columns:7rem 1fr;
		grid-template-rows:7rem auto;
		grid-template-areas:"photo details" ". details";
		column-gap:1rem;
	}

	.bartender-photo{
		display:block;
		grid-area:photo;
		width:7rem;
		height:7rem;
		object-fit:cover;
		border-radius:calc(2 * var(--border-radius));
		border:1px solid transparent;
		filter:grayscale(1);
		transition:filter .2s ease, border-color .2s ease;
	}

	.bartender-input:checked ~ .bartender-photo{
		filter:none;
		border-color:var(--light);
	}

	.bartender-details{
		grid-area:details;
	}

	/* Smaller type and tighter spacing, so "Selected" fits across a 7rem photo. */
	.bartender-button{
		grid-area:photo;
		align-self:end;
		width:auto;
		margin:0 .333rem .333rem;
		padding:.333rem;
		font-size:.833rem;
	}

	/* A photo in a right-hand column beside the text before it, such as the
	   bartender beside the title and made-by line on the cocktail pages. The
	   spare last row takes the photo's extra height when the text is short,
	   so the lines stay together at the top. Below 400px the children simply
	   stack, and the cocktail pages hide the photo. Approved 30 September 2026. */
	.photo-right{
		display:grid;
		grid-template-columns:1fr 7rem;
		grid-template-rows:auto auto 1fr;
		column-gap:1rem;
	}

	/* Grid margins don't collapse, so this keeps the stacked spacing. */
	.photo-right > *{
		margin-bottom:0;
	}

	.photo-right > img{
		display:block;
		grid-column:2;
		grid-row:1 / -1;
		width:7rem;
		height:7rem;
		margin:1rem 0 0;
	}
}

/* Float an element to the left for text to wrap around it. The margin keeps
   it tight to the left and top edges, with space between it and the text. */
.float-left{
	float:left;
	margin:0 1rem 1rem 0;
}

/* Holds a floated element inside its box, so a short text beside a tall image
   never lets the image spill past the border. */
.contain-floats{
	display:flow-root;
}

/* The bartender's photo on the generated and saved cocktail pages, shown only
   from 400px, beside the title and made-by line (see .photo-right).
   Approved 26 September 2026, hidden below 400px 30 September 2026. */
.bartender-avatar{
	display:none;
	width:7rem;
	height:7rem;
	object-fit:cover;
	border-radius:calc(2 * var(--border-radius));
}

/* A full-width photo with rounded corners. Used for the cocktail photo on the
   generated and saved cocktail pages. Approved 30 September 2026. */
.photo-full{
	display:block;
	width:100%;
	height:auto;
	border-radius:calc(2 * var(--border-radius));
}

/* Right-aligned text, such as the Serving suggestion caption.
   Approved 30 September 2026. */
.text-right{
	text-align:right;
}

/* Toggle switch: a checkbox styled as an on/off switch, with role="switch"
   on the input. Off is a black track with a gold knob, on is the checked
   checkbox's gold with a cream knob. The knob is the ::after, so the check
   mark from the checkbox rule is cleared here. Used for Expand Your Horizons
   on Make A Cocktail and Prevent phone sleep on the cocktail pages.
   Approved 26 September 2026. */
input[type="checkbox"].toggle{
	width:2.667rem;
	height:1.444rem;
	flex-shrink:0;
	border-radius:.722rem;
	cursor:pointer;
}

input[type="checkbox"].toggle:not(:checked){
	background-color:var(--black);
}

input[type="checkbox"].toggle::after{
	content:'';
	position:absolute;
	top:50%;
	left:.167rem;
	width:1rem;
	height:1rem;
	border-radius:50%;
	background-color:var(--accent);
	transform:translate(0, -50%);
	-webkit-mask:none;
	mask:none;
	transition:transform .2s ease, background-color .2s ease;
}

input[type="checkbox"].toggle:checked::after{
	background-color:var(--white);
	transform:translate(1.222rem, -50%);
}

input[type="checkbox"].toggle:focus-visible{
	outline:3px solid var(--light);
	outline-offset:2px;
}

/* A disabled toggle, such as the bottles option at the bottle limit. Matches
   .btn:disabled. Approved 26 September 2026. */
input[type="checkbox"].toggle:disabled{
	opacity:.4;
	cursor:default;
}

@media (prefers-reduced-motion: reduce){
	input[type="checkbox"].toggle::after{
		transition:none;
	}
}

/* Faux progress bar, at the foot of the waiting pop-up while a cocktail is
   made. Built like the toggle: a black track with a gold edge, and a gold
   fill inset by the same gap as the toggle's knob. The fill starts as a
   circle the size of that knob and stretches to full width over
   --progress-duration, set per bartender in config.php, then holds.
   Approved 27 September 2026.
   --progress-ease sets how the fill moves within that time: one of the
   speed patterns in config.php, chosen at random for each cocktail. Without
   it the fill is even. Approved 2 October 2026. */
.progress-bar{
	height:1.444rem;
	padding:.167rem;
	border:1px solid var(--accent);
	border-radius:.722rem;
	background-color:var(--black);
	overflow:hidden;
}

.progress-bar-fill{
	height:100%;
	width:1rem;
	border-radius:.5rem;
	background-color:var(--accent);
	animation:progress-fill var(--progress-duration, 20s) var(--progress-ease, linear) forwards;
}

@keyframes progress-fill{
	from{ width:1rem; }
	to{ width:100%; }
}

/* Space above the bar inside the pop-up. */
.alert-box .progress-bar{
	margin-top:1rem;
}

/* A title inside a card, as on the generated and saved cocktail pages: room
   above it, and the circle on its rule filled with the card's black instead
   of the page's blue. Approved 27 September 2026. */
.item-info h1:first-child,
.item-info .h1:first-child{
	margin-top:1rem;
}

.item-info h1:after,
.item-info .h1:after{
	background-color:var(--black);
}

/* A row whose children share the width equally, however many there are.
   Used for Save Cocktail or Delete beside New Cocktail on the generated and
   saved cocktail pages. Approved 27 September 2026. */
.equal-row{
	display:flex;
	gap:1rem;
	margin:1rem 0;
}

.equal-row > *{
	flex:1 1 0;
	margin:0;
}

/* An icon beside its text on one line, icon first. Icons are display:block,
   so without this they sit on a line of their own. Used for Jump to
   ingredients on the cocktail pages. Approved 27 September 2026. */
.icon-label{
	display:flex;
	align-items:center;
	gap:.5rem;
}

/* Pushes a flex row's content to the right edge, such as Jump to ingredients
   across from Keep screen on. Renamed from .saved-marker when the Saved
   marker was retired. Approved 27 September 2026. */
.justify-end{
	justify-content:flex-end;
}

/* The buttons under a cocktail's recipe, on the generated and saved cocktail
   pages, with extra room above and below. Approved 27 September 2026. */
.cocktail-buttons{
	margin:2rem 0;
}

/* Full-width header bar, on the app and the store front. The bar breaks out
   of the 30rem column to the edges of the screen, while the menu toggle,
   logo and menu items stay lined up with the column. The gold line under the
   open menu is kept. Approved 27 September 2026. */
.nav-header{
	margin-left:calc(50% - 50vw);
	margin-right:calc(50% - 50vw);
}

.nav-header-links{
	max-width:30rem;
	margin:0 auto;
}

.nav-header-menu{
	padding-left:max(1rem, calc((100% - 30rem) / 2 + 1rem));
	padding-right:max(1rem, calc((100% - 30rem) / 2 + 1rem));
}

/* 100vw counts the scrollbar on desktop, so without this the full-width bar
   would nudge every page into a slight sideways scroll. */
html{
	overflow-x:clip;
}

/* The page you're on, in cream, in the store front menu. */
.nav-header-menu .menu-item[aria-current="page"]{
	color:var(--white);
}

/* Full-width site footer, mirroring the header: edge to edge, with a gold
   line along its top like the one under the open menu. Its text stays within
   the 30rem column. Approved 27 September 2026. */
.site-footer{
	margin-top:3rem;
	margin-left:calc(50% - 50vw);
	margin-right:calc(50% - 50vw);
	border-top:1px solid var(--light);
}

.site-footer p{
	max-width:30rem;
	margin-left:auto;
	margin-right:auto;
}


.cocktail-actions{
	margin-top:0;
}

/* Keep screen on, beside Share at the top of a cocktail page. A label is
   bold by default. This one is a special case: it takes the regular weight
   so it matches the Share label next to it, and .text-secondary in the
   markup gives it the same size. Approved 5 October 2026. */
.cocktail-actions .checkbox-label{
	font-weight:400;
}

/* Icon button: a square .btn holding a single icon, used beside .btn and
   .btn-basic, which supply the button styling and remove the decorative
   marks. The padding matches a select's, so the two sit level in a row.
   A button that is switched off (aria-pressed="false") takes the page's dark
   background with a gold icon, as with the sort buttons on the Bottles tab
   of Manage Inventory. Approved 3 October 2026. */
.icon-btn{
	width:auto;
	flex-shrink:0;
	margin:0;
	padding:.5rem;
	cursor:pointer;
}

.icon-btn[aria-pressed="false"]{
	background:var(--dark);
	color:var(--light);
}

.icon-btn[aria-pressed="false"]:hover{
	color:var(--white);
}

/* Pop-up animation: unfold. The pop-up opens from its centre line with the
   content fading in behind it, and closes the same way in reverse.
   The opening plays whenever the overlay goes from hidden to shown.
   closeModal() in modal.js adds .is-closing, then hides the overlay once the
   exit finishes: 320ms, or 120ms under reduced motion. Keep those two
   figures in step with MODAL_EXIT_MS in modal.js.
   Approved 3 October 2026. */
.alert-overlay{
	overflow:hidden;
	animation:scrim-in .2s ease-out both;
}

.alert-overlay.is-closing{
	animation:scrim-out .32s ease-in both;
}

.alert-box{
	animation:unfold-in .36s cubic-bezier(.16,1,.3,1) both;
}

.alert-box > *{
	animation:content-in .2s ease-out .14s both;
}

.is-closing .alert-box{
	animation:unfold-out .22s ease-in .1s both;
}

.is-closing .alert-box > *{
	animation:content-out .1s ease-in both;
}

@keyframes scrim-in{
	from{ background-color:rgba(0, 0, 0, 0); }
	to{ background-color:rgba(0, 0, 0, 0.5); }
}

@keyframes scrim-out{
	from{ background-color:rgba(0, 0, 0, 0.5); }
	to{ background-color:rgba(0, 0, 0, 0); }
}

@keyframes unfold-in{
	0%{ opacity:0; clip-path:inset(calc(50% - 1px) 0 round var(--border-radius)); }
	15%{ opacity:1; }
	100%{ opacity:1; clip-path:inset(0 0 round var(--border-radius)); }
}

@keyframes unfold-out{
	0%{ opacity:1; clip-path:inset(0 0 round var(--border-radius)); }
	85%{ opacity:1; }
	100%{ opacity:0; clip-path:inset(calc(50% - 1px) 0 round var(--border-radius)); }
}

@keyframes content-in{
	from{ opacity:0; }
	to{ opacity:1; }
}

@keyframes content-out{
	from{ opacity:1; }
	to{ opacity:0; }
}

/* Reduced motion: a short plain fade in place of the unfold. */
@media (prefers-reduced-motion: reduce){
	.alert-overlay,
	.alert-overlay.is-closing{
		animation-duration:.12s;
	}

	.alert-box{
		animation:content-in .12s linear both;
	}

	.is-closing .alert-box{
		animation:content-out .12s linear both;
	}

	.alert-box > *,
	.is-closing .alert-box > *{
		animation:none;
	}
}

/* Compact view of the Bottles tab: one bottle per row, the name linked to
   its edit screen and cut short with an ellipsis. Approved 4 October 2026. */
.bottle-row{
	display:block;
	padding:.75rem 0;
	border-bottom:1px solid var(--black);
	white-space:nowrap;
	overflow:hidden;
	text-overflow:ellipsis;
}

/* Onboarding progress marker, under the heading of each onboarding step.
   The waiting pop-up's progress bar, held still, with the four steps named
   beneath it in equal columns. The fill stops under the middle of the
   current step's label and runs to the end on the last step. Finished steps
   are gold with a check, the current step is bold white, and steps still to
   come use the accent colour. Reaching the last step gives it a check too. Markup in
   includes/onboarding-progress.php. Added 5 October 2026, with Paul's
   go-ahead to write the CSS without a separate approval. */
.onboarding-progress{
	margin:1rem 0;
	/* How far the bar sits in from each side, so it reads as part of the
	   labels beneath it. The fill widths below allow for it. */
	--bar-inset:1rem;
	/* The inset plus the bar's own edge: its border and padding. */
	--bar-edge:calc(var(--bar-inset) + .167rem + 1px);
}

.onboarding-progress .progress-bar{
	margin:0 var(--bar-inset);
}

.onboarding-progress .progress-bar-fill{
	animation:none;
	/* Never narrower than its starting circle, on the smallest screens. */
	min-width:1rem;
}

/* The labels' centres sit at 12.5%, 37.5% and 62.5% of the full width. The
   bar is narrower than that by the inset on each side, so each width is
   adjusted to land the end of the fill under its label's centre. */
.onboarding-progress[data-step="1"] .progress-bar-fill{ width:calc(12.5% - var(--bar-edge) * .75); }
.onboarding-progress[data-step="2"] .progress-bar-fill{ width:calc(37.5% - var(--bar-edge) * .25); }
.onboarding-progress[data-step="3"] .progress-bar-fill{ width:calc(62.5% + var(--bar-edge) * .25); }
.onboarding-progress[data-step="4"] .progress-bar-fill{ width:100%; }

.progress-steps{
	display:grid;
	grid-template-columns:repeat(4, 1fr);
	margin:.444rem 0 0;
	padding:0;
	list-style:none;
	white-space:nowrap;
	/* Steps still to come. Black was tried first and was too hard to read. */
	color:var(--accent);
}

/* Each label is centred in its column, with its check beside it. */
.progress-steps li{
	margin:0;
	display:flex;
	justify-content:center;
	align-items:center;
	gap:.167rem;
}

.progress-steps .is-done{
	color:var(--light);
}

/* Lucide's check, sized down from the standard icon to sit beside the small
   label text. */
.progress-steps .icon{
	min-width:0;
	min-height:0;
	width:.778rem;
	height:.778rem;
}

/* After .is-done, so the last step keeps the current colour once it is
   reached and carries its check as well. */
.progress-steps [aria-current]{
	color:var(--white);
	font-weight:800;
}









