/*
 * Customer website responsive completion layer.
 *
 * This file is loaded after the established page styles (and after the
 * Products page's inline styles) so the normal desktop layout remains intact.
 * Rules are limited to compact/tablet viewports, short screens, and very wide
 * displays that need a capped reading measure, plus shared navigation links.
 */

.brand-name-short {
  display: none;
}

.apt-header-spacer {
  width: 32px;
  flex: 0 0 32px;
}

/* Appointment return navigation uses the same arrow-and-text link on the
   maroon stage and the completion dialog's light footer. */
#appointmentFlow .apt-header-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: start;
  gap: 6px;
}

#appointmentFlow .apt-main-title {
  width: 100%;
  min-width: 0;
  margin: 0;
}

:is(#appointmentFlow, #successAppointmentModal) .apt-home-link {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 9px;
  width: fit-content;
  max-width: 100%;
  min-height: 44px;
  padding: 4px 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--customer-wine);
  font: 600 15px / 1.4 "Montserrat", sans-serif;
  text-decoration: none;
  cursor: pointer;
  box-shadow: none;
  transform: none;
  transition: color 0.18s ease;
}

#appointmentFlow .apt-home-link {
  color: var(--customer-paper-sink);
}

:is(#appointmentFlow, #successAppointmentModal) .apt-home-link svg {
  flex: 0 0 20px;
  width: 20px;
  height: 20px;
}

:is(#appointmentFlow, #successAppointmentModal) .apt-home-link:is(:hover, :focus-visible) span {
  text-decoration: underline;
  text-underline-offset: 3px;
}

#appointmentFlow .apt-home-link:is(:hover, :focus-visible) {
  color: var(--apt-gold-soft);
}

#successAppointmentModal .apt-home-link:is(:hover, :focus-visible) {
  color: var(--customer-wine-hover);
}

:is(#appointmentFlow, #successAppointmentModal) .apt-home-link:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

#appointmentFlow .apt-home-link[aria-disabled="true"] {
  opacity: 0.55;
  cursor: wait;
  pointer-events: none;
}

/* "No services found" placeholder. Same presentation the services grid used
   inline before, kept in one place so phones can tighten it. Mirrors
   `.services-load-error` in main.css. */
.services-empty-state {
  grid-column: 1 / -1;
  padding: 50px 20px;
  color: #6d7480;
  font-weight: 700;
  text-align: center;
}

/* Calendar dates are native buttons; neutralize browser button chrome so
   their established visual treatment remains unchanged. */
.cal-day-cell {
  margin: 0;
  padding: 0;
  appearance: none;
  font-family: inherit;
}

@media (hover: hover) and (pointer: fine) {
  .cal-day-cell[title] {
    overflow: visible;
  }
}

/* Mobile/tablet navigation uses the requested compact UCN / FMRC lockup. */
@media (max-width: 900px) {
  .brand-name-full {
    display: none;
  }

  .brand-name-short {
    display: inline;
  }

  .site-header .logo-text,
  .sidebar-logo-container .logo-text {
    width: auto;
    max-width: none;
    gap: 1px;
  }

  .site-header .logo-title,
  .sidebar-logo-container .logo-title {
    font-size: clamp(14px, 2.6vw, 17px);
    line-height: 1;
    letter-spacing: 0.08em;
  }

  .site-header .logo-subtitle,
  .sidebar-logo-container .logo-subtitle {
    display: block;
    font-size: clamp(9px, 1.8vw, 11px);
    line-height: 1.05;
    letter-spacing: 0.16em;
  }

  .site-header .logo-container {
    flex: 1 1 auto;
    width: auto;
  }

  .toolbar-container,
  .toolbar-actions,
  .contact-grid,
  .contact-info-card,
  .contact-form-card,
  .modal-box,
  .shop-modal-box,
  .customer-modal,
  .guest-access-card,
  .apt-card,
  .ticket-container {
    min-width: 0;
  }

  .customer-order-main,
  .customer-order-side,
  .checkout-product-details,
  .checkout-cart-item-details,
  .cart-item-details,
  .client-details,
  .switch-text,
  .upsell-left,
  .upsell-right {
    min-width: 0;
  }

  /* No fill and no sticky — the title sits on the stage itself (main.css §8.6).
     The gradient that used to live here faded to fully transparent over its
     bottom 22%, so card text scrolled up through the title; sticky was what made
     that visible, and a filled bar was the only way to hide it. With no fill
     there is nothing to show through and nothing to hide, so both go, and the
     header is static at every width. `padding-block` stays at 6px —
     `.apt-error-alert`'s top offset below is calibrated to the height it
     produces. */
  .apt-header-top {
    margin-top: 0;
    padding-block: 6px;
  }
}

/* Small phones: let two-filter toolbars and modal controls use full rows. */
@media (max-width: 420px) {
  .toolbar-actions {
    display: grid;
    grid-template-columns: 1fr;
  }

  .category-dropdown-box {
    width: 100%;
  }

  .announcement-modal__actions,
  .modal-actions,
  .guest-access-actions,
  .customer-rating-actions {
    flex-wrap: wrap;
  }

  .announcement-modal__button,
  .modal-actions .modal-btn,
  .guest-access-btn {
    min-width: 0;
  }

  .profile-popup,
  .guest-profile-popup {
    left: auto;
    right: max(6px, env(safe-area-inset-right, 0px));
    width: min(390px, calc(100vw - 12px));
    max-width: calc(100vw - 12px);
  }

  .service-card-heading,
  .service-card-heading span,
  .hero-research-line {
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .customer-orders-tabs {
    scroll-snap-type: x proximity;
  }

  .customer-orders-tab {
    scroll-snap-align: start;
  }

  .client-name-phone,
  .client-dept-role,
  .product-price-row,
  .checkout-cart-item .product-price-row,
  .checkout-protection-upsell,
  .c-total-row,
  .cart-item-bottom,
  .customer-order-side,
  .customer-order-actions,
  .customer-order-timeline-top {
    flex-wrap: wrap;
  }

  .radio-grid {
    grid-template-columns: 1fr;
  }
}

/* ---------------------------------------------------------------------------
   Appointment field errors — portal-style summary alert (phones only).

   Built by main.js and appended to <body>. Hidden by default so the desktop
   experience (absolute bubbles beside each field) is untouched; the <=640px
   band below turns it on and keeps the bubbles out of the flow, because seven
   in-flow bubbles used to grow Step 2 by ~356px and shove the form under the
   user's thumb. Geometry mirrors .auth-error-alert in customer-auth/auth.css.
   --------------------------------------------------------------------------- */
.apt-error-alert {
  display: none;
}

@media (max-width: 640px) {
  /* Message text now lives in the summary alert; the field keeps only its ring
     so nothing below it moves when validation runs. */
  .apt-field-error-bubble {
    display: none !important;
  }

  .file-upload-wrapper.has-error {
    border-color: var(--customer-danger);
    box-shadow: 0 0 0 3px rgba(191, 27, 27, 0.14);
    background-color: #fffafa;
  }

  .apt-error-alert {
    position: fixed;
    /* Clears the sticky .apt-header-top, whose bottom edge measures 70px. */
    top: max(78px, calc(74px + var(--ux-safe-t, 0px)));
    left: 50%;
    transform: translateX(-50%);
    z-index: 26000;
    display: flex;
    gap: 10px;
    align-items: flex-start;
    width: min(430px, calc(100% - 20px));
    /* Deliberately short. Ten messages at once is the worst case (Next on a
       blank form) and the list scrolls; what matters more is that the panel
       stops short of the first field, which cannot be scrolled out from under
       a taller panel because the form is already at the top of its range. */
    max-height: min(34vh, 210px);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 12px;
    border: 1px solid #e8c4c1;
    border-radius: var(--ux-dlg-radius, 8px);
    background: #fff6f5;
    box-shadow: 0 14px 34px rgba(75, 12, 12, 0.18);
  }

  .apt-error-alert.is-leaving {
    opacity: 0;
    transition: opacity 0.26s ease;
  }

  .apt-error-mark {
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--customer-danger);
    color: #f7f2ec;
    font-size: 13px;
    font-weight: 800;
    line-height: 20px;
    text-align: center;
  }

  .apt-error-body {
    flex: 1 1 auto;
    min-width: 0;
  }

  .apt-error-title {
    margin: 0 0 6px;
    color: var(--customer-danger);
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .apt-error-list {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .apt-error-item + .apt-error-item {
    margin-top: 2px;
  }

  .apt-error-link {
    display: block;
    width: 100%;
    margin: 0;
    padding: 3px 0;
    border: 0;
    background: none;
    color: var(--customer-danger);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1.4;
    text-align: left;
    overflow-wrap: anywhere;
    cursor: pointer;
  }

  .apt-error-close {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--customer-danger);
    font-size: 19px;
    line-height: 1;
    cursor: pointer;
  }
}

@media (max-width: 430px) {
  .apt-error-alert {
    top: max(72px, calc(68px + var(--ux-safe-t, 0px)));
    padding: 10px;
    gap: 8px;
  }

  .apt-error-link {
    font-size: 12px;
  }
}

@media (max-width: 430px) {
  /* The month grid shrinks to the card instead of scrolling sideways inside it:
     a 332px floor used to hide ~35px of Saturday behind an easy-to-miss
     scroller on every iPhone width. */
  .apt-calendar-left {
    overflow-x: visible;
    padding-inline: clamp(6px, 2.4vw, 14px);
  }

  .cal-days-header,
  .cal-days-grid {
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: clamp(2px, 1vw, 4px);
  }

  .cal-days-header {
    row-gap: 0;
  }

  .cal-day-cell {
    aspect-ratio: 1;
    min-height: 0;
    font-size: clamp(10px, 2.8vw, 12px);
  }

  .cal-legend {
    flex-wrap: wrap;
  }

  /* Native title text is unreliable on touch and the pseudo-tooltip would be
     clipped by the calendar card; screen readers use the ARIA label. */
  .cal-day-cell[title]::before {
    display: none;
  }
}

/* Below ~300px seven squares stop being tappable, so the scroller comes back. */
@media (max-width: 300px) {
  .apt-calendar-left {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
  }

  .cal-navigation,
  .cal-days-header,
  .cal-days-grid {
    min-width: 266px;
  }

  .cal-day-cell {
    aspect-ratio: auto;
    min-height: 34px;
  }
}

/* ---------------------------------------------------------------------------
   Appointment progress strip + tickets (phones only)
   --------------------------------------------------------------------------- */
@media (max-width: 640px) {
  /* Fixed-width steps left each caption wider than its own box, so
     "Appointment" bled across its neighbours. Let the five steps share the
     strip evenly instead, and give single words somewhere to break. */
  .apt-step {
    width: auto;
    flex: 1 1 0;
    min-width: 0;
  }

  /* Thin fixed connectors: left growable they would take an equal share of the
     strip and starve the five captions. */
  .apt-line {
    flex: 0 0 clamp(4px, 1.6vw, 10px);
    min-width: 4px;
  }

  /* Sized so the longest caption ("Appointment") clears its box on one line at
     every width in this band; `anywhere` is only the safety net below that. */
  .apt-step span:last-child {
    font-size: clamp(7.5px, 2vw, 10px);
    line-height: 1.2;
    overflow-wrap: anywhere;
  }

  .apt-step .step-label {
    font-size: clamp(6.5px, 1.9vw, 9px);
    letter-spacing: 0.04em;
  }

  /* `margin: 0 auto` on a column flex item overrides `stretch`, which shrank
     Step 4's ticket to its own content (~280px) and wasted a third of the
     screen. Step 5 escaped it only because its QR column is wider. */
  .apt-content-section .ticket-container {
    width: 100%;
  }

  #officialReceiptCard .ticket-note {
    padding: 12px 14px;
  }

  #receiptQrImage {
    max-width: 100%;
    height: auto;
  }
}

/* Below ~340px five even steps stop fitting, so main.css turns the strip into a
   swipeable rail. Re-assert the fixed basis the rule above would otherwise win. */
@media (max-width: 340px) {
  .apt-step {
    flex: 0 0 auto;
    /* 6px wider than main.css's 52px: at this width the caption font bottoms out
       at 7.5px, where "Appointment" needs the full 52px and wrapped onto a second
       line, leaving that one step taller than its neighbours. The rail already
       scrolls here, so the extra width costs nothing. */
    width: 58px;
  }

  .apt-line {
    flex: 0 0 12px;
    min-width: 12px;
  }
}

