/* =========================================================================
   shop.css — the cart, the auth pages, the shared form language, the toast
   and the empty states.

   ONE FORM COMPONENT. The newsletter, the contact form, the cart request
   and the two auth forms all use .field / .field__label / .input /
   .field__err / .cform__status. Four forms that each looked slightly
   different was the single clearest tell that this site had been assembled
   rather than designed, so the differences were removed rather than
   documented.
   ========================================================================= */

/* =========================================================================
   FIELD
   ========================================================================= */
.field { display: grid; gap: var(--s-2); margin-bottom: var(--s-5); }

.field__label {
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--cocoa);
}
.field__label .req { color: var(--hot-pink); margin-left: 2px; }

.field__hint {
  font-size: 13px;
  color: var(--cocoa);
  opacity: .8;
}

.input,
textarea.input,
select.input {
  width: 100%;
  font-family: var(--font-ui);
  font-size: 16px;   /* 16px floor: anything smaller makes iOS zoom on focus */
  color: var(--ink);
  background: var(--cream);
  border: 1.5px solid rgba(var(--cocoa-rgb), .28);
  border-radius: var(--r-sm);
  padding: 13px 15px;
  transition: border-color var(--dur-control) var(--ease-out),
              box-shadow var(--dur-control) var(--ease-out),
              background-color var(--dur-control) var(--ease-out);
}
.input::placeholder { color: rgba(var(--cocoa-rgb), .55); }
.input:hover { border-color: rgba(var(--cocoa-rgb), .45); }
.input:focus-visible,
.input:focus {
  outline: none;
  border-color: var(--teal-deep);
  box-shadow: 0 0 0 4px rgba(var(--teal-rgb, 14, 63, 56), .14);
}
textarea.input { min-height: 132px; resize: vertical; }

/* Invalid. Border AND an icon-free message beneath — colour alone is not a
   signal for a red/green colour-blind visitor, which is ~8% of men. */
.field.is-invalid .input,
.input[aria-invalid='true'] {
  border-color: #C0392B;
  background: rgba(192, 57, 43, .04);
}
.field__err {
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 600;
  color: #A8321F;              /* 5.6:1 on cream — measured, not picked */
  margin: 0;
}
.field__err[hidden] { display: none; }

/* Checkbox row — the label is the hit target, so the box does not need to
   be one. */
.field--check {
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--s-3);
}
.field--check input[type='checkbox'] {
  width: 20px;
  height: 20px;
  accent-color: var(--teal-deep);
  cursor: pointer;
}
.field--check label {
  font-family: var(--font-ui);
  font-size: 15px;
  color: var(--cocoa);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 500;
  cursor: pointer;
}

/* =========================================================================
   STATUS LINE — one style, both outcomes.
   ========================================================================= */
.cform__status {
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.5;
  border-radius: var(--r-sm);
  padding: 12px 15px;
  margin-top: var(--s-4);
}
.cform__status[hidden] { display: none; }
.cform__status.is-ok {
  color: var(--teal-deep);
  background: rgba(14, 63, 56, .09);
  border-left: 4px solid var(--teal-deep);
}
.cform__status.is-error {
  color: #A8321F;
  background: rgba(192, 57, 43, .07);
  border-left: 4px solid #C0392B;
}

/* Busy submit. The label is replaced by a spinner and the width is held, so
   the button does not jump as it changes state. */
.btn.is-busy {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}
.btn.is-busy::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 18px;
  height: 18px;
  border: 2.5px solid rgba(255, 247, 239, .4);
  border-top-color: var(--cream);
  border-radius: 50%;
  animation: btn-spin .7s linear infinite;
}
.btn--ghost.is-busy::after,
.btn--dark.is-busy::after { border-color: rgba(92, 53, 33, .3); border-top-color: var(--cocoa); }
@keyframes btn-spin { to { transform: rotate(360deg); } }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn.is-busy:disabled { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .btn.is-busy::after { animation-duration: 2s; }
}

/* =========================================================================
   TOAST
   Bottom CENTRE, not a corner. Both corners are taken: the assistant
   launcher sits bottom-left and back-to-top bottom-right, and this is the
   third thing that has wanted that space. Centre is free, and a
   confirmation belongs near where the eye already is rather than in
   whichever corner happens to be empty this week.
   ========================================================================= */
.toast-host {
  position: fixed;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  translate: -50% 0;
  z-index: var(--z-toast, 800);
  display: grid;
  gap: var(--s-2);
  justify-items: center;
  pointer-events: none;
  width: min(92vw, 420px);
}
.toast {
  pointer-events: auto;
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 600;
  color: var(--cream);
  background: var(--teal-deep);
  border-radius: var(--r-pill);
  padding: 12px 22px;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  translate: 0 14px;
  transition: opacity .3s var(--ease-out), translate .3s var(--ease-out);
  text-align: center;
}
.toast.is-in { opacity: 1; translate: 0 0; }
@media (prefers-reduced-motion: reduce) {
  .toast { transition-duration: .01ms; translate: 0 0; }
}
/* The launcher and back-to-top are ~56px squares inset 24px from the bottom
   corners. Centring the toast between them works on a wide screen and fails
   on a narrow one: at 360px the two widgets are only ~200px apart and a
   238px toast sits on top of both. Measured at 360x760, where it covered
   them; the original rule only handled SHORT screens and missed this
   entirely.

   So: lift the toast above the widget row whenever the viewport is narrow
   OR short. Beside them is not an option at 360 — there is no beside. */