/* Ultra-narrow layouts include 126px watch-style and 240px phone widths. */
@media (max-width: 280px) {
  :root {
    --ux-gutter: 7px;
    --ux-gap: 8px;
    /* Matches the dialog radius; the cards stay pointy all the way down. */
    --ux-card-radius: 8px;
    --ux-tap: 38px;
  }

  .site-header {
    flex-wrap: wrap !important;
    gap: 5px !important;
    min-height: 0;
    padding: max(6px, env(safe-area-inset-top, 0px))
      max(7px, env(safe-area-inset-right, 0px)) 6px
      max(7px, env(safe-area-inset-left, 0px)) !important;
  }

  .site-header .mobile-menu-toggle {
    order: 1;
  }

  .site-header .logo-container {
    order: 2;
    flex: 1 1 calc(100% - 38px);
    width: calc(100% - 38px);
    margin: 0;
  }

  .site-header .header-right-actions {
    order: 3;
    width: 100%;
    justify-content: space-evenly;
    gap: 3px;
    /* The containing block for both profile dropdowns at this width. Without it
       they anchor `right: 6px` on `.user-profile`, which `space-evenly` above
       parks 65px in from the row's right edge — so a 264px card measured 60px of
       its own left side off the left of the screen. This row spans the header's
       full content width, so the same `right: 6px` now lands where it reads, and
       `top: 44px` still resolves just under the 34px-tall row. Safe for the bell:
       `.announcement-bell-wrapper` is already `position: relative` and owns its
       own badge, and the panel it opens is a `position: fixed` dialog.

       `!important` because main.css's own ≤900px arm ships
       `.header-right-actions { position: static !important }` (main.css:7120) to
       undo the `position: absolute; top: 20px; right: 5%` of its ≤768px arm — a
       flagged (0,1,0) declaration that a plain (0,2,0) selector cannot outrank.
       Scoped to ≤280px, so the ≤900px neutralisation it overrides still holds
       everywhere that rule was actually written for. */
    position: relative !important;
  }

  /* …and the host has to stop being the containing block, or the row above is
     just a positioned ancestor the popup never reaches: `.user-profile` is
     `position: relative` in main.css, which makes it the *nearest* one. Static
     here hands both dropdowns to the row. The popup is the only absolutely
     positioned child of this host — the badge belongs to the bell, which keeps
     its own `relative` wrapper — so nothing else moves. */
  .site-header .header-right-actions .user-profile {
    position: static;
  }

  .site-header .header-emblem {
    height: 26px;
    margin-right: 6px;
  }

  .site-header .logo-title {
    font-size: 12px;
  }

  .site-header .logo-subtitle {
    font-size: 8px;
  }

  .site-header .mobile-menu-toggle,
  .header-right-actions .cart-icon-container,
  .header-right-actions .announcement-bell,
  .header-right-actions .user-profile,
  .header-right-actions .guest-sign-in-trigger {
    width: 34px;
    min-width: 34px;
    height: 34px;
    min-height: 34px;
  }

  .header-right-actions .guest-sign-in-trigger {
    display: grid;
    grid-template-columns: 1fr;
    padding: 3px;
    border-radius: var(--apt-radius, 8px);
  }

  .header-right-actions .guest-sign-in-mark {
    display: grid;
    width: 26px;
    height: 26px;
    margin: auto;
  }

  .header-right-actions .guest-sign-in-copy,
  .header-right-actions .guest-sign-in-chevron {
    display: none;
  }

  .mobile-sidebar {
    width: min(96vw, 270px);
  }

  .sidebar-header {
    gap: 5px;
    padding-inline: 7px;
  }

  .sidebar-header .sidebar-close-btn {
    width: 34px;
    min-width: 34px;
    height: 34px;
    min-height: 34px;
  }

  .sidebar-logo-container .header-emblem {
    height: 25px;
    margin-right: 5px;
  }

  .sidebar-logo-container .logo-title {
    font-size: 11px;
  }

  .sidebar-logo-container .logo-subtitle {
    font-size: 7.5px;
  }

  .hero-section,
  .about-section,
  .vision-section,
  .mission-section,
  .services-preview-section,
  .services-list-section,
  .services-top-bar,
  .products-toolbar,
  .shop-section,
  .contact-main-section,
  .site-footer {
    padding-left: max(7px, env(safe-area-inset-left, 0px));
    padding-right: max(7px, env(safe-area-inset-right, 0px));
  }

  .hero-section {
    min-height: auto;
    padding-top: 20px;
    padding-bottom: 28px;
  }

  .hero-title {
    font-size: clamp(15px, 8vw, 21px) !important;
    line-height: 1.22;
    overflow-wrap: anywhere;
  }

  .hero-graphic {
    width: min(54vw, 116px);
  }

  .hero-buttons,
  .apt-footer-actions,
  .nested-actions,
  .modal-actions,
  .announcement-modal__actions,
  .guest-access-actions,
  .customer-rating-actions {
    display: grid !important;
    grid-template-columns: 1fr !important;
    width: 100%;
  }

  .btn-browse,
  .btn-appointment,
  .apt-btn,
  .nested-actions .apt-btn,
  .modal-btn,
  .announcement-modal__button,
  .guest-access-btn,
  .customer-rating-actions button {
    width: 100%;
    min-width: 0 !important;
    padding-inline: 8px;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .section-title,
  .vm-title,
  .services-list-header h2,
  .contact-title,
  .contact-subtitle {
    font-size: clamp(14px, 11vw, 21px) !important;
    overflow-wrap: anywhere;
  }

  .section-text,
  .vm-text,
  .services-list-header p,
  .contact-lead,
  .contact-link-text,
  .card-desc,
  .footer-desc,
  .footer-text,
  .footer-link,
  .contact-list li {
    font-size: clamp(10px, 7.8vw, 13px);
    line-height: 1.5;
    overflow-wrap: anywhere;
  }

  .about-container,
  .vision-container,
  .mission-container {
    padding-inline: 0;
  }

  .about-video-holder {
    height: auto;
    min-height: 82px;
    aspect-ratio: 4 / 3;
  }

  .carousel-btn {
    display: none;
  }

  .carousel-wrapper,
  .landscape-carousel.carousel-wrapper {
    width: 100%;
    height: clamp(250px, 210vw, 330px);
  }

  .carousel-item,
  .landscape-carousel .carousel-item {
    width: calc(100vw - 20px);
    height: clamp(225px, 190vw, 300px);
  }

  .carousel-item.prev,
  .carousel-item.next {
    opacity: 0;
    pointer-events: none;
  }

  .landscape-card .card-img-holder {
    height: clamp(72px, 68vw, 115px);
  }

  .services-grid .card-content,
  .product-info,
  .contact-info-card,
  .contact-form-card {
    padding: 10px !important;
  }

  .services-grid .card-title,
  .product-name {
    font-size: clamp(11px, 8vw, 14px);
  }

  .service-card-heading {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }

  .service-chip {
    max-width: 100%;
    padding: 5px 7px;
    font-size: 9px;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .service-image-preview-label {
    right: 6px;
    bottom: 6px;
    gap: 0;
    width: 30px;
    height: 30px;
    justify-content: center;
    padding: 0;
    font-size: 0;
  }

  .service-image-preview-label i {
    font-size: 11px;
  }

  .product-price {
    font-size: clamp(13px, 10vw, 17px);
  }

  .toolbar-container,
  .toolbar-actions {
    width: 100%;
  }

  .toolbar-search,
  .category-dropdown-box {
    padding-inline: 8px;
  }

  .toolbar-search > svg {
    width: 16px;
    flex: 0 0 16px;
  }

  .toolbar-search .search-input,
  .category-select,
  .contact-input,
  .c-input {
    min-width: 0;
  }

  .promotion-spotlight-wrap,
  .promotion-spotlight {
    padding-inline: 7px !important;
  }

  .promotion-spotlight-card,
  .promotion-spotlight__inner {
    gap: 6px !important;
    padding: 10px 8px !important;
    border-radius: 10px !important;
  }

  .promotion-spotlight__icon,
  .spotlight-celebration-icon {
    display: none !important;
  }

  .contact-links-list li {
    flex-direction: column;
    align-items: flex-start;
    gap: 7px;
  }

  .contact-link-icon {
    width: 30px;
    height: 30px;
  }

  .footer-logo-row {
    align-items: flex-start;
    flex-wrap: wrap;
  }

  .footer-logo {
    height: 30px;
  }

  .footer-brand,
  .footer-heading {
    font-size: clamp(13px, 10vw, 17px);
    overflow-wrap: anywhere;
  }

  /* All customer overlays remain scrollable on very small canvases. */
  .modal-overlay,
  .customer-modal-overlay,
  .guest-access-modal,
  .success-modal-overlay,
  .apt-nested-modal,
  .announcement-modal,
  .about-video-modal,
  .image-lightbox-overlay {
    padding: max(5px, env(safe-area-inset-top, 0px))
      max(5px, env(safe-area-inset-right, 0px))
      max(5px, env(safe-area-inset-bottom, 0px))
      max(5px, env(safe-area-inset-left, 0px));
    overflow-y: auto;
  }

  .modal-box,
  .guest-access-card,
  .customer-modal,
  .customer-modal-overlay.show .customer-modal,
  .apt-nested-box,
  #aptConfirmModal .apt-nested-box,
  .success-card,
  .announcement-modal__card {
    width: 100%;
    max-width: 100%;
    padding: 10px;
    border-radius: var(--ux-dlg-radius, 8px);
  }

  .modal-header,
  .modal-scroll-area,
  .modal-actions,
  .announcement-modal__hero,
  .announcement-modal__body {
    padding: 10px;
  }

  .modal-title,
  .announcement-modal__title,
  .guest-access-title,
  .customer-modal-title,
  .apt-nested-box h3,
  #aptConfirmModal .apt-nested-box h3,
  .success-title {
    font-size: clamp(13px, 10vw, 18px);
    overflow-wrap: anywhere;
  }

  .modal-header {
    gap: 5px;
  }

  .modal-title {
    min-width: 0;
  }

  .close-modal-btn,
  .lightbox-close-btn,
  .guest-access-close,
  .customer-modal-close,
  .about-video-close,
  .customer-orders-close {
    width: 34px;
    min-width: 34px;
    height: 34px;
    min-height: 34px;
  }

  /* Radius is not restated here any more: the home-page round took the desktop
     dropdown to `var(--apt-radius)`, so an 8px literal in this arm would just be
     a second place to change the same number. Padding still has work to do —
     desktop is 14px. */
  .profile-popup,
  .guest-profile-popup {
    padding: 10px;
  }

  .profile-popup-link,
  .popup-logout,
  .guest-auth-btn {
    min-height: 38px;
    padding: 9px 7px;
    font-size: 11px;
    overflow-wrap: anywhere;
  }

  .customer-orders-modal {
    padding: max(7px, env(safe-area-inset-top, 0px))
      max(5px, env(safe-area-inset-right, 0px))
      max(7px, env(safe-area-inset-bottom, 0px))
      max(5px, env(safe-area-inset-left, 0px));
    gap: 8px;
  }

  .customer-orders-head {
    gap: 5px;
    padding-bottom: 8px;
  }

  .customer-orders-title {
    font-size: 13px;
  }

  .customer-orders-subtitle,
  .customer-orders-sync-status {
    font-size: 9px;
    overflow-wrap: anywhere;
  }

  .customer-orders-panel {
    padding: 5px;
  }

  .customer-order-card {
    grid-template-columns: 1fr;
    padding: 7px;
  }

  .customer-order-thumb {
    width: min(58px, 100%);
    height: 58px;
  }

  .customer-order-side {
    grid-column: auto;
    align-items: flex-start;
  }

  .customer-order-detail-summary {
    grid-template-columns: 1fr;
  }

  .customer-order-detail-item {
    flex-direction: column;
    align-items: flex-start;
  }

  /* Product checkout/cart sheets: avoid fixed image/control rows. */
  .shop-modal-header,
  .shop-modal-body,
  .shop-modal-footer,
  .checkout-section,
  .checkout-client-info,
  .cart-item-card,
  .add-address-row,
  .address-card {
    padding: 8px !important;
  }

  .shop-modal-header {
    gap: 5px;
  }

  .shop-modal-title {
    min-width: 0;
    font-size: clamp(12px, 9vw, 16px) !important;
    overflow-wrap: anywhere;
  }

  .back-shop-modal,
  .trash-btn {
    width: 32px;
    min-width: 32px;
    height: 32px;
  }

  .qty-btn {
    width: 28px;
  }

  .qty-selector input {
    width: 32px;
  }

  .checkout-client-info,
  .checkout-product-card,
  .checkout-cart-item,
  .cart-item-card,
  .checkout-protection-upsell,
  .c-switch-group {
    flex-direction: column;
    align-items: stretch;
  }

  .checkout-product-card img,
  .checkout-cart-item img,
  .cart-item-img {
    width: min(62px, 100%);
    height: 62px;
    margin: 0;
  }

  .cart-item-details {
    width: 100%;
    height: auto;
    gap: 8px;
  }

  .shop-modal-footer {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }

  .footer-total-display,
  .btn-place-order {
    width: 100%;
    justify-content: center;
  }

  .phone-input-group {
    grid-template-columns: 1fr;
  }

  .phone-prefix {
    min-width: 0;
    padding: 9px;
    border-right: 0;
    border-bottom: 1px solid #d9d9d9;
  }

  /* Appointment flow keeps controls reachable and scrolls dense calendars. */
  .apt-container {
    padding: max(7px, env(safe-area-inset-top, 0px))
      max(7px, env(safe-area-inset-right, 0px))
      max(14px, env(safe-area-inset-bottom, 0px))
      max(7px, env(safe-area-inset-left, 0px));
  }

  .apt-header-top {
    justify-content: flex-start;
  }

  .apt-header-spacer {
    display: none;
  }

  .apt-main-title {
    min-width: 0;
    font-size: clamp(13px, 10vw, 18px);
    overflow-wrap: anywhere;
    text-align: left;
  }

  .apt-back-btn {
    width: 34px;
    min-width: 34px;
    height: 34px;
  }

  .apt-progress-wrapper {
    padding: 7px 5px;
    scroll-snap-type: x proximity;
  }

  .apt-step {
    width: 46px;
    scroll-snap-align: start;
  }

  .apt-icon {
    width: 30px;
    height: 30px;
  }

  .apt-card {
    padding: 9px !important;
  }

  .apt-reminder-item {
    flex-direction: column;
    padding: 9px;
  }

  .apt-card-header h3,
  .apt-reminder-content h4 {
    overflow-wrap: anywhere;
    word-break: break-word;
  }

  .apt-form-grid {
    gap: 10px;
  }

  .apt-calendar-left,
  .apt-time-right {
    padding: 8px;
  }

  .apt-calendar-left {
    overflow-x: auto;
    overscroll-behavior-x: contain;
  }

  .cal-navigation,
  .cal-days-header,
  .cal-days-grid {
    min-width: 332px;
  }

  .cal-day-cell {
    min-height: 44px;
  }

  .calendar-header-text h3,
  #calMonthYear {
    font-size: clamp(12px, 9vw, 17px);
    overflow-wrap: anywhere;
  }

  .calendar-header-text p,
  .time-placeholder,
  .leg-item,
  .time-slot-btn {
    font-size: clamp(9px, 7vw, 12px);
  }

  .file-upload-wrapper {
    height: auto;
    min-height: 82px;
    padding: 8px;
  }

  .file-upload-text,
  #aptFileName {
    max-width: 100%;
    font-size: 10px !important;
    overflow-wrap: anywhere;
  }

  .ticket-header,
  .ticket-body {
    padding: 9px !important;
  }

  .ticket-header h3,
  #revTicketNo,
  #comTicketNo {
    font-size: clamp(11px, 9vw, 16px) !important;
    overflow-wrap: anywhere;
  }

  .ticket-row,
  .ticket-column {
    width: 100%;
    min-width: 0;
  }

  .t-value,
  #revSched,
  #comSched,
  .success-reference strong {
    font-size: clamp(10px, 7.5vw, 14px) !important;
    overflow-wrap: anywhere;
    word-break: break-word;
  }

  #officialReceiptCard .ticket-qr {
    max-width: 100%;
  }

  #officialReceiptCard .ticket-note {
    padding: 9px;
    font-size: 10px;
    overflow-wrap: anywhere;
  }

  .nested-icon,
  #aptConfirmModal .nested-icon,
  .success-icon {
    width: 44px;
    height: 44px;
    margin-bottom: 10px;
    border-width: 4px;
    font-size: 21px;
  }

  #aptPrivacyModal .nested-icon {
    position: static;
    margin: 0 auto 10px;
    transform: none;
  }

  .apt-nested-box p,
  #aptConfirmModal .apt-nested-box p,
  .success-desc,
  .success-note,
  .guest-access-copy {
    font-size: 10px;
    line-height: 1.45;
    overflow-wrap: anywhere;
  }

  .success-card__header,
  .success-card__body,
  .success-card__footer {
    padding: 10px;
  }
}

/* Very short screens use top-aligned, scroll-safe dialogs. */
@media (max-width: 900px) and (max-height: 520px) {
  .modal-overlay,
  .customer-modal-overlay,
  .guest-access-modal,
  .success-modal-overlay,
  .apt-nested-modal,
  .announcement-modal,
  .about-video-modal,
  .image-lightbox-overlay {
    align-items: flex-start;
    overflow-y: auto;
  }

  .modal-box,
  .customer-modal,
  .guest-access-card,
  .success-card,
  .apt-nested-box,
  .announcement-modal__card {
    margin-block: auto;
    max-height: calc(100dvh - 12px);
    overflow-y: auto;
  }

  .success-card {
    display: block;
    overflow-y: auto;
  }

  .success-card__body {
    overflow: visible;
  }

  #aptPrivacyModal .nested-icon {
    position: static;
    margin: 0 auto 10px;
    transform: none;
  }

  .shop-modal-box,
  .customer-orders-modal {
    height: 100dvh;
    min-height: 0;
  }

  .apt-overlay {
    overflow-y: auto;
  }
}

/* Keep header controls and content comfortably grouped on 4K/8K canvases. */
@media (min-width: 2200px) {
  .site-header {
    padding-left: max(72px, calc((100vw - 1760px) / 2));
    padding-right: max(72px, calc((100vw - 1760px) / 2));
  }
}

/* -----------------------------------------------------------------
   Mobile density refinement

   Keep the requested UCN / FMRC lockup readable, prevent the hero CTAs
   from inheriting a 150px flex-basis after they stack, and give the
   Services and Products pages a genuinely compact two-card mobile grid.
   ----------------------------------------------------------------- */
@media (max-width: 900px) {
  .site-header .logo-title,
  .sidebar-logo-container .logo-title {
    font-size: clamp(15px, 2.8vw, 18px);
    line-height: 1;
    letter-spacing: 0.075em;
  }

  .site-header .logo-subtitle,
  .sidebar-logo-container .logo-subtitle {
    font-size: clamp(10px, 1.9vw, 12px);
    line-height: 1;
    letter-spacing: 0.14em;
  }

  /* Hero SDG badges: still 4 + 4, just a tighter pitch. */
  .hero-sdg-strip {
    --sdg-gap: clamp(5px, 1vw, 10px);
    margin-top: clamp(22px, 3.6vw, 40px);
    width: min(100%, 380px);
  }

  .hero-sdg-item {
    max-width: 64px;
  }
}

@media (max-width: 720px) {
  /* The inherited `flex-basis: 150px` was being interpreted vertically
     once the CTA group stacked, which produced the oversized pills. */
  .hero-buttons {
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 9px;
    width: min(100%, 360px);
    max-width: 360px;
  }

  .btn-browse,
  .btn-appointment {
    width: auto;
    min-width: 0;
    min-height: 42px;
    flex: 0 0 auto;
    padding: 10px 12px;
    /* Same 8px the desktop rule paints. The two hero CTAs used to drop to a 12px
       rectangle once they stacked into the two-column grid above, which made the
       same two controls read as a different kind of control on a phone. This
       entry exists only to hold them at the site's one button radius; nothing
       about the grid needs a different corner. */
    border-radius: var(--apt-radius, 8px);
    font-size: 12px;
    line-height: 1.15;
    white-space: normal;
  }

  .hero-section {
    padding: clamp(24px, 6vw, 38px) max(12px, env(safe-area-inset-right, 0px))
      clamp(34px, 8vw, 54px) max(12px, env(safe-area-inset-left, 0px));
  }

  .hero-container {
    gap: 12px;
  }

  .hero-graphic {
    width: min(46vw, 190px);
  }

  .hero-title {
    margin-bottom: 18px;
    font-size: clamp(22px, 7.2vw, 34px) !important;
  }

  /* Match the CTA grid width so the badges read as one block with the pills. */
  .hero-sdg-strip {
    --sdg-gap: 6px;
    margin-top: 26px;
    width: min(100%, 360px);
    max-width: 360px;
  }

  .hero-sdg-item {
    max-width: 52px;
  }

  .hero-sdg-caption {
    margin: 8px 0 0;
    font-size: 9px;
    letter-spacing: 0.1em;
  }

  .hero-sdg-btn {
    padding: 2px;
    border-width: 1.5px;
  }

  /* Compact signed-out navigation to the same icon-sized control language
     as cart, notifications, and profile. */
  .header-right-actions .guest-sign-in-trigger {
    display: inline-grid;
    place-items: center;
    width: 40px;
    min-width: 40px;
    height: 40px;
    min-height: 40px;
    padding: 0;
    border-radius: var(--apt-radius, 8px);
  }

  .header-right-actions .guest-sign-in-mark {
    display: grid;
    width: 30px;
    height: 30px;
  }

  .header-right-actions .guest-sign-in-copy,
  .header-right-actions .guest-sign-in-chevron {
    display: none;
  }

  /* Two cards per row on normal mobile widths. `minmax(0, 1fr)` lets the
     card internals shrink instead of forcing the grid back to one column. */
  .services-grid,
  .shop-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: clamp(8px, 2.4vw, 14px) !important;
  }

  .services-grid .service-card,
  .shop-card {
    width: 100%;
    min-width: 0;
  }

  .products-page-body #productGrid .product-img-wrapper {
    position: relative;
    height: auto !important;
    aspect-ratio: 4 / 3;
  }

  .service-image-trigger,
  .services-grid .service-image-placeholder,
  .services-grid .card-img-holder {
    aspect-ratio: 4 / 3;
  }

  /* The label collapses to an icon-only circle here (`font-size: 0`), but the
     ` Preview` text node is still a flex item, so the inherited 7px gap pushed
     the glyph 3.45px left of centre. Zero the gap for the collapsed state only
     — the expanded pill at wider widths keeps its icon/text spacing. */
  .service-image-preview-label {
    right: 7px;
    bottom: 7px;
    gap: 0;
    width: 30px;
    height: 30px;
    justify-content: center;
    padding: 0;
    font-size: 0;
  }

  .service-image-preview-label i {
    font-size: 12px;
  }

  .services-grid .card-content,
  .product-info {
    padding: clamp(9px, 2.8vw, 13px) !important;
  }

  .services-grid .card-content {
    gap: 7px;
  }

  .service-card-heading {
    align-items: flex-start;
    gap: 5px;
  }

  .service-chip {
    max-width: 100%;
    padding: 4px 6px;
    font-size: clamp(7.5px, 2.1vw, 9px);
    line-height: 1.15;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .service-index {
    flex: 0 0 auto;
    font-size: 8px;
  }

  .services-grid .card-title,
  .product-name {
    font-size: clamp(11px, 3.1vw, 13px);
    line-height: 1.28;
  }

  .services-grid .card-desc {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    font-size: clamp(9px, 2.45vw, 11px);
    line-height: 1.4;
  }

  /* A touch more breathing room under the card body so the footer no longer
     hugs the bottom edge (+10px of card height on a phone). */
  .service-card-footer {
    margin-top: 6px;
    padding-top: 9px;
    padding-bottom: 4px;
  }

  /* `main.css`'s ≤600px rule stacks the footer into a column; the services card
     needs a single row so the View control can span the full width. */
  .services-page-body .service-card-footer {
    flex-direction: row;
    align-items: center;
  }

  /* The View control reads as a real button on touch: full width, the word
     "View" plus the arrow, which also signals that the card opens details.
     Radius is the site's one button corner — this was 10px, which is close
     enough to 8px to look like a mistake rather than a decision once the
     service modal that opens above it carries 8px on its own footer buttons. */
  .services-grid .details-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    min-width: 0;
    height: 36px;
    min-height: 36px;
    padding: 0 10px;
    border: 1px solid rgba(107, 32, 43, 0.16);
    border-radius: var(--apt-radius, 8px);
    background: rgba(107, 32, 43, 0.07);
    font-size: clamp(10.5px, 3vw, 12.5px);
    font-weight: 800;
    letter-spacing: 0.2px;
  }

  /* The control is a bordered button here, so the desktop underline bar would
     cut across it. The hover and focus variants are listed too: the desktop
     rule that reveals the bar is `:hover::after`, one class more specific than
     a bare `::after`, so a sticky hover on a touch screen would otherwise draw
     a 2px bar across the button. */
  .services-grid .details-btn::after,
  .services-grid .details-btn:hover::after,
  .services-grid .details-btn:focus-visible::after {
    display: none;
  }

  /* Only the tail of the services label is hidden, so the pill reads "View →"
     while assistive tech still gets the full "View service details" wording.
     The products page hides only its cart label, at every width — see the
     file-scope rule after this band. */
  .services-grid .details-btn .details-btn-tail {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
  }

  .services-grid .details-btn i {
    font-size: 13px;
  }

  /* Services list intro: the desktop copy ran to four lines on a 320px screen. */
  .services-page-body .services-list-header h2 {
    font-size: clamp(17px, 4.6vw, 22px);
    line-height: 1.2;
  }

  .services-page-body .services-list-header p {
    font-size: clamp(11px, 3.2vw, 13px);
    line-height: 1.45;
  }

  /* Match the loading skeleton to the real card's mobile image ratio (4/3)
     so the grid does not jump when the API data lands. */
  .services-page-body .service-skeleton-img {
    aspect-ratio: 4 / 3;
  }

  .services-page-body .services-empty-state {
    padding: 28px 14px;
    font-size: clamp(11px, 3.2vw, 13px);
  }

  .product-info {
    gap: 2px;
  }

  .product-name {
    min-height: 2.56em;
    margin-bottom: 5px;
  }

  .product-code-row {
    min-width: 0;
    margin-bottom: 6px;
    font-size: 9px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .product-code-row .code-label {
    display: none;
  }

  .product-price {
    margin-bottom: 7px;
    font-size: clamp(14px, 4vw, 17px);
    line-height: 1.15;
  }

  .product-price-sale {
    flex-wrap: wrap;
    gap: 3px 6px;
  }

  .product-price-sale .sale-price {
    font-size: clamp(14px, 4vw, 17px);
  }

  .product-price-sale .original-price {
    font-size: clamp(9px, 2.5vw, 11px);
  }

  .product-stock-row {
    align-items: flex-start;
    gap: 4px;
  }

  .stock-text {
    display: none;
  }

  .stock-badge,
  .product-discount-badge {
    padding: 3px 6px;
    font-size: clamp(7px, 2vw, 9px);
    letter-spacing: 0;
  }

  .product-discount-badge {
    top: 6px;
    left: 6px;
  }

  /* Card footer on phones: "View Info" owns the first row full-width, then the
     icon-only plus-cart and "Buy Now" share the second. Three labelled buttons
     cannot fit one row at these widths (the footer's inner width is 132px at
     320), and this is the same shape the details modal uses. Placement is by
     grid area, so `buildCard`'s DOM order is untouched. */
  .products-page-body .product-actions {
    /* `!important` clears the 1-column override main.css forces at <=340px. */
    grid-template-columns: auto minmax(0, 1fr) !important;
    gap: 4px;
    padding: 6px;
    border-radius: 0 0 15px 15px;
  }

  .products-page-body .product-actions .btn-view-info {
    grid-column: 1 / -1;
  }

  .products-page-body .product-actions .action-btn {
    position: relative;
    min-width: 0;
    min-height: 36px;
    height: 36px;
    padding: 0 8px;
    gap: 6px;
    border-width: 1px;
    border-radius: var(--apt-radius, 8px);
    /* Both `!important`s answer main.css's <=340px band, which pins the font to
       11px and re-enables wrapping; three classes here still out-rank it. */
    font-size: clamp(10px, 2.9vw, 12px) !important;
    font-weight: 800;
    letter-spacing: 0.2px;
    white-space: nowrap !important;
  }

  /* The cart is a square icon button at every width — see the file-scope rules
     after this band for the desktop half. */
  .products-page-body .product-actions .btn-add-cart {
    width: 40px;
    padding: 0;
    gap: 0;
  }

  .products-page-body .product-actions .action-btn > svg {
    width: 15px;
    height: 15px;
  }

  /* The rating row kept its desktop type scale, which crowded the 146px card. */
  .products-page-body .product-rating-row {
    margin-bottom: 6px;
    gap: 4px;
    font-size: clamp(10px, 3vw, 12px);
  }

  /* ---- Service details modal on phones -------------------------------- */

  /* Matches the specificity of the shared ux-dlg cap in main.css and wins by
     load order, so the sheet can use the last few pixels of a short screen. */
  #serviceModal.ux-dlg .modal-box.ux-dlg__card {
    max-height: min(94vh, calc(100dvh - 12px));
  }

  #serviceModal .modal-scroll-area {
    padding: 12px;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  /* The fixed clamp band left letterboxing on narrow screens; a 4/3 box keeps
     the banner in step with the card images. */
  #serviceModal .modal-img-holder {
    height: auto;
    aspect-ratio: 4 / 3;
  }

  #serviceModal .modal-desc,
  #serviceModal .modal-list li {
    overflow-wrap: anywhere;
  }

  /* ---- Service image lightbox on phones ------------------------------- */

  /* The close button hangs outside the box on desktop, which put it flush with
     the screen edge at 320px. Bring it inside the frame. */
  /* The gutter is wide enough for the corner badge below to hang outside the
     frame and still keep ~10px of clearance from the screen edge. */
  #serviceImageLightboxModal .lightbox-box {
    max-width: calc(100vw - 44px);
    padding: 12px;
  }

  /* Same corner badge as desktop — the circle straddles the top-right edge of
     the frame — only pulled in from the stock -14px so the 40px tap target
     never reaches the screen edge on a narrow phone. */
  #serviceImageLightboxModal .lightbox-close-btn {
    top: -12px;
    right: -12px;
  }

  /* The shared photo cap is `min(86vw, 1000px)`, which ignores the frame and
     would poke the image past the white border now that the box is narrower.
     44px of gutter + 2 x 12px of padding = the 68px subtracted here, so the
     frame hugs the photo exactly. */
  #serviceImageLightboxModal .lightbox-box img {
    max-width: calc(100vw - 68px);
  }

  #serviceImageLightboxModal .lightbox-caption {
    font-size: clamp(11px, 3.2vw, 13px);
    line-height: 1.35;
  }

  /* ---- Product details modal on phones -------------------------------- */

  #productInfoModal.ux-dlg .modal-box.ux-dlg__card {
    max-height: min(94vh, calc(100dvh - 12px));
  }

  /* `contain` stops a flick inside the sheet from scrolling the catalogue
     behind it once the body reaches its end. */
  #productInfoModal .modal-scroll-area {
    padding: 12px;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  #productInfoModal .modal-img-holder {
    height: auto;
    aspect-ratio: 4 / 3;
  }

  #productInfoModal .modal-desc,
  #productInfoModal .modal-list li,
  #productInfoModal .modal-spec-value {
    overflow-wrap: anywhere;
  }

  /* Deterministic two rows: "Customer Reviews" spans the first, then the
     icon-only cart and "Buy Now" share the second. The flex version wrapped
     into the same shape by luck and re-flowed as soon as the count changed. */
  #productInfoModal .modal-actions {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    flex-wrap: nowrap;
    gap: 8px;
    padding: 12px;
  }

  #productInfoModal .modal-actions .reviews-btn {
    grid-column: 1 / -1;
    margin-right: 0;
  }

  #productInfoModal .modal-actions .modal-btn {
    min-width: 0;
    width: auto;
    min-height: 42px;
    padding: 0 10px;
    gap: 6px;
    white-space: nowrap;
  }

  /* Styled by id: products.js rewrites this button's className on every open. */
  #productInfoModal #productInfoAddToCart {
    width: 46px;
    padding: 0;
    gap: 0;
  }

  /* ---- Customer reviews modal on phones ------------------------------- */

  #customerReviewsModal.ux-dlg .customer-reviews-box.ux-dlg__card {
    max-height: min(94vh, calc(100dvh - 12px));
  }

  /* Same selector as the unconditional rule in main.css that forces wrapping,
     so this wins by load order. The seven chips need ~606px against 298px of
     track at 320px, and three stacked rows ate 144px of the sheet. */
  #customerReviewsModal.ux-dlg .ux-dlg__card > .customer-reviews-filters {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    gap: 6px;
    padding: 10px 14px 12px;
    scroll-snap-type: x proximity;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  #customerReviewsModal .customer-reviews-filters::-webkit-scrollbar {
    display: none;
  }

  #customerReviewsModal .customer-review-filter {
    white-space: nowrap;
    scroll-snap-align: start;
  }

  #customerReviewsModal .customer-reviews-list {
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  #customerReviewsModal .customer-review-card {
    overflow-wrap: anywhere;
  }

  /* ---- Product image lightbox on phones ------------------------------- */

  #imageLightboxModal .lightbox-box {
    max-width: calc(100vw - 44px);
    padding: 12px;
  }

  #imageLightboxModal .lightbox-close-btn {
    top: -12px;
    right: -12px;
  }

  /* main.css sizes lightbox media in viewport units (86vw for images, 92vw for
     video), which ignores the frame; 44px of gutter + 2 x 12px of padding is
     the 68px subtracted here, so the media hugs the white border exactly. */
  #imageLightboxModal .lightbox-box img,
  #imageLightboxModal .lightbox-box video {
    max-width: calc(100vw - 68px);
  }

  #imageLightboxModal .lightbox-box video {
    width: 100%;
    height: auto;
  }

  #imageLightboxModal .lightbox-caption {
    font-size: clamp(11px, 3.2vw, 13px);
    line-height: 1.35;
  }

  /* The checkout/cart sheets are already full-screen scrollers here; keep a
     flick inside them from dragging the catalogue underneath. */
  .products-page-body .shop-modal-body {
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
}

/* The cart control is icon-only at EVERY width, by request: a plus-cart square
   in the card footer and in the details modal, with the wording kept for
   assistive tech and a `title` tooltip for pointer users. Outside the phone
   band on purpose. */
.products-page-body .btn-add-cart .action-btn-label,
#productInfoAddToCart .modal-btn-label {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  clip-path: inset(50%) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

/* Above the phone band: one row of three, with the cart column shrunk to its
   icon. Bounded by a query rather than left at file scope because these rules
   repeat the phone band's selectors and would otherwise win on load order. */
@media (min-width: 721px) {
  .products-page-body .product-actions {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  }

  .products-page-body .product-actions .btn-add-cart {
    width: 44px;
    padding-inline: 0;
    gap: 0;
  }

  /* A flex item here, so it needs `flex: 0 0 auto` to hold its square. */
  #productInfoModal #productInfoAddToCart {
    flex: 0 0 auto;
    width: 52px;
    padding-inline: 0;
    gap: 0;
  }
}

/* A phone held sideways is ~837px wide, so it lands above the band above and
   misses the scroll containment. The height ceiling keeps desktop out. */
@media (max-width: 900px) and (max-height: 520px) {
  .products-page-body .shop-modal-body,
  #productInfoModal .modal-scroll-area,
  #customerReviewsModal .customer-reviews-list {
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
}

/* Services toolbar on phones: the search field and the category box share one
   line that fills the toolbar exactly. Scoped to `.services-page-body` because
   the same `.products-toolbar` markup is reused by the Products page, and the
   floor of 301px is where the two controls stop fitting side by side. */
@media (min-width: 301px) and (max-width: 720px) {
  /* Three classes, so this outranks the legacy `flex-direction: column`
     stacking rule for `.products-toolbar .toolbar-container` in main.css. */
  .services-page-body .products-toolbar .toolbar-container {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: stretch;
    flex-direction: row;
    gap: 8px;
  }

  .services-page-body .toolbar-search {
    min-width: 0;
    max-width: none;
  }

  /* A plain block wrapper: as a flex item the box's `flex-basis: 140px` from
     main.css would override the width below. It stretches to the grid row, and
     the box fills it, so both controls always share the same height. */
  .services-page-body .toolbar-actions {
    display: block;
    width: auto;
    min-width: 0;
  }

  /* Sized so the resting "All Categories" label (116.5px at the 16px iOS-safe
     font) clears the chevron, its padding and the box padding with room to
     spare, while the search field keeps the rest of the row. The longest
     option ellipsises once selected — the native picker is unaffected. */
  .services-page-body .category-dropdown-box {
    width: clamp(160px, 42vw, 182px);
    height: 100%;
    padding: 0 8px 0 12px;
    border-radius: 14px;
  }

  /* The select keeps `width: 100%`: an `auto` width would resolve to the widest
     option and blow the row apart. Removing the OS chrome for a compact
     chevron does not affect the native picker on tap. */
  .services-page-body .category-select {
    width: 100%;
    padding-right: 14px;
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' stroke='%23343b49' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0 center;
    background-size: 9px;
    text-overflow: ellipsis;
  }
}