@media (max-width: 620px), (max-height: 620px) {
  .toast-host { bottom: calc(96px + env(safe-area-inset-bottom, 0px)); }
}

/* =========================================================================
   EMPTY STATES — designed, not blank.
   One component for all four cases: empty cart, no saved requests, no
   search results, no filter matches. Mark, sentence, way out.
   ========================================================================= */
.empty-state {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: var(--s-4);
  padding: clamp(var(--s-10), 6vw, var(--s-20)) var(--s-4);
  max-width: 44ch;
  margin-inline: auto;
}
.empty-state__mark {
  width: clamp(72px, 9vw, 104px);
  height: clamp(72px, 9vw, 104px);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--sand);
  color: var(--teal-deep);
}
.empty-state__mark svg { width: 58%; height: 58%; }
.empty-state__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(23px, 2.4vw, 32px);
  color: var(--teal-deep);
  font-variation-settings: var(--wonk-sub);
  margin: 0;
}
.empty-state p { color: var(--cocoa); margin: 0; }
.empty-state__actions { display: flex; flex-wrap: wrap; gap: var(--s-3); justify-content: center; }

/* =========================================================================
   CART PAGE
   ========================================================================= */
.cart-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(300px, 1fr);
  gap: clamp(var(--s-6), 3.5vw, var(--s-12));
  align-items: start;
}
@media (max-width: 900px) { .cart-layout { grid-template-columns: 1fr; } }

.cart-lines { display: grid; gap: var(--s-4); }

.cart-line {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr) auto;
  gap: var(--s-4);
  align-items: center;
  padding: var(--s-4);
  background: var(--cream);
  border: 1px solid rgba(var(--cocoa-rgb), .12);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
}
.cart-line__media {
  width: 92px;
  aspect-ratio: 3 / 4;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--sand);
}
.cart-line__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cart-line__name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(17px, 1.5vw, 21px);
  color: var(--ink);
  margin: 0 0 2px;
}
.cart-line__unit { font-size: 14px; color: var(--cocoa); }
.cart-line__right { display: grid; justify-items: end; gap: var(--s-2); }
.cart-line__total {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(17px, 1.5vw, 21px);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--ink);
}

/* Stepper. 40px targets — below that this is a fiddly control on a phone,
   and quantity is the thing people change most on a cart page. */
.stepper { display: flex; align-items: center; gap: var(--s-1); }
.stepper__btn {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  border: 1.5px solid rgba(var(--cocoa-rgb), .28);
  background: var(--cream);
  color: var(--ink);
  font-size: 19px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur-control) var(--ease-out),
              border-color var(--dur-control) var(--ease-out);
}
.stepper__btn:hover { background: var(--sand); border-color: var(--cocoa); }
.stepper__btn:active { scale: .9; }
.stepper__btn:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
  box-shadow: var(--focus-halo);
}
.stepper__val {
  min-width: 34px;
  text-align: center;
  font-family: var(--font-ui);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  color: var(--ink);
}

.cart-line__remove {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  color: var(--cocoa);
  background: none;
  border: 0;
  padding: 4px 2px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--dur-control) var(--ease-out);
}
.cart-line__remove:hover { color: #A8321F; }
.cart-line__remove:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

@media (max-width: 600px) {
  .cart-line { grid-template-columns: 72px minmax(0, 1fr); }
  .cart-line__media { width: 72px; }
  .cart-line__right { grid-column: 1 / -1; justify-items: stretch; }
  .cart-line__right .stepper { justify-content: space-between; }
}

/* ---- Summary rail ------------------------------------------------------ */
.cart-side {
  position: sticky;
  top: calc(var(--nav-h-solid) + var(--s-4));
  display: grid;
  gap: var(--s-5);
}
@media (max-width: 900px) { .cart-side { position: static; } }

.cart-card {
  background: var(--sand);
  border-radius: var(--r-md);
  padding: clamp(var(--s-5), 2.4vw, var(--s-8));
  box-shadow: var(--shadow-sm);
}
.cart-card__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(19px, 1.8vw, 25px);
  color: var(--teal-deep);
  font-variation-settings: var(--wonk-sub);
  margin: 0 0 var(--s-4);
}
.cart-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-3);
  padding-top: var(--s-4);
  margin-top: var(--s-4);
  border-top: 1.5px solid rgba(var(--cocoa-rgb), .22);
}
.cart-total__label {
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--cocoa);
}
.cart-total__value {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(24px, 2.6vw, 34px);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  white-space: nowrap;
}
.cart-actions { display: grid; gap: var(--s-3); margin-top: var(--s-5); }
.cart-actions .btn { width: 100%; justify-content: center; }