/* Products toolbar on phones. Three controls cannot share one line here: the
   iOS no-zoom floor (16px) makes the two selects alone need ~267px of a 300px
   container, so the search keeps its own full-width row above them and the two
   selects share one exactly-fitting row. Scoped to this page because the same
   `.products-toolbar` markup is reused by Services, whose band sits above. */
@media (min-width: 301px) and (max-width: 720px) {
  /* Three classes, so this outranks the legacy `flex-direction: column`
     stacking rule for `.products-toolbar .toolbar-container` in main.css. */
  .products-page-body .products-toolbar .toolbar-container {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: stretch;
    flex-direction: row;
    gap: 8px;
  }

  .products-page-body .toolbar-search {
    min-width: 0;
    max-width: none;
  }

  /* 1.25fr : 1fr, because "All Categories" is 116.5px at the 16px iOS-safe font
     and "All Filters" only 78.5px — the split gives 162 / 130 at 320px, so both
     resting labels clear the 9px chevron with room to spare. Two classes, which
     outranks the 1-column grid this page's <=420px band would otherwise use. */
  .products-page-body .toolbar-actions {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    gap: 8px;
    width: auto;
    min-width: 0;
  }

  /* `width: auto` so the box fills its grid track instead of main.css's
     `flex-basis: 140px`, which would push the row past the container. */
  .products-page-body .category-dropdown-box {
    width: auto;
    min-width: 0;
    min-height: 44px;
    padding: 0 8px 0 12px;
    border-radius: 14px;
  }

  /* Same compact chevron as the Services band; the long options ("Price: Low to
     High") ellipsise once selected and the native picker is unaffected. */
  .products-page-body .category-select {
    width: 100%;
    padding-right: 14px;
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' stroke='%23343b49' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0 center;
    background-size: 9px;
    text-overflow: ellipsis;
  }
}

@media (min-width: 721px) and (max-width: 900px) {
  .hero-graphic {
    width: clamp(200px, 28vw, 252px);
  }

  .hero-title {
    font-size: clamp(34px, 4.8vw, 44px) !important;
  }
}

@media (max-width: 300px) {
  .site-header .logo-title,
  .sidebar-logo-container .logo-title {
    font-size: 14px;
  }

  .site-header .logo-subtitle,
  .sidebar-logo-container .logo-subtitle {
    font-size: 9px;
  }

  .hero-buttons {
    grid-template-columns: 1fr;
    width: min(100%, 190px);
  }

  .btn-browse,
  .btn-appointment {
    min-height: 38px;
    padding: 8px 10px;
    font-size: 11px;
  }

  .hero-graphic {
    width: min(48vw, 110px);
  }

  .hero-title {
    font-size: clamp(15px, 8vw, 21px) !important;
  }

  /* Watch-narrow: drop the caption, keep 4 + 4 circles legible. */
  .hero-sdg-strip {
    --sdg-gap: 4px;
    margin-top: 18px;
    width: min(100%, 190px);
  }

  .hero-sdg-caption {
    display: none;
  }

  .hero-sdg-item {
    max-width: 34px;
  }

  .hero-sdg-btn {
    padding: 1.5px;
    border-width: 1px;
  }

  .services-grid,
  .shop-grid {
    gap: 6px !important;
  }

  .services-grid .card-content,
  .product-info {
    padding: 7px !important;
  }

  .service-chip {
    font-size: 7px;
  }

  .service-index {
    display: none;
  }

  .services-grid .details-btn,
  .products-page-body .product-actions .action-btn {
    min-height: 32px;
    height: 32px;
  }

  /* The services button keeps its full-width label; only its height shrinks. */
  .services-grid .details-btn {
    padding: 0 8px;
    font-size: 10px;
  }

  .products-page-body .product-actions {
    gap: 2px;
    padding: 4px;
  }

  .products-page-body .product-actions .action-btn > svg {
    width: 13px;
    height: 13px;
  }
}

/* At watch-sized widths, two cards would be narrower than a single icon.
   Keep the page usable while normal phone widths retain two cards per row. */
@media (max-width: 190px) {
  .site-header .logo-container,
  .sidebar-logo-container {
    gap: 4px;
  }

  .site-header .header-emblem,
  .sidebar-logo-container .header-emblem {
    height: 24px;
    margin-right: 0;
  }

  .site-header .logo-title,
  .sidebar-logo-container .logo-title {
    font-size: 12px;
  }

  .site-header .logo-subtitle,
  .sidebar-logo-container .logo-subtitle {
    font-size: 8px;
  }

  .services-grid,
  .shop-grid {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  .hero-sdg-strip {
    --sdg-gap: 3px;
    margin-top: 12px;
  }

  .hero-sdg-item {
    max-width: 26px;
  }
}

/* Short and square phones get a compact side-by-side hero so the primary
   actions remain visible without making any control smaller than 38px. */
@media (min-width: 320px) and (max-width: 720px) and (max-height: 520px) {
  .hero-section {
    min-height: calc(100dvh - var(--ux-header-h) + var(--hero-tail));
    padding-top: 16px;
    padding-bottom: 22px;
  }

  .hero-container {
    flex-direction: row;
    gap: 14px;
    text-align: left;
  }

  .hero-content-left {
    order: 1;
    flex: 1 1 auto;
    align-items: flex-start;
  }

  .hero-content-right {
    order: 2;
    flex: 0 0 auto;
    width: auto;
    margin: 0;
  }

  .hero-graphic {
    width: min(28vw, 128px);
  }

  .hero-title {
    margin-bottom: 12px;
    font-size: clamp(17px, 4.8vw, 23px) !important;
    text-align: left;
  }

  .hero-buttons {
    width: min(100%, 320px);
  }

  .btn-browse,
  .btn-appointment {
    min-height: 38px;
    padding: 8px;
    font-size: 10.5px;
  }

  .scroll-indicator {
    display: none;
  }
}

/* Landscape phones and small tablets are height-starved (844x390, 900x520):
   keep all 8 badges, lose the caption, and tighten the band so the hero copy
   and CTAs stay as close to the fold as they were before the strip existed.
   Placed after the width-only blocks so it wins where both apply, and gated
   at 320px so ≤300px handsets keep their own smaller circles. */
@media (min-width: 320px) and (max-width: 900px) and (max-height: 520px) {
  .hero-sdg-strip {
    --sdg-gap: 5px;
    margin-top: 16px;
    width: min(100%, 320px);
  }

  .hero-sdg-caption {
    display: none;
  }

  .hero-sdg-item {
    max-width: 40px;
  }
}

/* -------------------------------------------------------------------------
   Compact brand lockup — one straight row reading "UCN-FMRC".
   Declared after every earlier header block so it decides the layout at all
   widths below 901px, in the sticky header and in the cloned sidebar header.
   A single font-size on `.logo-text` drives both halves, so the narrower
   breakpoints no longer need their own pair of sizes: the clamp shrinks the
   whole word together and the row can never break in two.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
  .site-header .logo-text,
  .sidebar-logo-container .logo-text {
    flex-direction: row;
    align-items: baseline;
    flex-wrap: nowrap;
    gap: 0;
    min-width: 0;
    width: auto;
    max-width: none;
    /* STEP 8: 3.2vw → 3.9vw, one step up on real phones (390 → 15.2px, 430 →
       16.8px) where the measured slack beside the lockup was 63-93px. The 11px
       floor is kept, so nothing below ~282px moves and there is no new clipping
       risk at the narrow end. */
    font-size: clamp(11px, 3.9vw, 20px);
    white-space: nowrap;
  }

  .site-header .logo-title,
  .sidebar-logo-container .logo-title,
  .site-header .logo-subtitle,
  .sidebar-logo-container .logo-subtitle {
    display: inline;
    font-size: inherit;
    font-weight: 800;
    line-height: 1;
    letter-spacing: 0.05em;
    color: var(--customer-wine);
    white-space: nowrap;
  }

  /* Joins "UCN" and "FMRC" into the requested single hyphenated word. The
     short spans only exist below 901px, so no hyphen leaks onto desktop. */
  .site-header .logo-title .brand-name-short::after,
  .sidebar-logo-container .logo-title .brand-name-short::after {
    content: "-";
  }
}

/* Dialog gutters follow the viewport. One token drives the shared band, body
   and footer padding of every ux-dlg dialog, so narrow phones and watch-sized
   canvases get tighter margins without per-dialog overrides. */
@media (max-width: 430px) {
  :root {
    --ux-dlg-pad-x: 18px;
  }
}

@media (max-width: 320px) {
  :root {
    --ux-dlg-pad-x: 14px;
  }
}

@media (max-width: 280px) {
  :root {
    --ux-dlg-pad-x: 11px;
  }
}

/* =========================================================================
   PHONES — 480px and under.  iPhone SE (320) through Pro Max (430).

   Everything above this point bands at 900 / 720 / 640 / 480 / 430 / 400 /
   340 / 300 / 280, but almost all of the real compaction sits in the 280px
   block, so the sizes an actual iPhone gets came from the light 900/720
   rules: the hero ran 903px, About 927px, the footer 893px inside an 844px
   screen. This block is the missing middle — the 280px treatment applied at
   a gentler scale so 320-430px reads as a designed phone layout rather than
   a squeezed desktop one. It is last in the last stylesheet, so it settles
   the argument between the earlier layers without needing !important
   (except where an earlier layer used it, or a style attribute has to lose).
   ========================================================================= */
@media (max-width: 480px) {
  /* ---- Hero ------------------------------------------------------------ */
  /* The tail is the slice of hero below the fold that carries the SDG band.
     At 90-170px it left a measured ~169px hole between the badges and the
     scroll cue. Trimming the tail and spending it on the band's own top
     margin moves the badges down into that hole — the requested "a little
     bit below" — and takes ~130px off the hero at the same time. */
  .hero-section {
    --hero-tail: 34px;
  }

  .hero-container {
    gap: 16px;
  }

  .hero-title {
    font-size: clamp(21px, 6.9vw, 29px) !important;
    line-height: 1.22;
  }

  .hero-graphic {
    width: min(52vw, 210px);
  }

  .hero-sdg-strip {
    margin-top: 40px;
    width: 100%;
  }

  /* One centred row instead of the renderer's hard 4 + 4 split: `contents`
     drops the <ul>s out of the box tree so all the badges become children of
     the same wrapping flex row. Five SDGs stop rendering as an off-balance
     4 + 1, and eight still break 4 + 4 on their own. No change to
     renderSdgs() — this is purely how the boxes are laid out. */
  .hero-sdg-rows {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    row-gap: calc(var(--sdg-gap) + 2px);
  }

  .hero-sdg-row {
    display: contents;
  }

  .hero-sdg-item {
    flex: 0 0 auto;
    width: clamp(42px, 12.4vw, 56px);
    max-width: none;
  }

  .hero-sdg-caption {
    margin-top: 12px;
    font-size: 9.5px;
    letter-spacing: 0.1em;
  }

  /* ---- About / Our Vision / Our Mission -------------------------------- */
  /* Every size below is a vw clamp rather than a flat px value on purpose.
     The 340 / 300 / 280 / 190 blocks sit *earlier* in this file, so a flat
     value here would out-rank them and undo their work; a clamp keeps
     shrinking past the end of this band instead of fighting it. The upper
     bound is the 480px value, the lower bound is the floor for 190px. */
  .about-section,
  .vision-section,
  .mission-section {
    padding-block: clamp(16px, 6.7vw, 28px);
  }

  .about-container,
  .vision-container,
  .mission-container {
    padding-block: clamp(8px, 3.6vw, 16px);
    gap: clamp(12px, 4.6vw, 20px);
  }

  /* The 50px bottom margin here stacks on top of the container's own gap,
     so the copy and the video sat ~72px apart on a 390px screen. */
  .about-content-left {
    margin-bottom: 0;
  }

  .section-title {
    font-size: clamp(17px, 5.4vw, 22px);
    line-height: 1.25;
    margin-bottom: clamp(7px, 2.6vw, 12px);
  }

  .section-text {
    font-size: clamp(11.5px, 3.5vw, 13.6px);
    line-height: 1.62;
    margin-bottom: clamp(7px, 2.6vw, 12px);
  }

  .section-text:last-child {
    margin-bottom: 0;
  }

  .vm-title {
    font-size: clamp(16px, 5.1vw, 21px);
    line-height: 1.25;
    margin-bottom: clamp(6px, 2.2vw, 10px);
  }

  .vm-text {
    font-size: clamp(12px, 3.6vw, 14px);
    line-height: 1.6;
  }

  /* Media stops driving section height: the mission blob was a full-width
     1:1 square (302x306 at 390px, a quarter of the screen), and the vision
     photo and About video were free to grow with the column. */
  .blob-wrapper {
    width: min(62vw, 240px);
    margin-inline: auto;
    /* The 1:1 wrapper left ~57px of empty box under a 4:3 photo at 390px.
       Height follows the photo instead. */
    aspect-ratio: auto;
    /* The `margin-bottom: min(7vw, 26px)` that used to sit here was the phone
       twin of main.css's 62px reserve, and both existed only to hold room for
       the two decorative pseudo-element blobs that hung below the wrapper.
       Those were removed by request, so the reserve went with them — on a card
       whose own padding-block is only clamp(8px, 3.6vw, 16px), keeping it would
       have left ~26px of visible dead space under the photo. */
  }

  .mission-img {
    width: 100%;
    height: auto;
    /* A fixed ratio rather than "whatever the admin uploaded": the wrapper is
       the box the whole deck shares, so its height has to be predictable
       whatever shape gets uploaded next. `cover` keeps the organic mask
       filled. Must stay in step with `.vm-deck--mission.has-stack` below. */
    aspect-ratio: 4 / 3;
    object-fit: cover;
  }

  .vision-img,
  .about-video-holder {
    height: auto;
    aspect-ratio: 16 / 10;
    object-fit: cover;
  }

  /* ---- Vision / Mission decks ------------------------------------------ */
  /* A stacked mission deck has to keep the same 4:3 the single photo uses just
     above, or the wrapper goes back to being a square and opens a void under the
     photo. Vision's 16/10 already agrees with .vision-img, so it needs no
     override. */
  .vm-deck--mission.has-stack {
    aspect-ratio: 4 / 3;
  }

  /* The first-paint placeholder needs the same 4/3 for the same reason, and it
     needs it more urgently: at this width `.blob-wrapper` is `aspect-ratio:
     auto` and takes its height from the photo, so a src-less deck has no height
     at all and the grey card would collapse to nothing. */
  .vm-deck--mission.is-loading,
  .vm-deck--mission.is-empty {
    aspect-ratio: 4 / 3;
  }

  /* The fan is pulled in by about a third. At desktop offsets the deepest card
     reached ~12px below a phone-sized deck; at these offsets the 7% scale-down
     eats most of the 10px translate, so the deepest card lands within a few px
     of the deck's own bottom edge and stays inside the card's padding. */
  .vm-deck.has-stack .vm-deck__card[data-slot="1"] {
    transform: translate(-7px, 5px) rotate(-2.4deg) scale(0.96);
  }

  .vm-deck.has-stack .vm-deck__card[data-slot="2"],
  .vm-deck.has-stack .vm-deck__card[data-slot="hidden"],
  .vm-deck--mission.has-stack .vm-deck__card.is-tucking {
    transform: translate(-14px, 10px) rotate(-4.6deg) scale(0.93);
  }

  .vm-deck--vision.has-stack.is-peeking .vm-deck__card[data-slot="1"] {
    transform: translate(-4px, 3px) rotate(-1.3deg) scale(0.985);
  }

  .vm-deck--vision.has-stack.is-peeking .vm-deck__card[data-slot="2"] {
    transform: translate(-10px, 7px) rotate(-3.2deg) scale(0.945);
  }

  /* The lift is the one part of the shuffle that has to shrink on a phone: the
     copy sits directly above the photo here, and the container's gap is only
     clamp(12px, 4.6vw, 20px) — measured 21px of clearance at 375px, from the
     glyph box of the copy's last line down to the photo. A lift raises the card's
     box by `translate + (scale - 1) * height * 0.85` (transform-origin 50% 85%)
     plus about `width * sin(angle) / 2` for the rotation, so on a 174px card this
     rises ~15px: visibly past the deck's own top edge, still inside the gap.
     main.css uses -72px on a desktop, where 48px of card padding is there to
     break out of, and -14px in the 481-768px band. */
  .vm-deck--mission.has-stack .vm-deck__card.is-lifting {
    transform: translateY(-11px) scale(1.015) rotate(-1.2deg);
  }

  .vm-deck__hint {
    margin-top: clamp(9px, 3vw, 14px);
    font-size: 11.5px;
  }

  /* ---- "What We Offer" carousel ---------------------------------------- */
  /* The heading carries an inline margin-bottom: 50px in main.html, so this
     is one of the few places that genuinely needs !important. */
  .services-container .section-title {
    margin-bottom: clamp(14px, 4.8vw, 22px) !important;
  }

  /* The card was text-first on a phone: a 20px title over a 15px paragraph
     filled the whole 252px card and squeezed the photo down to 35px, so the
     card read as a wall of type. Sizing the type down and pinning the image
     holder gives the picture back ~100px and takes ~30px off the card. */
  .landscape-carousel.carousel-wrapper {
    height: clamp(240px, 66vw, 290px);
  }

  .landscape-carousel .carousel-item {
    width: min(76vw, 300px);
    height: clamp(210px, 58vw, 250px);
  }

  .landscape-card .card-img-holder {
    flex: 0 0 auto;
    height: clamp(80px, 25vw, 104px);
  }

  .carousel-item .card-content {
    padding: clamp(9px, 3vw, 13px);
  }

  .carousel-item .card-title {
    font-size: clamp(13px, 4vw, 15.5px);
    line-height: 1.25;
    margin-bottom: clamp(3px, 1.4vw, 6px);
  }

  .carousel-item .card-desc {
    font-size: clamp(11px, 3.3vw, 12.8px);
    line-height: 1.5;
    margin-bottom: 0;
  }

  /* Service copy comes from the API, so its length is not ours to control.
     Clamping the lines is what keeps one wordy service from blowing the
     card out of the wrapper on a 320px screen. */
  .carousel-item .card-title,
  .carousel-item .card-desc {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  .carousel-item .card-title {
    -webkit-line-clamp: 2;
  }

  .carousel-item .card-desc {
    -webkit-line-clamp: 3;
  }

  /* Swipe is the primary gesture on a phone; the arrows stay as a visible
     affordance but stop eating the card's width. */
  .carousel-track {
    touch-action: pan-y;
  }

  .view-all-container {
    margin-top: clamp(14px, 4.6vw, 22px);
  }

  /* ---- Footer ---------------------------------------------------------- */
  /* Scrolling to the bottom of a phone handed you a footer taller than the
     screen (745px against 844px, and 915px against 568px on an SE). The
     two-column grid landed earlier in main.css; this is the type layer that
     goes with it. Nothing is hidden or collapsed behind a tap — every link
     stays on screen, it is the vertical padding and the desktop-scale type
     that shrink. All four customer pages share this stylesheet, so this is
     also the "apply this footer to all pages" half of the request. */
  .site-footer {
    padding-top: clamp(18px, 6.4vw, 26px);
    padding-bottom: calc(clamp(8px, 3vw, 12px) + var(--ux-safe-b, 0px));
  }

  .footer-container {
    gap: clamp(11px, 4.2vw, 17px);
    margin-bottom: clamp(10px, 3.6vw, 15px);
  }

  /* Business Hours and Contact Information take the left column, Quick Links
     the right, where it spans both lower rows. Hours is two short lines, so
     stacking Contact under it in the same column keeps ~90px of dead space out
     of the footer — that void was the single largest block of nothing here.
     Nothing is hidden or collapsed: the same four blocks, packed. The left
     column is the wider of the two because it carries the four-line street
     address; Quick Links only needs room for "Products". */
  .footer-container {
    grid-template-columns: minmax(0, 1.18fr) minmax(0, 0.82fr);
    grid-template-areas:
      "brand brand"
      "hours quick"
      "contact quick";
  }

  .footer-container .footer-col:nth-child(1) {
    grid-area: brand;
  }
  .footer-container .footer-col:nth-child(2) {
    grid-area: quick;
    align-self: start;
  }
  .footer-container .footer-col:nth-child(3) {
    grid-area: hours;
  }
  .footer-container .footer-col:nth-child(4) {
    grid-area: contact;
  }

  .footer-logo-row {
    gap: clamp(6px, 2vw, 9px);
    margin-bottom: clamp(6px, 2.2vw, 10px);
  }

  .footer-logo {
    height: clamp(26px, 8.6vw, 34px);
    width: clamp(26px, 8.6vw, 34px);
  }

  .footer-brand {
    font-size: clamp(14px, 4.4vw, 17px);
  }

  .footer-desc,
  .footer-text,
  .footer-menu a,
  .footer-link,
  .contact-list li {
    font-size: clamp(10.5px, 3.2vw, 12.5px);
    line-height: 1.5;
  }

  .footer-heading {
    font-size: clamp(12.5px, 3.8vw, 14.5px);
    line-height: 1.2;
    margin-bottom: clamp(5px, 2vw, 8px);
    /* The underline hangs off ::after; 11px of clearance is a desktop measure
       and it is paid three times over in a footer this short. */
    padding-bottom: clamp(5px, 2vw, 8px);
  }

  /* 26px keeps the links comfortably tappable while the 9-15px list rhythm
     that came from the desktop layout drops to a phone-scale 4px. */
  .footer-menu li,
  .contact-list li {
    margin-bottom: clamp(2px, 1.2vw, 5px);
  }

  .footer-menu li:last-child,
  .contact-list li:last-child {
    margin-bottom: 0;
  }

  .contact-list li {
    gap: clamp(5px, 1.8vw, 8px);
  }

  .contact-icon {
    width: clamp(13px, 4.2vw, 16px);
    height: clamp(13px, 4.2vw, 16px);
    flex: 0 0 auto;
  }

  .footer-line {
    margin-bottom: clamp(6px, 2.6vw, 11px);
  }

  .footer-bottom {
    padding-bottom: calc(clamp(4px, 2vw, 8px) + var(--ux-safe-b, 0px));
  }

  .footer-bottom p {
    font-size: clamp(9.5px, 2.9vw, 11.5px);
    line-height: 1.35;
  }

  /* ---- Navbar surfaces -------------------------------------------------- */
  /* Header, sidebar, announcement card and My Account already measure inside
     the viewport at 320-430 (the screenshot's "ruins the screen size" was the
     document being 888px wide, fixed in main.css), and every .ux-dlg__card
     already caps at calc(100dvh - 30px) with its body scrolling. The one
     surface with no width ceiling of its own is the profile dropdown, which
     is positioned from the right edge and sized in px. */
  .profile-popup {
    max-width: calc(100vw - 24px);
  }
}

/* -------------------------------------------------------------------------
   Small phones — 360px and under (iPhone SE 320, mini 375 in landscape UI).
   The block above is written in vw clamps so it keeps shrinking on its own;
   these are the few places that needed a second, flatter cut. The footer is
   the reason this block exists: on a 568px-tall SE even the compacted
   two-column footer still fills most of the screen.
   ------------------------------------------------------------------------- */
@media (max-width: 360px) {
  .site-footer {
    padding-top: 14px;
  }

  .footer-container {
    gap: 9px;
  }

  /* 22px is still a usable target for a text link in a list this dense, and
     it is what buys the last ~25px of footer height. */
  .footer-menu a,
  .footer-link {
    min-height: 22px;
    padding-block: 0;
  }

  .hero-section {
    --hero-tail: 26px;
  }

  .hero-sdg-strip {
    margin-top: 30px;
  }
}

/* ---------------------------------------------------------------------------
   Landscape phones (932x430 and friends). The width is wide enough that none
   of the phone width bands above apply, so the footer was still being drawn at
   desktop scale — 56px of top padding and 20px headings — and stood 504px tall
   inside a 430px-tall screen. Same content and still four columns, because the
   width is genuinely there; only the vertical scale comes down.
   Keyed on height, so portrait phones never see it.
   ------------------------------------------------------------------------- */
@media (min-width: 641px) and (max-height: 520px) and (orientation: landscape) {
  .site-footer {
    padding-top: 22px;
    padding-bottom: calc(12px + var(--ux-safe-b, 0px));
  }

  .footer-container {
    gap: 14px 26px;
    margin-bottom: 14px;
  }

  .footer-logo-row {
    gap: 8px;
    margin-bottom: 8px;
  }

  .footer-logo {
    height: 30px;
    width: 30px;
  }

  .footer-brand {
    font-size: 16px;
  }

  .footer-heading {
    font-size: 13.5px;
    margin-bottom: 8px;
    padding-bottom: 7px;
  }

  .footer-desc,
  .footer-text,
  .footer-menu a,
  .footer-link,
  .contact-list li {
    font-size: 12px;
    line-height: 1.5;
  }

  .footer-menu li,
  .contact-list li {
    margin-bottom: 4px;
  }

  .footer-menu li:last-child,
  .contact-list li:last-child {
    margin-bottom: 0;
  }

  .contact-icon {
    width: 15px;
    height: 15px;
  }

  .footer-line {
    margin-bottom: 10px;
  }

  .footer-bottom {
    padding-bottom: calc(6px + var(--ux-safe-b, 0px));
  }

  .footer-bottom p {
    font-size: 11px;
    line-height: 1.35;
  }
}

/* ===========================================================================
   STEP 7 — CONTACT PAGE, ACCOUNT DIALOGS & ORDER DRAWER: PHONE PASS
   ---------------------------------------------------------------------------
   Every rule below is width-gated, so desktop is untouched.

   Dialog rules are scoped to the six Step 7 dialog ids instead of `.ux-dlg`,
   because the appointment dialogs (`#aptPrivacyModal`, `#aptConfirmModal`)
   share the same chrome classes and are deliberately left byte-identical.

   `:is(#a, #b, ...)` counts as a single id, so
   `:is(#ids) .ux-dlg__card .ux-dlg__head > .child` lands on (1,3,0) — the same
   weight as main.css:17217 `:is(.ux-dlg, ...) .ux-dlg__card .ux-dlg__head >
   *:not(...)`. This file loads after main.css, so the tie goes here. Drop
   `.ux-dlg__card` from a head-child selector and it loses the tie instead.

   The `.customer-rating-overlay` sub-sheets (rate, return, cancel, GCash,
   ship-back, discard) are appended to `document.body` with no id at all, so one
   id in main.css outweighs any class chain written here — those overrides use
   `!important`, already the idiom at lines 589-614 above.
   ------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   §1 / §3 — Contact page body, and the My Account details card.
   Gated at 720px, below which main.css has already collapsed `.contact-grid`
   and `.contact-form-grid` to one column (main.css:6662, 6679, 15519).
   ------------------------------------------------------------------------- */
@media (max-width: 720px) {
  /* The icon span is a flex item of the row and carries no `flex-shrink: 0`,
     so an unbreakable address or email token starves it — measured 9.4px and
     7.64px wide against its own 20px artwork. Pin the span, pin the SVG, and
     let the text wrap instead of pushing. */
  .contact-links-list li .contact-link-icon {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    align-items: flex-start;
    justify-content: center;
  }

  .contact-links-list li .contact-link-icon svg {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
  }

  .contact-links-list li .contact-link-text {
    min-width: 0;
    overflow-wrap: anywhere;
  }
  /* Consent row: the checkbox is the smallest hit target on the page at 18px,
     and it sits next to three lines of statute text. 20px plus the maroon
     accent makes the checked state readable without touching the inline
     layout the markup sets. */
  .contact-form-actions .consent-label input[type="checkbox"] {
    width: 20px;
    height: 20px;
    accent-color: var(--customer-wine);
  }

  .contact-form-actions .consent-label {
    line-height: 1.55;
  }

  /* The submit label was drawn at the bottom of its clamp (13.5px) on every
     phone while the dialog buttons next to it sit at 14.5px. Same size, same
     height, same 8px corner, so the page's one primary action matches the
     dialogs. */
  .contact-form-actions .contact-submit-btn {
    min-height: 50px;
    padding: 14px 20px;
    font-size: 14.5px;
    letter-spacing: 0.2px;
    border-radius: var(--apt-radius, 8px);
  }

  /* ---- §3 My Account details card ---------------------------------------
     The reported right-edge overlap. `.profile-detail-item` is a flex row with
     `justify-content: space-between` and no `min-width: 0` on either span, so
     the unbreakable email in `.detail-val` gives the row a 496px min-content
     contribution; the `1fr` track of `.profile-details-grid` takes that as its
     automatic minimum and every row overhangs a 362px card by ~192px, clipped
     rather than scrollable because `.ux-dlg__card` is `overflow: hidden`.
     Stacking the row into a single `minmax(0, 1fr)` column removes the
     contribution entirely, and `overflow-wrap: anywhere` breaks the token. */
  #customerProfileModal .customer-card .profile-detail-item {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 3px;
    align-items: start;
    padding: 11px 13px;
    /* Follows the desktop row, which the home-page round took from 14px to
       `--apt-radius-sm`. */
    border-radius: var(--apt-radius-sm);
  }

  #customerProfileModal .customer-card .detail-label {
    min-width: 0;
    font-size: 10px;
    line-height: 1.3;
  }

  #customerProfileModal .customer-card .detail-val {
    min-width: 0;
    font-size: 13.5px;
    line-height: 1.45;
    overflow-wrap: anywhere;
  }
  /* Same untamed email one row up: `.user-avatar-meta` is a flex column with no
     `min-width: 0`, so it measured 401.8px inside the same card. */
  #customerProfileModal .customer-card .profile-header-avatar {
    display: flex;
    align-items: center;
    gap: 13px;
    padding-bottom: 14px;
    margin-bottom: 14px;
  }

  #customerProfileModal .customer-card .user-avatar-initial {
    width: 52px;
    height: 52px;
    font-size: 22px;
    border-width: 2px;
  }

  #customerProfileModal .customer-card .user-avatar-meta {
    min-width: 0;
  }

  #customerProfileModal .customer-card .user-meta-name {
    font-size: 17px;
    line-height: 1.25;
    overflow-wrap: anywhere;
  }

  #customerProfileModal .customer-card .user-meta-email {
    font-size: 12.8px;
    line-height: 1.35;
    overflow-wrap: anywhere;
  }
}

/* ---------------------------------------------------------------------------
   §2 — Shared dialog chrome for the Step 7 dialogs.
   The maroon band was measuring 88.8px, 102.4px and 123.5px tall on a 667px
   screen before a single line of content, and the footer pills were 51px tall
   with 30px of strip padding around them. A tighter vertical rhythm, a 36px
   badge instead of 44px and a 52px close-lane instead of 64px hand the copy
   column ~30px of width and each card ~35px of height, without changing a
   single colour, radius or shadow.
   ------------------------------------------------------------------------- */