/* =========================================================================
   THE REQUEST IS NOT AN ORDER
   This notice is load-bearing copy, not decoration. A visitor who believes
   they have ordered and then hears nothing is the failure mode this whole
   flow is shaped around, so it is stated at the form, again on the button,
   and again in the success state.
   ========================================================================= */
.request-note {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  background: rgba(246, 173, 205, .28);
  border-radius: var(--r-sm);
  padding: var(--s-4);
  margin-bottom: var(--s-6);
  font-size: 15px;
  line-height: 1.55;
  color: var(--cocoa);
}
.request-note strong { color: var(--ink); }
.request-note__icon { flex: 0 0 auto; width: 22px; height: 22px; color: var(--teal-deep); }
.request-note__icon svg { width: 100%; height: 100%; }

/* =========================================================================
   AUTH
   ========================================================================= */
.auth-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .85fr);
  gap: clamp(var(--s-8), 5vw, var(--s-16));
  align-items: start;
}
@media (max-width: 900px) { .auth-layout { grid-template-columns: 1fr; } }

.auth-card {
  background: var(--cream);
  border: 1px solid rgba(var(--cocoa-rgb), .12);
  border-radius: var(--r-md);
  padding: clamp(var(--s-6), 3vw, var(--s-10));
  box-shadow: var(--shadow-md);
  max-width: 32rem;
}
.auth-card .btn[type='submit'] { width: 100%; justify-content: center; margin-top: var(--s-2); }
.auth-alt {
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px solid rgba(var(--cocoa-rgb), .14);
  font-size: 15px;
  color: var(--cocoa);
}
.auth-alt a { color: var(--teal-deep); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }

/* ---- The demo-password notice ------------------------------------------
   REQUIRED WHILE js/auth.js STORES PASSWORDS IN PLAIN TEXT. See the
   SECURITY header in that file. Styled as part of the design rather than as
   an error — an error style would read as a fault the visitor caused — but
   deliberately impossible to skim past: it sits inside the form, above the
   password field, at full width, with a solid rule and a heading weight.

   Do not remove this because it interrupts the layout. It is the control
   that makes shipping the plain-text store defensible at all, and it comes
   out only when the store does. */
.demo-notice {
  border: 2px solid var(--teal-deep);
  border-radius: var(--r-sm);
  background: rgba(14, 63, 56, .06);
  padding: var(--s-4) var(--s-5);
  margin-bottom: var(--s-6);
}
.demo-notice__head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--teal-deep);
  margin-bottom: var(--s-2);
}
.demo-notice__head svg { width: 17px; height: 17px; flex: 0 0 auto; }
.demo-notice p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--cocoa);
}
.demo-notice strong { color: var(--ink); }

/* ---- Account ----------------------------------------------------------- */
.account-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
  gap: clamp(var(--s-6), 3.5vw, var(--s-12));
  align-items: start;
}
@media (max-width: 900px) { .account-grid { grid-template-columns: 1fr; } }

.account-id {
  background: var(--teal-deep);
  color: var(--cream);
  border-radius: var(--r-md);
  padding: clamp(var(--s-6), 3vw, var(--s-10));
}
.account-id__name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(26px, 2.8vw, 38px);
  font-variation-settings: var(--wonk-sub);
  margin: 0 0 var(--s-1);
  color: var(--cream);
}
.account-id__email { color: var(--bubblegum); font-size: 15px; word-break: break-word; }
.account-id .btn { margin-top: var(--s-6); }

.order-list { display: grid; gap: var(--s-4); }
.order-card {
  background: var(--cream);
  border: 1px solid rgba(var(--cocoa-rgb), .14);
  border-left: 4px solid var(--bubblegum);
  border-radius: var(--r-sm);
  padding: var(--s-5);
  box-shadow: var(--shadow-sm);
}
.order-card__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-bottom: var(--s-3);
}
.order-card__when {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--cocoa);
}
/* "Zahtev poslat", never "Porudžbina primljena". The state this records is
   that a request exists in this browser — nothing has been accepted by
   anyone and no money has moved. */
.order-card__state {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--teal-deep);
  background: rgba(14, 63, 56, .1);
  border-radius: var(--r-pill);
  padding: 4px 11px;
}
.order-card__items { margin: 0; padding: 0; list-style: none; display: grid; gap: 3px; }
.order-card__items li {
  font-size: 15px;
  color: var(--cocoa);
  display: flex;
  justify-content: space-between;
  gap: var(--s-3);
}
.order-card__items b { color: var(--ink); font-variant-numeric: tabular-nums; }
.order-card__meta {
  margin-top: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid rgba(var(--cocoa-rgb), .12);
  font-size: 14px;
  color: var(--cocoa);
  display: grid;
  gap: 2px;
}