@media (max-width: 480px) {
  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__head {
    padding-top: 13px;
    padding-bottom: 13px;
    padding-right: max(52px, var(--ux-dlg-pad-x));
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__badge {
    width: 36px;
    height: 36px;
    margin-right: 11px;
    border-width: 1.5px;
    font-size: 15.5px;
    box-shadow: 0 5px 12px rgba(45, 12, 12, 0.2);
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__eyebrow {
    margin-bottom: 2px;
    font-size: 9.6px;
    letter-spacing: 0.11em;
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__title {
    font-size: clamp(15.5px, 4.2vw, 18.5px);
    line-height: 1.22;
    overflow-wrap: anywhere;
  }

  /* The decorative ring is sized for a 44px badge; scaled down it stays a
     corner arc instead of a wash across the shorter band. */
  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__head::after {
    right: -30px;
    bottom: -88px;
    width: 138px;
    height: 138px;
    box-shadow: 0 0 0 20px rgba(241, 237, 18, 0.055);
  }
  /* Pulled into the corner so the reserved lane can shrink from 64px to 52px.
     The 36px box is kept: it is the whole hit target. */
  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__close {
    top: 10px;
    right: 10px;
  }

  /* Scroll containment: without it a flick that reaches the end of the body
     hands the gesture to the page behind the scrim, which then scrolls under
     the open dialog. */
  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__body {
    padding-top: 18px;
    padding-bottom: 16px;
    overscroll-behavior: contain;
  }

  /* -- Footer strip and pills --------------------------------------------- */
  /* 16px + 18px of strip padding around a 51px pill put the system pop-up's
     footer at 117px, and 20px of pill side-padding wrapped "Got it, thanks"
     onto a second line — an 82px-tall button. 13px padding, a 46px pill and a
     13.6px label keep every label on one line and stay above the 44px tap
     floor. */
  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__foot {
    gap: 8px;
    padding-top: 12px;
    padding-bottom: max(14px, env(safe-area-inset-bottom));
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__btn {
    gap: 6px;
    padding: 12px 13px;
    min-height: 46px;
    font-size: 13.6px;
    line-height: 1.2;
    letter-spacing: 0.1px;
  }

  /* -- §5 System pop-up ---------------------------------------------------
     The one dialog built without a close X (main.js:161-188), so the 52px lane
     the shared rule reserves is dead space. Giving it back widens the title
     column by ~34px, which is what stopped "Message Sent Successfully" from
     wrapping to three lines. */
  #customerSystemPopup .admin-system-popup__card .ux-dlg__head {
    padding-right: var(--ux-dlg-pad-x);
  }
  /* -- §4 Account security (change / set password) ------------------------
     The Back pill sits in the close button's slot, so the band reserves 104px
     for it (main.css:18008). On a 292px card that is more than a third of the
     width. A shorter pill needs an 86px lane. */
  #customerPasswordModal .customer-modal.ux-dlg__card .ux-dlg__head {
    padding-right: max(90px, var(--ux-dlg-pad-x));
  }

  #customerPasswordModal .customer-modal.ux-dlg__card .ux-dlg__back {
    top: 10px;
    right: 10px;
    height: 36px;
    min-height: 36px;
    padding: 0 11px 0 9px;
    font-size: 11px;
  }

  /* The eye toggle was a bare 20px icon with no box. 40px square clears the
     44px-ish floor once the 8px of surrounding pill padding is counted, and the
     input reserves the room so masked text never runs under it. */
  #customerPasswordModal #changePasswordForm .password-wrapper input {
    min-height: 46px;
    padding-right: 50px;
    /* This rule is (2,3,1), so it has to restate the radius or it would undo it
       on every phone. Followed the field look from 18px down to
       `--apt-radius` in the home-page round; the two must move together. */
    border-radius: var(--apt-radius);
  }

  #customerPasswordModal #changePasswordForm .toggle-pass {
    right: 7px;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: var(--apt-radius-sm);
  }

  #customerPasswordModal #changePasswordForm .customer-field {
    margin-bottom: 14px;
  }

  #customerPasswordModal #changePasswordForm .customer-field label {
    margin-bottom: 6px;
    font-size: 12.5px;
  }

  /* -- §6 Guest access dialog ---------------------------------------------
     "Login" and "Sign Up" are short enough to sit side by side, which takes the
     footer from 147px (47% of the card) down to ~72px. */
  #guestAccessModal .guest-access-card.ux-dlg__card .ux-dlg__foot {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
  /* The signed-out dropdown runs 9.28px-12.48px throughout — the smallest type
     on the phone site. Scoped through its own id so the class-based rules in
     main.css cannot put the old sizes back. */
  #guestProfilePopup.guest-profile-popup {
    padding: 15px;
  }

  /* The header bleeds to the card edge with a negative margin sized to the old
     18px gutter, so it has to be re-cut whenever the gutter changes — measured
     3px of it painting outside the rounded corners once the padding dropped. */
  #guestProfilePopup .guest-popup-header {
    margin: -15px -15px 12px;
    padding: 15px;
  }

  #guestProfilePopup .guest-popup-eyebrow {
    font-size: 10px;
    letter-spacing: 0.1em;
  }

  #guestProfilePopup .guest-popup-copy {
    margin: 0 0 11px;
    font-size: 13px;
    line-height: 1.5;
  }

  #guestProfilePopup .guest-popup-benefits {
    gap: 7px;
    margin-bottom: 12px;
  }

  #guestProfilePopup .guest-popup-benefits span {
    padding: 8px;
    font-size: 11.5px;
    line-height: 1.3;
  }

  #guestProfilePopup .guest-popup-benefits i {
    font-size: 11.5px;
  }

  #guestProfilePopup .guest-auth-btn {
    min-height: 46px;
    padding: 0 14px;
    font-size: 13.5px;
  }

  #guestProfilePopup .guest-auth-separator {
    font-size: 10.5px;
  }

  /* -- §7 Announcement modal ----------------------------------------------
     Its runtime stylesheet is appended to <head> after this file, so only
     specificity can beat it: the id chain here is (1,3,0) against that sheet's
     (0,1,0). The counter is the footer grid's first item, so it already lands
     on its own row — centring it and pulling the gap in keeps the two visible
     buttons as the bottom of the card. */
  /* main.css also carries its own `#announcementModal.ux-dlg .ux-dlg__card
     .ux-dlg__foot` (1,3,0), which outranks the six-id foot rule above at
     (1,2,0) and puts the 10px desktop gap back. Naming the card class here
     ties that specificity and wins on load order. Between 421 and 480 this is
     the only thing setting the gap; at 420 and under the runtime sheet's
     `gap: 8px !important` already agrees, so the two never disagree. */
  #announcementModal .announcement-modal__card.ux-dlg__card .ux-dlg__foot {
    gap: 8px;
  }

  #announcementModal .announcement-modal__card .ux-dlg__foot .announcement-modal__counter {
    margin-bottom: 1px;
    font-size: 11.5px;
    text-align: center;
    /* The announcements sheet switches this foot to a one-column grid under
       420px. Stretching the counter across that column is what makes the
       centred text actually read as centred; the property is inert in the
       flex layout that still applies between 421 and 480. */
    justify-self: stretch;
  }
  /* -- §8 My Orders drawer: the head -------------------------------------
     Measured 154.1px tall in portrait, and 139.2px plus a 50px tab strip in
     landscape — 189px of a 393px viewport, leaving a 153.8px panel. The head is
     a two-column grid of five loose children (close, badge, eyebrow, title,
     subtitle, sync line), each stacking its own row. Dropping the decorative
     subtitle and lifting the live-sync chip onto the title's row turns three
     copy rows into two: ~76px instead of 154px, with nothing removed from the
     DOM and no JS touched. */
  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head {
    grid-template-columns: auto minmax(0, 1fr) auto;
    column-gap: 9px;
  }

  /* The badge carries the column-1 gap as its own margin in main.css; now that
     the head has a real `column-gap`, most of that margin has to come off or
     the badge sits 20px from the copy. */
  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head .ux-dlg__badge {
    margin-right: 2px;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head > .ux-dlg__eyebrow {
    grid-column: 2 / -1;
    grid-row: 1;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head > .customer-orders-title {
    grid-column: 2;
    grid-row: 2;
    align-self: center;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head > .customer-orders-subtitle {
    display: none;
  }

  /* Capped rather than truncated: the longest state string is "Showing saved
     orders - reconnecting...", and `aria-live` announces it either way, so the
     chip wraps inside its 138px lane instead of hiding the tail behind an
     ellipsis. Two 10px lines still fit inside the 36px badge row, so the head
     does not grow. */
  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head > .customer-orders-sync-status {
    grid-column: 3;
    grid-row: 2;
    align-self: center;
    justify-self: end;
    max-width: 138px;
    margin: 0;
    padding: 4px 9px;
    gap: 5px;
    font-size: 10px;
    line-height: 1.3;
    text-align: left;
  }

  #customerOrdersModal .customer-orders-head .customer-orders-sync-dot {
    flex: 0 0 auto;
    width: 6px;
    height: 6px;
    box-shadow: 0 0 0 2px rgba(241, 237, 18, 0.2);
  }
  /* Tab strip and viewport: the head gave back ~78px, so the gaps around the
     strip come in to hand that height to the panel rather than to whitespace. */
  #customerOrdersModal .customer-orders-modal.ux-dlg__card > .customer-orders-tabs {
    margin-top: 11px;
    padding: 4px;
    gap: 4px;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card > .customer-orders-tabs .customer-orders-tab {
    min-height: 40px;
    padding: 8px 10px;
    font-size: 12.4px;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card > .customer-orders-viewport {
    margin-top: 10px;
    margin-bottom: max(12px, env(safe-area-inset-bottom));
  }

  #customerOrdersModal .customer-orders-panel {
    padding: 2px;
    gap: 10px;
    overscroll-behavior-y: contain;
  }

  /* Order card actions: the ≤480 block in main.css (12482) grids them two-up but
     leaves each button its own padding and label size, so a row could hold a
     42px-tall 11.52px "View Details" next to a 34px-tall 13.12px "Order
     Received". One height, one label size, one radius for every action. */
  #customerOrdersModal .customer-order-card > .customer-order-actions,
  #customerOrdersModal .customer-return-detail-actions {
    gap: 7px;
    padding-top: 9px;
  }

  #customerOrdersModal .customer-order-card > .customer-order-actions > button,
  #customerOrdersModal .customer-order-card > .customer-order-actions > a,
  #customerOrdersModal .customer-return-detail-actions > button {
    min-height: 40px;
    padding: 8px 9px;
    border-radius: 10px;
    font-size: 12.4px;
    font-weight: 700;
    line-height: 1.2;
  }
  /* -- §9 Order detail sub-card -------------------------------------------
     main.css:9322 collapses the summary to one column for everything under
     900px, so three 54px chips ate 182px of the sheet before the timeline. The
     chips hold four to twelve characters each; two-up is the right density on a
     phone, with a lone third chip spanning the row. */
  #customerOrdersModal .customer-order-detail-modal .customer-order-detail-summary {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
  }

  #customerOrdersModal .customer-order-detail-modal .customer-order-detail-summary > .customer-order-detail-chip {
    min-width: 0;
    padding: 8px 10px;
  }

  #customerOrdersModal .customer-order-detail-modal .customer-order-detail-summary > .customer-order-detail-chip:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  #customerOrdersModal .customer-order-detail-modal.ux-dlg__card > .customer-order-detail-content {
    padding-top: 15px;
    padding-bottom: max(18px, env(safe-area-inset-bottom));
    overscroll-behavior: contain;
  }

  /* -- §10 Order sub-sheets ------------------------------------------------
     Rate, Return request, Cancel order, GCash payment, Ship back and the
     discard prompt are appended straight to `document.body` with no id, so one
     id anywhere in main.css outweighs any class chain written here. `!important`
     is the only lever, and it is already this file's idiom at lines 589-614. */
  .customer-rating-overlay .customer-rating-card.ux-dlg__card > .customer-rating-head {
    padding-top: 13px !important;
    padding-bottom: 13px !important;
    padding-right: max(52px, var(--ux-dlg-pad-x)) !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card > .ux-dlg__head > .ux-dlg__close {
    top: 10px !important;
    right: 10px !important;
  }

  /* The eyebrow and title of these six sheets sit inside an anonymous wrapper
     div rather than as loose head children, so the wrapper is the grid item and
     the type has to be reached through it. */
  .customer-rating-overlay .customer-rating-card.ux-dlg__card .ux-dlg__head .ux-dlg__title {
    font-size: clamp(15.5px, 4.2vw, 18.5px) !important;
    line-height: 1.22 !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card .ux-dlg__head .ux-dlg__eyebrow {
    margin-bottom: 2px !important;
    font-size: 9.6px !important;
  }
  .customer-rating-overlay .customer-rating-card.ux-dlg__card .ux-dlg__badge {
    width: 36px !important;
    height: 36px !important;
    margin-right: 11px !important;
    font-size: 15.5px !important;
  }

  .customer-rating-overlay {
    padding: 8px;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card > .customer-rating-body {
    padding-top: 16px !important;
    padding-bottom: 14px !important;
    padding-left: var(--ux-dlg-pad-x) !important;
    padding-right: var(--ux-dlg-pad-x) !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card > .ux-dlg__foot {
    gap: 8px !important;
    padding-top: 12px !important;
    padding-bottom: max(14px, env(safe-area-inset-bottom)) !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card .ux-dlg__btn {
    gap: 6px !important;
    padding: 12px 13px !important;
    min-height: 46px !important;
    font-size: 13.6px !important;
    line-height: 1.2 !important;
  }

  /* Rating stars are the sheet's primary control: 2rem glyphs with 1px of side
     padding gave a 32px hit box on a 34px pitch. 30px boxes on a 38px pitch keep
     five of them inside a 292px card and stay tappable. */
  .customer-rating-overlay .customer-rating-item .rating-star-large,
  .customer-rating-overlay .customer-rating-stars .rating-star-large {
    padding: 2px 4px !important;
    font-size: 1.85rem !important;
    line-height: 1 !important;
  }

  /* iOS zooms the viewport on focus for any control under 16px. These four were
     the last violations on the customer site: 13.12px on the return reason
     select, 13.6px and 12.8px on the two feedback textareas. */
  .customer-rating-overlay .customer-return-select,
  .customer-rating-overlay .customer-rating-feedback,
  .customer-rating-overlay .customer-rating-item .customer-rating-feedback,
  .customer-rating-overlay .customer-return-input {
    font-size: 16px !important;
  }

  .customer-rating-overlay .customer-return-select {
    min-height: 46px !important;
    padding: 11px 12px !important;
  }
  /* The quantity stepper on the return sheet was a pair of 24px buttons — the
     smallest touch target in any dialog. */
  .customer-rating-overlay .customer-return-qty {
    padding: 3px !important;
    gap: 3px !important;
  }

  .customer-rating-overlay .customer-return-qty button {
    width: 32px !important;
    height: 32px !important;
    font-size: 15px !important;
  }

  .customer-rating-overlay .customer-return-qty span {
    min-width: 26px !important;
    font-size: 13px !important;
  }

  /* Cancellation reasons are radio rows: 12.16px labels beside a 17px mark, in
     rows short enough that two of them fell inside one thumb. */
  .customer-rating-overlay .ccx-reason {
    min-height: 46px !important;
    padding: 11px 12px !important;
  }

  .customer-rating-overlay .ccx-reason-mark {
    flex: 0 0 auto !important;
    width: 20px !important;
    height: 20px !important;
  }

  .customer-rating-overlay .ccx-reason-label {
    font-size: 13px !important;
    line-height: 1.4 !important;
  }

  /* GCash sheet: the reference amount and its copy control share a wrapping
     row, so the 0.68rem button lost its tap height whenever the amount grew. */
  .customer-rating-overlay .cgc-amount-value {
    font-size: 1.35rem !important;
  }

  .customer-rating-overlay .cgc-copy-btn {
    min-height: 40px !important;
    padding: 8px 14px !important;
    font-size: 12px !important;
  }

  .customer-rating-overlay .cgc-file-input {
    padding: 11px 12px !important;
    font-size: 13px !important;
  }

  /* Rating list gutters: 24px of side padding inside a body that already has
     `--ux-dlg-pad-x` of its own left a 292px card with 62px of margin per side. */
  .customer-rating-overlay .customer-rating-items {
    padding: 8px 14px 14px !important;
  }

  .customer-rating-overlay .customer-rating-item {
    padding: 12px !important;
  }

  .customer-rating-overlay .customer-rating-product-name {
    padding: 10px 14px 4px !important;
    font-size: 13px !important;
  }
  /* To Rate and My Ratings cards are flex rows: thumb, a `flex: 1; min-width: 0`
     main column, and a `flex-shrink: 0` price/action strip. Once the strip's
     "Rate products" pill and the price stack up, the main column is starved to
     almost nothing. Same grid main.css already gives `.customer-order-card`
     under 900px: thumb and copy on row one, the strip across row two. */
  #customerOrdersModal .customer-torate-card,
  #customerOrdersModal .customer-rated-card {
    display: grid;
    grid-template-columns: 64px minmax(0, 1fr);
    align-items: start;
    gap: 10px;
    padding: 10px;
  }

  #customerOrdersModal .customer-torate-card > .customer-order-thumb,
  #customerOrdersModal .customer-rated-card > .customer-order-thumb {
    grid-column: 1;
  }

  #customerOrdersModal .customer-torate-main,
  #customerOrdersModal .customer-rated-main {
    grid-column: 2;
    min-width: 0;
  }

  #customerOrdersModal .customer-torate-side,
  #customerOrdersModal .customer-rated-side {
    grid-column: 1 / -1;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding-top: 8px;
    border-top: 1px dashed #e2e8f0;
  }

  #customerOrdersModal .customer-torate-side .customer-order-rate-btn {
    min-height: 40px;
    padding: 8px 14px;
    border-radius: 10px;
    font-size: 12.4px;
  }
}

/* ---------------------------------------------------------------------------
   Narrow phones (iPhone SE 1st gen at 320px, and the 360px Android floor).
   A 1fr/1.25fr confirm footer gives the primary pill about 116px of inner
   width here, which wraps "Confirm Cancellation" and "Submit Return Request"
   onto three lines. Stacking is the honest answer, primary on top so the
   affirmative action keeps the position the thumb lands on.
   ------------------------------------------------------------------------- */
@media (max-width: 360px) {
  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__foot.is-confirm {
    grid-template-columns: minmax(0, 1fr);
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__foot.is-confirm > .ux-dlg__btn--primary {
    order: -1;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card > .ux-dlg__foot.is-confirm {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card > .ux-dlg__foot.is-confirm > .ux-dlg__btn--primary {
    order: -1 !important;
  }

  /* "Login" and "Sign Up" still fit two-up at 360px; below that the pair is
     narrower than the labels, so the guest footer goes back to a stack. */
  #guestAccessModal .guest-access-card.ux-dlg__card .ux-dlg__foot {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The sync chip's lane comes in with the card so the title keeps one line. */
  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head > .customer-orders-sync-status {
    max-width: 104px;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card > .customer-orders-tabs .customer-orders-tab {
    padding: 8px;
    font-size: 12px;
  }

  .customer-rating-overlay .customer-rating-items {
    padding: 6px 10px 12px !important;
  }

  .customer-rating-overlay .customer-rating-item {
    padding: 10px !important;
  }

  .customer-rating-overlay .customer-rating-item .rating-star-large,
  .customer-rating-overlay .customer-rating-stars .rating-star-large {
    padding: 2px 2px !important;
    font-size: 1.65rem !important;
  }
}

/* ---------------------------------------------------------------------------
   §11 — Landscape phones. 852x393 is wider than every width band above, so the
   dialogs were still drawn at full portrait scale: the My Orders head measured
   139.2px and the tab strip 50px, which is 189px of a 393px viewport and left
   the panel 153.8px to scroll orders in. Only vertical scale changes here; the
   width is genuinely there, so gutters and columns are left alone.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) and (max-height: 520px) and (orientation: landscape) {
  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card {
    max-height: calc(100dvh - 12px);
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__head {
    padding-top: 9px;
    padding-bottom: 9px;
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__badge {
    width: 32px;
    height: 32px;
    margin-right: 10px;
    font-size: 14px;
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__eyebrow {
    margin-bottom: 1px;
    font-size: 9.5px;
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__title {
    font-size: 16px;
    line-height: 1.2;
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__close {
    top: 8px;
    right: 8px;
    width: 32px;
    height: 32px;
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__body {
    padding-top: 12px;
    padding-bottom: 12px;
    overscroll-behavior: contain;
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__foot {
    gap: 8px;
    padding-top: 9px;
    padding-bottom: max(9px, env(safe-area-inset-bottom));
  }

  :is(#customerProfileModal, #customerPasswordModal, #customerOrdersModal, #customerSystemPopup, #guestAccessModal, #announcementModal) .ux-dlg__card .ux-dlg__btn {
    padding: 10px 16px;
    min-height: 42px;
    font-size: 13.5px;
  }

  /* Same specificity tie-break as the ≤480 band: main.css keeps an
     announcement-only foot rule at (1,3,0), so the shared (1,2,0) gap above
     never reaches this one card. */
  #announcementModal .announcement-modal__card.ux-dlg__card .ux-dlg__foot {
    gap: 8px;
  }
  /* My Orders: same three-column head as the ≤480 band, so the sync chip sits
     beside the title instead of consuming a fourth row of height. */
  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head {
    grid-template-columns: auto minmax(0, 1fr) auto;
    column-gap: 10px;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head .ux-dlg__badge {
    margin-right: 2px;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head > .ux-dlg__eyebrow {
    grid-column: 2 / -1;
    grid-row: 1;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head > .customer-orders-title {
    grid-column: 2;
    grid-row: 2;
    align-self: center;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head > .customer-orders-subtitle {
    display: none;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-head > .customer-orders-sync-status {
    grid-column: 3;
    grid-row: 2;
    align-self: center;
    justify-self: end;
    max-width: 210px;
    margin: 0;
    padding: 4px 9px;
    gap: 5px;
    font-size: 10px;
    line-height: 1.3;
    text-align: left;
  }

  #customerOrdersModal .customer-orders-head .customer-orders-sync-dot {
    flex: 0 0 auto;
    width: 6px;
    height: 6px;
  }
  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-tabs {
    margin-top: 8px;
    padding: 3px;
    gap: 4px;
  }

  /* main.css reaches this button through `#customerOrdersModal.ux-dlg
     .ux-dlg__card > .customer-orders-tabs .customer-orders-tab` (1,4,0), so the
     strip has to be named in the chain here as well — a card-then-tab selector
     is only (1,3,0) and silently loses the 34px row back to the 38px default,
     which is 4px of head the landscape band cannot spare. */
  #customerOrdersModal .customer-orders-modal.ux-dlg__card > .customer-orders-tabs .customer-orders-tab {
    min-height: 34px;
    padding: 6px 12px;
    font-size: 12.4px;
  }

  #customerOrdersModal .customer-orders-modal.ux-dlg__card .customer-orders-viewport {
    margin-top: 8px;
    margin-bottom: max(8px, env(safe-area-inset-bottom));
  }

  #customerOrdersModal .customer-orders-panel {
    gap: 10px;
    overscroll-behavior-y: contain;
  }

  #customerOrdersModal .customer-order-detail-modal.ux-dlg__card > .customer-order-detail-content {
    padding-top: 12px;
    padding-bottom: max(12px, env(safe-area-inset-bottom));
    overscroll-behavior: contain;
  }
  /* Rating / return / cancel / GCash sub-sheets. These are appended to
     document.body with no id, so main.css reaches them through its
     id-weighted :is() list and only !important can win. */
  .customer-rating-overlay {
    padding: 6px !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card {
    max-height: calc(100dvh - 12px) !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card .ux-dlg__head {
    padding-top: 9px !important;
    padding-bottom: 9px !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card .ux-dlg__title {
    font-size: 16px !important;
    line-height: 1.2 !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card .ux-dlg__badge {
    width: 32px !important;
    height: 32px !important;
    margin-right: 10px !important;
    font-size: 14px !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card .ux-dlg__close {
    top: 8px !important;
    right: 8px !important;
    width: 32px !important;
    height: 32px !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card > .ux-dlg__foot {
    padding-top: 9px !important;
    padding-bottom: max(9px, env(safe-area-inset-bottom)) !important;
  }

  .customer-rating-overlay .customer-rating-card.ux-dlg__card > .ux-dlg__foot .ux-dlg__btn {
    padding: 10px 16px !important;
    min-height: 42px !important;
    font-size: 13.5px !important;
  }

  .customer-rating-overlay .customer-rating-item .rating-star-large,
  .customer-rating-overlay .customer-rating-stars .rating-star-large {
    font-size: 1.6rem !important;
  }
}

/* ===========================================================================
   STEP 8 — ONE FIELD LOOK, TIP-CARD FIT, CONTACT TYPE, BRAND LOCKUP
   ---------------------------------------------------------------------------
   §1 is deliberately NOT width-gated: the field look was asked for "in all
   sizes". Neither is the Account Tip card itself — but its own styling now lives
   in main.css, and what is left in §2 here is only the two narrow bands where
   344px genuinely does not fit. §3 and §4 stay width-gated.

   §1 reuses the token set that `.c-input` (main.css:3974), `.contact-input`
   (main.css:6451) and `.payment-select` (main.css:3226) already share, so the
   fields that were already right do not move a pixel. The values are copied
   verbatim rather than re-derived:

     rest   border 1px solid rgba(92,43,38,.14) · radius 18px
            background rgba(255,254,250,.86)
            shadow inset 0 1px 0 rgba(255,255,255,.9), 0 8px 18px rgba(72,27,22,.04)
     focus  border-color rgba(127,17,17,.64) · background #fff
            shadow 0 0 0 4px rgba(158,20,20,.08), 0 14px 28px rgba(72,27,22,.09)

   Never declare `font-size` on a text control in this section: main.css:14849
   pins every one of them to `max(16px, 0.95rem)` so iOS Safari cannot auto-zoom
   on focus, and an equal-weight `font-size` here would silently undo it.
   ------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   §1a — The controls that never got the portal field look.
   This file loads after main.css, so an equal-weight selector wins the tie;
   where main.css is heavier the chain is lengthened rather than reaching for
   `!important`.
   ------------------------------------------------------------------------- */

/* The two entries below are the Set / Change Password fields, and they are the
   only ones in §1a that the home-page minimalism round moves. `.customer-field`
   appears in exactly two places in the whole site — the Google "Create
   Password" card and the Change Password modal (main.js:7650 and :7691) — both
   of which open out of My Account, which the owner named. So retargeting them
   cannot touch the contact form, checkout or the address phone field; those
   keep the portal look documented in the §1 banner until their own round.

   They were the last customer-dialog controls still wearing it: an 18px radius,
   a translucent `rgba(255,254,250,.86)` fill, an inset white top line and an
   `0 8px 18px` bloom, growing to `0 14px 28px` on focus. main.css:9935 and
   :10064 were already rewritten to the minimalism recipe this round, but this
   file loads after it and these selectors are equal or heavier, so the old look
   kept winning inside the modal. Rather than delete the block — main.css:9721
   and :9848 shipped cold blue-grey hairlines, which is what §1 was written to
   fix, and a future edit there must not be able to bring them back — the
   declarations are restated on the new values.

   Focus is a 3px ring and nothing else. The `0 14px 28px` bloom is the same
   "lift" the owner ruled out for buttons; a field that swells when tabbed into
   is the same gesture in another place. */
.customer-field input {
  background: var(--customer-paper);
  border: 1px solid var(--apt-line);
  border-radius: var(--apt-radius);
  box-shadow: none;
  /* `border-color`, `background-color` and `box-shadow` by name, not `all`: a
     bare `all` here would also animate the focus ring's spread, and on a text
     control that reads as a wobble rather than a state change. */
  transition: border-color 0.2s ease, background-color 0.2s ease,
    box-shadow 0.2s ease;
}

.customer-field input:focus {
  outline: none;
  border-color: var(--apt-danger);
  background: var(--customer-paper);
  box-shadow: 0 0 0 3px rgba(176, 28, 28, 0.12);
}

/* 48px of right padding still clears the toggle (28px wide at `right: 12px`);
   the extra 4px over main.css:10064's 44px is kept because this modal's inputs
   are taller than the ones that rule was written for. */
.customer-field .password-wrapper input {
  padding: 12px 48px 12px 14px;
  background: var(--customer-paper);
  border: 1px solid var(--apt-line);
  border-radius: var(--apt-radius);
  box-shadow: none;
  transition: border-color 0.2s ease, background-color 0.2s ease,
    box-shadow 0.2s ease;
}

.customer-field .password-wrapper input:focus {
  outline: none;
  border-color: var(--apt-danger);
  background: var(--customer-paper);
  box-shadow: 0 0 0 3px rgba(176, 28, 28, 0.12);
}

/* Checkout / address phone field. main.css:4088 was #d9d9d9 at radius 8 with no
   focus state at all. The group owns the edge — main.css:4110 strips its
   `.c-input` child to `border: none; border-radius: 0` — so the focus ring goes
   on the group. `border-color` (not `border-right-color`) on the prefix because
   the ≤280 band at line 1000 swaps that divider to a `border-bottom`. */
.phone-input-group {
  background: var(--customer-paper);
  border: 1px solid var(--apt-line);
  border-radius: var(--apt-radius);
  box-shadow: none;
  transition: border-color 0.2s ease, background-color 0.2s ease,
    box-shadow 0.2s ease;
}

/* Same focus contract as the fields above it: one 3px ring, no bloom, no radius
   of its own. The 18px radius and the `0 14px 28px` lift this rule used to carry
   were the only two places in the profile forms still speaking the old
   language. */
.phone-input-group:focus-within {
  border-color: var(--apt-danger);
  background: var(--customer-paper);
  box-shadow: 0 0 0 3px rgba(176, 28, 28, 0.12);
}

.phone-prefix {
  border-color: var(--apt-line);
}

/* The inner field must not paint its own surface or halo: the group is
   `overflow: hidden`, so a child shadow is clipped into a hard rectangle. */
.phone-input-group .c-input,
.phone-input-group .c-input:focus {
  background: transparent;
  box-shadow: none;
}

/* Quantity steppers — product card, product page, checkout line items and the
   return-request rows. All had an off-token edge and no focus state. The radius
   is left as authored: 18px on a 32px stepper reads as a pill, not a field. */
.qty-selector {
  border-color: rgba(107, 32, 43, 0.14);
}

.qty-selector:focus-within {
  border-color: rgba(107, 32, 43, 0.64);
  box-shadow: 0 0 0 3px rgba(158, 20, 20, 0.08);
}

.qty-selector input {
  border-color: rgba(107, 32, 43, 0.12);
}

.customer-return-qty {
  border-color: rgba(107, 32, 43, 0.14);
}

.customer-return-qty:focus-within {
  border-color: rgba(107, 32, 43, 0.64);
  box-shadow: 0 0 0 3px rgba(158, 20, 20, 0.08);
}

/* Return / cancellation / GCash reference fields (main.css:11745, 11623 — plus
   `.cgc-ref-input` and `.ccx-detail-input`, which are modifiers on the same
   bases) sat one shade off the token at radius 10. */
.customer-return-input,
.customer-return-select {
  background: rgba(255, 254, 250, 0.86);
  border: 1px solid rgba(107, 32, 43, 0.14);
  border-radius: 18px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 8px 18px rgba(72, 27, 22, 0.04);
}

.customer-return-input:focus,
.customer-return-select:focus {
  border-color: rgba(107, 32, 43, 0.64);
  background: var(--customer-paper);
  box-shadow:
    0 0 0 4px rgba(158, 20, 20, 0.08),
    0 14px 28px rgba(72, 27, 22, 0.09);
}

/* main.css declares `.has-error` after its own `:focus`, so the error edge used
   to survive focus. Re-assert it at (0,3,0) or the new focus rule would hide a
   validation error the moment the field is focused. */
.customer-return-input.has-error,
.customer-return-input.has-error:focus,
.customer-return-select.has-error,
.customer-return-select.has-error:focus {
  border-color: var(--customer-danger);
  box-shadow: 0 0 0 3px rgba(183, 28, 28, 0.12);
}

/* File drop zones. `.customer-rating-upload` (main.css:10821) already carries a
   red dashed treatment, so the appointment attachment field (`2px dashed #ccc`
   on #fafafa) and the GCash receipt field are brought onto it rather than a
   third look being invented. Radii stay as authored — STEP 1 set the flat 8px
   card language on purpose. */
.file-upload-wrapper,
.cgc-file-input {
  border: 1px dashed rgba(107, 32, 43, 0.34);
  background: #fffafa;
}

.file-upload-wrapper:focus-within,
.cgc-file-input:focus-within,
.customer-rating-upload:focus-within {
  border-color: var(--customer-wine);
  background: #fff0f0;
  box-shadow: 0 0 0 3px rgba(133, 19, 19, 0.12);
}

/* Everything else was still browser blue. `:where()` is (0,0,0) on purpose so
   every existing `accent-color` keeps winning — including the deliberate white
   one on `.customer-return-resolution-option input` (main.css:11685), which is
   white-on-maroon and must not flip. */
:where(input[type="checkbox"], input[type="radio"]) {
  accent-color: var(--customer-wine);
}

/* ---------------------------------------------------------------------------
   §1b — Remove the red rectangle drawn inside the rounded wrappers.
   main.css:15966 gives every field `outline: 1px solid rgba(176,28,28,.45)`
   with `outline-offset: 3px` on focus. Chrome follows `border-radius` when it
   draws an outline, so on an ordinary field that is a rounded hairline — but
   these children are `border-radius: 0` inside a rounded box, so the outline
   becomes a hard rectangle floating inside it (measured at 1280: a 155x24
   square select, outlined 3px out, inside a 193x46 box at radius 16).
   `select:focus-visible` is (0,1,1), so the wrapper has to be named to win.
   Keyboard focus is not lost: every wrapper here draws its own rounded red
   `:focus-within` ring (`.category-dropdown-box` main.css:2041,
   `.toolbar-search` main.css:2000, and the two added above).
   ------------------------------------------------------------------------- */
.category-dropdown-box .category-select:focus-visible,
.toolbar-search .search-input:focus-visible,
.phone-input-group .c-input:focus-visible,
.qty-selector input:focus-visible,
.qty-selector .qty-btn:focus-visible {
  outline: none;
}

/* ---------------------------------------------------------------------------
   §2 — The "Account Tip" popover has to fit every width.
   The card's whole look now comes from the ACCOUNT TIP POPOVER section at the
   end of main.css, which rebuilds it on the `ux-dlg` system as a sibling of the
   profile dropdown: 344px wide, `--ux-dlg-radius`, the maroon head band, the
   cream footer strip, and no media query anywhere in it. That is deliberate —
   the tip is gated on account data, never on viewport width — so nothing here
   may hide it, and nothing here may shrink it below its own tap floors.

   What is left for this section is the two places where 344px genuinely does not
   fit: the phone comfort band, and the ultra-narrow band where the header
   restacks and moves the avatar the card hangs from.

   Every selector below carries `.user-profile` or `.google-pwd-card` for the
   same reason main.css does: the part rules there are (1,2,0), so a plainer
   selector in this file would silently lose even though it loads later.
   ------------------------------------------------------------------------- */

/* Phone comfort band: 344px is wider than a 390px screen wants to give a
   popover once the 12px page gutter is taken out, so the padding and type step
   down together rather than the card crowding its own edges. */
@media (max-width: 420px) {
  .user-profile #googlePwdFloatingCard.google-pwd-floating-card {
    top: calc(100% + 12px);
    /* One token, every part: head, body and foot all read `--ux-dlg-pad-x`. */
    --ux-dlg-pad-x: 14px;
  }

  #googlePwdFloatingCard .google-pwd-card .ux-dlg__head {
    padding: 12px 14px;
    padding-right: 50px;
  }

  #googlePwdFloatingCard .google-pwd-card .ux-dlg__title {
    font-size: 14.5px;
  }

  #googlePwdFloatingCard .google-pwd-card .ux-dlg__body {
    padding: 13px 14px 12px;
  }

  #googlePwdFloatingCard .google-pwd-card .ux-dlg__text {
    font-size: 12.4px;
  }

  #googlePwdFloatingCard .google-pwd-card .ux-dlg__foot {
    padding: 11px 14px 12px;
  }

  #googlePwdFloatingCard .google-pwd-card .ux-dlg__btn {
    padding: 11px 12px;
    font-size: 12.4px;
  }
}

/* Ultra-narrow: this band restacks the header into two rows, and the avatar the
   card hangs from is then centred in its row instead of sitting at the right
   edge — measured at 280, its right edge is 208, not 273. A card sized off the
   viewport alone therefore starts at -44 and `body { overflow-x: hidden }` cuts
   it off. `50vw + 56px` is that centred avatar's right edge (50vw + 68px) less a
   12px breathing margin, so the left edge lands on 12px at every width in the
   band. The `::before` arrow needs no change: 18px in from the card's right is
   still the centre of the 34px avatar.

   The footer also has to give up its two columns here: 196px of card leaves the
   primary button ~86px, and "Set Password" does not fit in 86px at any readable
   size. Stacked, the primary goes on top — it is the action being offered. */
@media (max-width: 280px) {
  .user-profile #googlePwdFloatingCard.google-pwd-floating-card {
    width: min(344px, calc(50vw + 56px));
  }

  #googlePwdFloatingCard .google-pwd-card .ux-dlg__foot.is-confirm {
    grid-template-columns: minmax(0, 1fr);
  }

  #googlePwdFloatingCard .google-pwd-card #openPwdFromFloatingCard {
    order: -1;
  }
}

/* ---------------------------------------------------------------------------
   §3 — "Send Us a Message" card type, phones and tablets.
   main.css:7290 (inside its own `@media (max-width: 900px)`) sets
   `.contact-link-text, .contact-input, .contact-field-group label { 16px }`.
   Later unmedia'd layers re-declare the first two at the same weight so they
   recover — but nothing ever re-declares the label, so it stayed 16px/800 on
   every phone while its own base rule (main.css:6444) is 12px, and the card
   read larger than the 13.5px body copy beside it.
   Gated at 900, not 720, so it cancels exactly the band that caused it.
   `.contact-input`'s own size is deliberately untouched: main.css:14849 holds
   it at `max(16px, .95rem)` for the iOS no-zoom floor. The placeholder can
   shrink freely — iOS keys auto-zoom off the input, not the placeholder.
   ------------------------------------------------------------------------- */
@media (max-width: 900px) {
  .contact-field-group label {
    font-size: clamp(11.5px, 3.2vw, 13px);
    letter-spacing: 0.04em;
  }

  /* main.css:15605 sets this `!important` in its own ≤480 band, so matching it
     is the only way to win — no specificity trick avoids it. */
  .contact-subtitle {
    font-size: clamp(16px, 4.4vw, 19px) !important;
  }

  .contact-input::placeholder,
  .contact-textarea::placeholder {
    font-size: clamp(13px, 3.6vw, 14px);
  }

  #contactConsentTextEl {
    font-size: clamp(12px, 3.3vw, 13.2px);
  }
}

/* §4 — the `UCN-FMRC` lockup lives on one declaration (line 2254), which drives
   both the sticky header and the cloned mobile-sidebar brand; it was widened
   there rather than duplicated here, so there is only ever one clamp. */



/* §5 — reduced motion, phone widths.
   The phone band above re-tunes the deck fan, and a media query adds no
   specificity, so those rules land on top of the reduced-motion pins in
   main.css. Re-pin them here to the phone geometry, so a visitor who has asked
   for less motion gets the same still deck on a phone that they get on a
   desktop. */
@media (max-width: 480px) and (prefers-reduced-motion: reduce) {
  .vm-deck--vision.has-stack.is-peeking .vm-deck__card[data-slot="1"] {
    transform: translate(-7px, 5px) rotate(-2.4deg) scale(0.96);
  }

  .vm-deck--vision.has-stack.is-peeking .vm-deck__card[data-slot="2"] {
    transform: translate(-14px, 10px) rotate(-4.6deg) scale(0.93);
  }

  .vm-deck--mission.has-stack .vm-deck__card.is-lifting {
    transform: none;
  }
}

/* Product button consistency: rectangular actions across cards, details,
   reviews and checkout. Header controls and quantity/review media controls
   retain their existing treatment. Compact controls keep the same corner. */
.products-page-body .product-actions .action-btn,
#productInfoModal .modal-actions .modal-btn,
.products-page-body .shop-modal-box .btn-place-order,
.products-page-body .shop-modal-body :is(.gcash-copy-btn, .gcash-open-app-btn, .edit-address-btn, .delete-address-inline),
#customerReviewsModal :is(.customer-review-filter, .customer-reviews-load-more),
.products-page-body #orderSuccessModal .success-card__footer .apt-btn {
  box-sizing: border-box;
  min-height: 44px;
  border-width: 1px;
  border-style: solid;
  border-radius: var(--apt-radius, 8px);
  padding: 10px 16px;
  font-family: "Montserrat", sans-serif;
  font-weight: 800;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  box-shadow: none;
  transition: background-color .18s ease, border-color .18s ease, color .18s ease, transform .1s ease;
}

.products-page-body .product-actions .action-btn {
  min-height: 40px;
  height: 40px;
  padding: 0 8px;
}

.products-page-body .product-actions .btn-add-cart {
  width: 40px;
  padding: 0;
}

#productInfoModal .modal-actions .modal-btn {
  min-height: 44px;
  height: 44px;
  padding-block: 0;
}

#productInfoModal #productInfoAddToCart {
  width: 44px;
  padding: 0;
}

.products-page-body .shop-modal-body :is(.gcash-copy-btn, .edit-address-btn, .delete-address-inline),
#customerReviewsModal .customer-review-filter {
  min-height: 36px;
  padding: 7px 12px;
  font-size: 12px;
}

.products-page-body .product-actions :is(.btn-view-info, .btn-add-cart),
#productInfoModal .modal-actions :is(.outline-btn, .reviews-btn),
.products-page-body .shop-modal-box .delete-btn,
.products-page-body .shop-modal-body :is(.gcash-copy-btn, .edit-address-btn, .delete-address-inline),
#customerReviewsModal .customer-review-filter {
  background: var(--customer-paper);
  border-color: var(--customer-wine);
  color: var(--customer-wine);
}

.products-page-body .product-actions .btn-buy-now,
#productInfoModal .modal-actions .solid-btn,
.products-page-body .shop-modal-box .btn-place-order:not(.delete-btn),
#customerReviewsModal :is(.customer-review-filter.active, .customer-reviews-load-more) {
  background: var(--customer-wine);
  border-color: var(--customer-wine);
  color: var(--customer-paper-sink);
}

.products-page-body .product-actions .action-btn:hover:not(:disabled),
#productInfoModal .modal-actions .modal-btn:hover:not(:disabled),
.products-page-body .shop-modal-box .btn-place-order:hover:not(:disabled),
.products-page-body .shop-modal-body :is(.gcash-copy-btn, .edit-address-btn, .delete-address-inline):hover:not(:disabled),
#customerReviewsModal :is(.customer-review-filter, .customer-reviews-load-more):hover:not(:disabled) {
  background: var(--customer-wine);
  border-color: var(--customer-wine);
  color: var(--customer-paper-sink);
  box-shadow: none;
  transform: none;
}

.products-page-body .product-actions .btn-buy-now:hover:not(:disabled),
#productInfoModal .modal-actions .solid-btn:hover:not(:disabled),
.products-page-body .shop-modal-box .btn-place-order:not(.delete-btn):hover:not(:disabled),
#customerReviewsModal :is(.customer-review-filter.active, .customer-reviews-load-more):hover:not(:disabled) {
  background: var(--customer-wine-hover);
  border-color: var(--customer-wine-hover);
}

/* The three legacy delete handlers use id-level !important hover paint. */
.products-page-body :is(#cartDeleteBtn, #deleteSelectedAddressBtn, #deleteAllAddressBtn):hover:not(:disabled) {
  background: var(--customer-wine) !important;
  border-color: var(--customer-wine) !important;
  color: var(--customer-paper-sink) !important;
}

.products-page-body .product-actions .action-btn:focus-visible,
#productInfoModal .modal-actions .modal-btn:focus-visible,
.products-page-body .shop-modal-box .btn-place-order:focus-visible,
.products-page-body .shop-modal-body :is(.gcash-copy-btn, .gcash-open-app-btn, .edit-address-btn, .delete-address-inline):focus-visible,
#customerReviewsModal :is(.customer-review-filter, .customer-reviews-load-more):focus-visible {
  outline: 2px solid var(--customer-wine);
  outline-offset: 3px;
  box-shadow: none;
}

.products-page-body .product-actions .action-btn:active:not(:disabled),
#productInfoModal .modal-actions .modal-btn:active:not(:disabled),
.products-page-body .shop-modal-box .btn-place-order:active:not(:disabled),
.products-page-body .shop-modal-body :is(.gcash-copy-btn, .gcash-open-app-btn, .edit-address-btn, .delete-address-inline):active:not(:disabled),
#customerReviewsModal :is(.customer-review-filter, .customer-reviews-load-more):active:not(:disabled) {
  box-shadow: none;
  transform: scale(.98);
}

.products-page-body .product-actions .action-btn:is(:disabled, .disabled),
#productInfoModal .modal-actions .modal-btn:is(:disabled, .disabled),
.products-page-body .shop-modal-box .btn-place-order:disabled,
.products-page-body .shop-modal-body :is(.gcash-copy-btn, .gcash-open-app-btn, .edit-address-btn, .delete-address-inline):disabled,
#customerReviewsModal :is(.customer-review-filter, .customer-reviews-load-more):disabled {
  background: var(--customer-paper-sink);
  border-color: #d8cbc8;
  color: #756b70;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}

@media (max-width: 720px) {
  .products-page-body .product-actions .action-btn {
    min-height: 36px;
    height: 36px;
    padding-inline: 8px;
  }

  .products-page-body .product-actions .btn-add-cart {
    width: 36px;
    padding: 0;
  }

  #productInfoModal .modal-actions .modal-btn {
    padding-inline: 10px;
  }

  #productInfoModal #productInfoAddToCart {
    padding: 0;
  }
}

/* Appointment Steps 1-5: size each caption to its complete word; only the
   connector gaps expand. This keeps every label on one line on phone screens. */
#appointmentFlow .apt-step span:last-child {
  white-space: nowrap;
  overflow-wrap: normal;
  word-break: normal;
  hyphens: none;
}

#appointmentFlow :is(.apt-input-group, .apt-reminder-content, .ticket-grid, .ticket-column, .ticket-header > div) {
  min-width: 0;
}

#appointmentFlow :is(.c-input, .file-upload-wrapper) {
  min-width: 0;
  max-width: 100%;
}

#appointmentFlow :is(.file-upload-text, .file-upload-name, .ticket-no, .t-value) {
  max-width: 100%;
  overflow-wrap: anywhere;
}

@media (max-width: 640px) {
  #appointmentFlow {
    --apt-dot: clamp(34px, 9.5vw, 42px);
    --apt-pad-l: max(12px, env(safe-area-inset-left, 0px));
    --apt-pad-r: max(12px, env(safe-area-inset-right, 0px));
    height: 100dvh;
  }

  #appointmentFlow .apt-container {
    min-height: calc(100dvh - var(--ux-safe-t) - var(--ux-safe-b));
    padding: 10px var(--apt-pad-r) 16px var(--apt-pad-l);
  }

  #appointmentFlow .apt-header-top {
    margin: 0 0 14px;
    padding: 0 0 14px;
    gap: 4px;
  }

  #appointmentFlow .apt-main-title {
    font-size: clamp(20px, 5.5vw, 26px);
    line-height: 1.3;
  }

  #appointmentFlow .apt-progress-wrapper {
    display: grid;
    grid-template-columns: max-content minmax(2px, 1fr) max-content minmax(2px, 1fr) max-content minmax(2px, 1fr) max-content minmax(2px, 1fr) max-content;
    align-items: start;
    justify-content: stretch;
    gap: 0;
    width: 100%;
    padding: 12px 6px;
    margin-bottom: 16px;
    /* Retain a contained fallback for screens smaller than modern phones and
       enlarged text, without ever clipping or breaking a step name. */
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: none;
  }

  #appointmentFlow .apt-step {
    width: auto;
    min-width: max-content;
    gap: 7px;
  }

  #appointmentFlow .apt-step span:last-child {
    font-size: clamp(10px, 2.65vw, 12px);
    line-height: 1.3;
    letter-spacing: -0.015em;
  }

  #appointmentFlow .apt-line {
    width: auto;
    min-width: 0;
    margin-inline: 2px;
  }

  #appointmentFlow .apt-card {
    margin-bottom: 0;
  }

  #appointmentFlow .apt-reminder-item {
    padding: 12px;
    gap: 10px;
  }

  #appointmentFlow .apt-form-grid {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 16px;
  }

  #appointmentFlow .c-input {
    width: 100%;
    min-height: 44px;
    font-size: 16px;
  }

  #appointmentFlow .file-upload-wrapper {
    height: auto;
    min-height: 100px;
    padding: 12px;
    text-align: center;
  }

  #appointmentFlow :is(.apt-calendar-left, .apt-time-right) {
    min-width: 0;
    padding: 12px 8px;
  }

  #appointmentFlow .cal-navigation {
    gap: 6px;
  }

  #appointmentFlow .cal-navigation button {
    flex: 0 0 44px;
    width: 44px;
    height: 44px;
  }

  #appointmentFlow #calMonthYear {
    min-width: 0;
    font-size: clamp(14px, 4vw, 18px);
    line-height: 1.3;
    text-align: center;
  }

  #appointmentFlow :is(.cal-days-header, .cal-days-grid) {
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 3px;
  }

  #appointmentFlow .cal-day-cell {
    min-height: 40px;
    aspect-ratio: auto;
    padding-inline: 0;
    font-size: 12px;
  }

  #appointmentFlow .cal-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 12px;
  }

  #appointmentFlow .slot-counter-wrapper {
    flex-wrap: wrap;
    gap: 8px;
  }

  #appointmentFlow .time-slot-btn {
    min-height: 44px;
  }

  #appointmentFlow :is(.ticket-container, .ticket-body, .ticket-grid) {
    width: 100%;
    min-width: 0;
  }

  #appointmentFlow :is(.ticket-row, .ticket-grid) {
    grid-template-columns: minmax(0, 1fr);
  }

  #appointmentFlow .apt-footer-actions .apt-btn {
    min-height: 44px;
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

@media (max-width: 360px) {
  #appointmentFlow {
    --apt-pad-l: max(10px, env(safe-area-inset-left, 0px));
    --apt-pad-r: max(10px, env(safe-area-inset-right, 0px));
  }

  #appointmentFlow .apt-progress-wrapper {
    padding-inline: 4px;
  }

  #appointmentFlow .apt-step span:last-child {
    letter-spacing: -0.035em;
  }
}
