/* ============================================================================
   MS GROUP DISTRIBUTORS — Porto Storefront Brand Overlay
   ----------------------------------------------------------------------------
   VISUAL LAYER ONLY. Loaded LAST in layouts/porto.blade.php (after demo41.min
   and custom.css) so its rules win the cascade. Re-skins the copied Porto
   "demo41" template into a distinct MS Group identity — brand teal system,
   restructured header utility bar, custom section headers, refined cards,
   buttons and footer. No markup, routes, JS or business logic depend on this
   file; removing it degrades gracefully to the base Porto styling.
   ============================================================================ */

:root {
  /* ==========================================================================
     PHASE 2 — BRAND PALETTE (UI_REFRESH_SPEC.md "Brand Identity").
     Spec values: Primary Teal #159EAA, Primary Navy #08264A, Background
     #FFFFFF, Section Background #F6F8FA, Primary Text #1E293B, Border #E5E7EB.

     CONTRAST NOTE (plan conflict C2): the spec teal #159EAA measures 3.23:1 on
     white — compliant for borders, icons, underlines and large text, but BELOW
     the WCAG AA 4.5:1 needed for normal-size text and for white label text on a
     teal fill. So #159EAA is kept as the visible brand accent, while the two
     darker steps carry text:
        --brand-primary      #159EAA  decorative: borders, icons, underlines, fills behind large text
        --brand-primary-600  #11838D  button fills — white text on it = 4.51:1 (AA pass)
        --brand-primary-700  #0D6873  teal text on white = 6.59:1 (AA pass), hover/pressed
     Neutrals use the same family the spec drew its own values from, so the
     greys stay consistent with #E5E7EB / #1E293B.
     ========================================================================== */
  --brand-primary:     #159EAA;   /* spec Primary Teal */
  --brand-primary-600: #11838D;   /* button fill / "slightly darker" hover */
  --brand-primary-700: #0D6873;   /* teal-on-white text, pressed */
  --brand-primary-050: #E7F5F7;
  --brand-primary-100: #D0EAEE;
  --brand-accent:      #3EB5C0;   /* lighter teal — accents on navy surfaces */
  --brand-accent-600:  #2AA3AF;
  --brand-navy:        #08264A;   /* spec Primary Navy */
  --brand-navy-700:    #061D39;
  --brand-deep-teal:   #0B4F5E;   /* topbar gradient end (navy -> deep teal) */

  --gold:      #E0A82E;
  --gold-700:  #C8901E;
  --danger:    #D64550;
  --danger-100:#FBE9EA;
  --sale-red:  #E85D5D;
  --success:   #1E9E6A;
  --success-050:#E7F6EF;

  --bg-app:    #F6F8FA;   /* spec Section Background */
  --bg-subtle: #F1F5F9;   /* image wells, quiet fills */
  --surface:   #FFFFFF;   /* spec Background */
  --border:    #E5E7EB;   /* spec Border Color */
  --border-strong: #D1D5DB;
  --text:      #1E293B;   /* spec Primary Text */
  --text-muted:#64748B;
  --text-soft: #94A3B8;   /* least-emphasis / strikethrough */

  /* Shadows tinted with the brand navy rather than a generic blue-grey.
     PHASE 4: softened per the spec's "use soft, subtle shadows only" — the
     large step was a heavy 40px/.14 drop that read as a lifted card. */
  --shadow-sm: 0 1px 2px rgba(8,38,74,.05), 0 1px 3px rgba(8,38,74,.04);
  --shadow-md: 0 4px 14px rgba(8,38,74,.07), 0 8px 24px rgba(8,38,74,.04);
  --shadow-lg: 0 10px 28px rgba(8,38,74,.10);

  /* Category badge gradients — the single source for product ribbon colors */
  --grad-new:      linear-gradient(135deg, var(--brand-accent) 0%, var(--brand-primary) 100%);
  --grad-best:     linear-gradient(135deg, var(--brand-primary) 0%, var(--brand-navy) 100%);
  --grad-sale:     linear-gradient(135deg, var(--gold) 0%, var(--gold-700) 100%);
  --grad-discount: linear-gradient(135deg, var(--sale-red) 0%, var(--danger) 100%);
  --grad-header:   linear-gradient(135deg, var(--brand-primary) 0%, var(--brand-navy) 100%);

  /* Spacing scale — reuse instead of ad-hoc values.
     Expressed in px for the same reason as the type scale: the 10px root makes
     rem misleading here. These are the exact equivalents of the previous rem
     values (.25/.5/.75/1/1.5/2/3rem at a 10px root), so nothing shifts. */
  --space-1: 2.5px;
  --space-2: 5px;
  --space-3: 7.5px;
  --space-4: 10px;
  --space-5: 15px;
  --space-6: 20px;
  --space-7: 30px;

  /* Consistent control height + focus ring for all form fields & buttons */
  --control-h: 44px;
  --focus-ring: 0 0 0 3px rgba(var(--brand-primary-rgb), .22);

  /* PHASE 4 — radius standardised to the spec's 10-12px band.
     Applies to SURFACES AND CONTROLS (buttons, inputs, cards, dropdowns,
     alerts). --r-pill stays circular on purpose: it is used for badges, the
     cart count and avatars, which look broken at 10px (plan conflict C7). */
  --r-sm: 10px;   /* controls: buttons, inputs, search — spec's stated value */
  --r-md: 12px;   /* surfaces: cards, panels, dropdowns */
  --r-lg: 12px;   /* was 16px — clamped to the spec ceiling */
  --r-pill: 999px;
  --transition: .2s ease;

  /* ==========================================================================
     PHASE 1 TOKEN LAYER — added during the 2026 UI refresh.
     Every token below is seeded with the value that was ALREADY in effect, so
     introducing them is a pure refactor with no visual change. Phase 2 flips
     the colour values; Phase 3 the font; Phase 4 radius/shadow/spacing.
     Change values HERE — never in the rules below, and never in demo41/custom.
     ========================================================================== */

  /* Channel form of the brand teal, for rgba() tints that need an alpha.
     Keep in sync with --brand-primary whenever that changes. */
  --brand-primary-rgb: 21, 158, 170;   /* #159EAA */
  --brand-navy-rgb:    8, 38, 74;      /* #08264A */

  /* --- Typography ---------------------------------------------------------
     Poppins is currently DECLARED across demo41/custom/porto-brand but never
     actually loaded, so the site renders in a system fallback. Phase 3 adds
     the @font-face/link; until then this token reproduces the status quo. */
  --font-sans:  Poppins, sans-serif;

  /* Type scale in px, NOT rem, and deliberately so: Porto sets
     `html { font-size: 62.5% }`, i.e. a 10px root, so 1rem = 10px here rather
     than the usual 16px. A rem-based scale silently renders at 62.5% of intent
     (body came out 8.75px instead of 14px). px keeps the scale independent of
     that root and of any future change to it. */
  --fs-h1:   36px;
  --fs-h2:   28px;
  --fs-h3:   22px;      /* matches the existing .inline-title */
  --fs-h4:   18px;
  --fs-h5:   16px;
  --fs-h6:   14px;
  --fs-body: 14px;      /* Phase 0 computed body size */
  --fs-sm:   13px;      /* nav links, small print */
  --fs-xs:   12px;

  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;

  --lh-tight: 1.25;
  --lh-body:  1.4;      /* current computed 19.6px / 14px */

  /* --- Layout rhythm ------------------------------------------------------ */
  /* PHASE 4: raised from the measured 34px per the spec's "increase spacing
     between sections to improve readability". Used by .product-section and the
     generic section shells so page rhythm stays consistent. */
  --section-y:     48px;
  --container-pad: 15px;   /* Bootstrap container gutter */
  /* PHASE 5: raised from the measured 25px — spec "increase spacing between the
     logo, search bar, and navigation". */
  --gap-header:    40px;

  /* --- Header ------------------------------------------------------------- */
  /* PHASE 5: 16px -> 18px. The header row also grows because the logo does, so
     a small padding bump is enough for the spec's "slightly increase the
     overall header height" (1440: 97px -> 112px). */
  --header-pad-y: 18px;
  --topbar-h:     38px;    /* current .brand-topbar min-height */
  /* PHASE 5 — explicit logo heights (natural 1600x533, ratio 3:1). Before this
     the logo had NO height of its own: it was sized by whatever width the
     .col-lg-2 column happened to be, which is why it rendered 64px at 1440,
     49px at 1024 and blew out to 222px at 768 (no column cap in that band).
     Values are +15-20% over the Phase 0 measurements, per spec.
        >=1200px  76px  (was 64.17)  +18.4%
        <1200px   58px  (was 48.84)  +18.7%   — also fixes the 768 blow-out
        <576px    36px  (was 29.97)  +20.1%
     Raised again on request after the first render — these are the live values,
     one token per breakpoint, so the logo can be resized from here alone. */
  --logo-h:    90px;
  --logo-h-md: 68px;
  --logo-h-sm: 42px;
  /* Search sits slightly taller than the shared --control-h (44px) so it reads
     as the primary header control — spec "slightly increase the search bar
     height". Form fields elsewhere keep --control-h. */
  --search-h:     48px;
  --search-max-w: 480px;
  --search-btn-w: 54px;   /* attached submit button, matches .modern-search */

  /* --- Navigation --------------------------------------------------------- */
  /* PHASE 5: gap 12 -> 24px, link padding trimmed to 18px, so the space between
     two labels goes 52px -> 60px (spec "increase spacing between nav items"). */
  --nav-gap:          24px;
  --nav-pad-x:        18px;
  --nav-fs:           13px;  /* current .shop-menu > li > a font-size */
  --nav-underline-h:  3px;   /* active/hover underline — see C1 */

  /* --- Trust bar ---------------------------------------------------------- */
  /* DEFINED ONLY — the component does not exist yet (Phase 6, blocked on C5). */
  --trustbar-bg:      var(--brand-navy);
  --trustbar-divider: rgba(255, 255, 255, .12);

  /* --- Footer ------------------------------------------------------------- */
  /* Spec: heading white, link light gray, link hover Primary Teal.
     On the navy footer: link 9.6:1, teal hover 4.7:1 — both AA. */
  --footer-heading:    #FFFFFF;
  --footer-text:       #CBD5E1;
  --footer-link:       #CBD5E1;
  --footer-link-hover: var(--brand-primary);
  --footer-copyright:  #94A3B8;
  --footer-rule:       rgba(255, 255, 255, .10);
}

/* ---------------------------------------------------------------------------
   1. Branded utility top bar (added in components/Header.blade.php)
   --------------------------------------------------------------------------- */
.brand-topbar {
  background: linear-gradient(90deg, var(--brand-navy) 0%, var(--brand-deep-teal) 100%);
  color: #E8EEF3;
  font-size: 12.5px;
  letter-spacing: .3px;
}
.brand-topbar .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 38px;
  flex-wrap: wrap;
  gap: 6px 18px;
}
.brand-topbar .bt-left { font-weight: 500;color: #fff; }
.brand-topbar .bt-left .hl { color: var(--gold); font-weight: 700; }
.brand-topbar .bt-right { display: flex; gap: 20px; flex-wrap: wrap; }
.brand-topbar a { color: #E8EEF3; transition: color .2s ease; display: inline-flex; align-items: center; gap: 6px; }
.brand-topbar a:hover { color: var(--brand-accent); text-decoration: none; }
.brand-topbar i { color: var(--brand-accent); }
@media (max-width: 767px) {
  .brand-topbar .bt-right { display: none; }
  .brand-topbar .container { justify-content: center; }
}

/* ============================================================================
   2. Header cluster — logo · search · navigation  (PHASE 5)
   ----------------------------------------------------------------------------
   This section is now the ONLY home for header styling. The ~230-line inline
   <style> block that used to sit at the top of components/Header.blade.php was
   migrated here (see 2.5/2.6 below) because it loaded AFTER this file and
   therefore silently beat every header token — nothing in this phase could be
   delivered from CSS while it stayed in the blade.

   Order inside this section matters: the nav underline rules deliberately come
   BEFORE the categories caret rules, which re-enable the ::after that the
   underline reset switches off.
   ============================================================================ */

/* --- 2.1 Header shell ----------------------------------------------------- */
.header .header-middle {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  padding-top: var(--header-pad-y);
  padding-bottom: var(--header-pad-y);
}

/* --- 2.2 Logo ------------------------------------------------------------- */
/* The logo previously had no intrinsic size — it inherited whatever width the
   .col-lg-2 column resolved to, so it changed size arbitrarily per breakpoint.
   Now the HEIGHT is the fixed dimension and the width follows the aspect ratio;
   object-fit:contain guarantees no distortion if the asset is ever swapped. */
.header .logo {
  display: flex;
  align-items: center;      /* vertical centring within the header row */
  max-width: none;          /* beats demo41's 100px/90px responsive caps */
}
.header .logo img {
  height: var(--logo-h);
  width: auto;
  max-width: 100%;
  object-fit: contain;
  display: block;
}
@media (max-width: 1199px) { .header .logo img { height: var(--logo-h-md); } }
@media (max-width: 575px)  { .header .logo img { height: var(--logo-h-sm); } }

/* Header-middle layout: distribute the three groups evenly across the row —
   [logo] · · · [search] · · · [sign-in + cart]. Base Porto pins the whole
   search+account cluster to the right (header-right has margin-left:auto),
   leaving a big empty gap after the logo. We let header-right fill the row
   and centre the search so the space is balanced on both sides. */
@media (min-width: 992px) {
  /* Release the .col-lg-2 cap so the taller logo is not squeezed, and give it
     the extra white space the spec asks for. */
  .header .header-middle .header-left {
    flex: 0 0 auto !important;
    max-width: none !important;
    padding-right: 0;
  }
  .header .header-middle .header-right {
    flex: 1 1 auto !important;
    margin-left: var(--gap-header) !important;   /* breathing room after the logo */
    width: auto !important;
    min-width: 0;
  }
  .header .header-middle .header-right .header-search {
    flex: 1 1 auto;
    min-width: 0;
    max-width: var(--search-max-w);
    margin-left: auto !important;     /* equal free space to the left ... */
    margin-right: auto !important;    /* ... and to the right of the search */
  }
  /* keep the account block (sign-in + cart) tight together at the far right */
  .header .header-middle .header-login { margin-left: var(--space-6) !important; }
}

/* --- 2.3 Search bar ------------------------------------------------------- */
/* Built to match #product-search-input (.modern-search on the listing page) so
   the two searches on the site are one control: input plus an ATTACHED solid
   teal submit button, 2px border, 10px radius on the outer corners only.

   Requested directly, and it supersedes part of the spec's Search Bar section —
   that asked for a 1px #E5E7EB border and a soft shadow. Matching .modern-search
   means a 2px --border-strong border and no shadow. The 10px radius and the
   taller field, which the spec also asked for, are kept.

   Markup is untouched: the button was absolutely positioned inside the field
   before and is now a flex sibling, which is a pure CSS change. It carries .p-0
   (padding:0 !important), so its size comes from --search-btn-w, not padding. */
.header-search-wrapper {
  position: relative;
  display: flex;
  width: 100%;
}
.header-search-wrapper input[type="search"],
.header-search .form-control {
  flex: 1 1 auto;
  min-width: 0;
  width: auto;
  height: var(--search-h);
  border: 2px solid var(--border-strong) !important;
  border-right: 0 !important;
  border-radius: var(--r-sm) 0 0 var(--r-sm) !important;
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-body);
  padding: 8px 16px !important;
  box-shadow: none !important;
  transition: border-color var(--transition);
}
.header-search-wrapper input[type="search"]:focus,
.header-search .form-control:focus {
  border-color: var(--brand-primary) !important;
  box-shadow: none !important;
  outline: none;
}
.header-search-wrapper input[type="search"]::placeholder { color: var(--text-soft); opacity: 1; }

.header-search-wrapper button.icon-magnifier {
  flex: 0 0 var(--search-btn-w);
  width: var(--search-btn-w);
  height: var(--search-h);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--brand-primary-600);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: var(--brand-primary-600);
  color: #fff;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition);
}
.header-search-wrapper button.icon-magnifier:hover {
  background: var(--brand-primary-700);
  border-color: var(--brand-primary-700);
  color: #fff;
}
/* The field and its button read as one control, so the button follows the
   input's focus state rather than lighting up separately. */
.header-search-wrapper input[type="search"]:focus ~ button.icon-magnifier {
  border-color: var(--brand-primary);
  background: var(--brand-primary);
}
/* It carries .btn for Porto's markup — opt it out of the §5 hover lift, which
   would detach it from the field it is joined to. */
.header-search-wrapper button.icon-magnifier:hover,
.header-search-wrapper button.icon-magnifier:active {
  transform: none !important;
  box-shadow: none !important;
}

/* --- 2.4 Navigation ------------------------------------------------------- */
/* Nav row: white band, navy labels, teal hover, teal underline on the active
   item (spec). This REPLACES the filled teal pill from the previous pass —
   plan conflict C1. Base Porto ships this <ul> as a grey #ececec band with
   white vertical dividers and a 16.6rem left pad; all three are removed so the
   header reads as one white surface (spec "maintain a white header background").

   Colour note (C2): the underline uses the true brand teal #159EAA — it is
   decorative, where 3:1 is compliant — while hovered/active LABEL text uses
   --brand-primary-700, which clears AA at 6.59:1 on white. */
.header .header-bottom {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.header .shop-menu {
  padding-left: 0 !important;
  background: transparent !important;
  border-radius: 0;
  height: auto;
  min-height: 54px;
  margin-bottom: 0;
  gap: var(--nav-gap);
}
.header .shop-menu > li { margin: 0; }
.header .shop-menu > li:not(:last-child) { border-right: 0 !important; }
.header .shop-menu > li > a,
.header .header-menu ul li a {
  color: var(--brand-navy) !important;
  font-weight: 600;
  letter-spacing: .3px;
  text-transform: uppercase;
  font-size: var(--nav-fs);
  border-radius: 0;
  background: transparent !important;
  position: relative;
  transition: color var(--transition);
}
.header .shop-menu > li > a { padding: 14px var(--nav-pad-x) !important; }
.header .shop-menu > li > a:hover,
.header .shop-menu > li > a.active,
.header .header-menu ul li a:hover,
.header .header-menu ul li a.active { color: var(--brand-primary-700) !important; }

/* Underline is drawn with ::before and owned entirely here. custom.css draws a
   competing 2px ::after at bottom:-5px only on :hover/.active — switched off so
   there is one underline, not two. (The categories caret in 2.6 re-enables its
   own ::after; that rule must stay after this one.) */
.header .shop-menu li a::after,
.header .header-menu ul li a::after { display: none !important; }
.header .shop-menu > li > a::before,
.header .header-menu ul li a::before {
  content: "";
  position: absolute;
  left: var(--nav-pad-x);
  right: var(--nav-pad-x);
  bottom: 6px;
  height: var(--nav-underline-h);
  border-radius: 2px;
  background: var(--brand-primary);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform var(--transition);
}
.header .header-menu ul li a::before { left: 0; right: 0; bottom: -4px; }
.header .shop-menu > li > a:hover::before,
.header .shop-menu > li > a.active::before,
.header .header-menu ul li a:hover::before,
.header .header-menu ul li a.active::before { transform: scaleX(1); }

/* Track Order stays a filled button — it is an action, not a nav destination.
   De-pilled to the 10px control radius (C3) and filled with --brand-primary-600
   so its white label clears AA at 4.51:1 (C2). */
.header .shop-menu > li > a.track-btn,
.header-menu a.track-btn {
  background: var(--brand-primary-600) !important;
  color: #fff !important;
  border-radius: var(--r-sm) !important;
  padding: 10px 22px !important;
  text-transform: uppercase;
  letter-spacing: .4px;
}
.header .shop-menu > li > a.track-btn::before,
.header .header-menu a.track-btn::before { display: none !important; }
.header .shop-menu > li > a.track-btn:hover,
.header .header-menu a.track-btn:hover {
  background: var(--brand-primary-700) !important;
  color: #fff !important;
}

/* --- 2.5 Search autocomplete dropdown ------------------------------------- */
/* Migrated verbatim from components/Header.blade.php. The JS toggles
   .product-search-dropdown.active — do not change these class names. */
.product-search-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 9999;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  margin-top: 6px;
  max-height: 300px;
  overflow-y: auto;
  display: none;   /* shown by JS while typing */
}
.header-search-wrapper input:focus + .product-search-dropdown,
.product-search-dropdown.active { display: block; }

.product-search-item {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  transition: background var(--transition);
}
.product-search-item:last-child { border-bottom: none; }
.product-search-item:hover { background: var(--bg-subtle); }

.product-search-link { display: flex; text-decoration: none; color: var(--text); }
.product-search-info { display: flex; flex-direction: column; text-align: left; }
.product-search-name {
  font-weight: var(--fw-medium);
  font-size: var(--fs-body);
  margin-bottom: 3px;
  color: var(--text);
  text-align: left;
}
.product-search-name strong {
  background: #FFE58F;
  color: var(--text);
  font-weight: var(--fw-bold);
  padding: 0 2px;
  border-radius: 2px;
}
.product-search-details span { font-size: var(--fs-xs); color: var(--text-muted); margin-right: 10px; }
.product-search-empty { padding: 12px; text-align: center; color: var(--text-soft); font-size: var(--fs-body); }

/* --- 2.6 Categories mega-dropdown ----------------------------------------- */
/* Migrated verbatim from components/Header.blade.php. The stacking context and
   the overflow:visible overrides are load-bearing: .shop-menu carries
   overflow-x:auto from demo41, which would clip this panel. */
.header { position: relative; z-index: 1000; }
.header-bottom { position: relative; z-index: 1000; overflow: visible !important; }
.header-bottom .container { overflow: visible !important; position: relative; }
.shop-menu { position: relative; z-index: 1000; overflow: visible !important; }
.shop-menu li.has-categories { position: relative; z-index: 1001; }

/* Caret. Re-enables the ::after that 2.4 switches off — hence the !important
   and hence this rule living below it. */
.shop-menu li.has-categories > a::after,
.shop-menu li.has-categories > a:hover::after,
.shop-menu li.has-categories:hover > a::after {
  content: "▼" !important;
  font-size: .7em;
  margin-left: 5px;
  vertical-align: middle;
  display: inline-block !important;
  opacity: 1 !important;
  visibility: visible !important;
  position: static !important;
  bottom: auto !important;
  left: auto !important;
  width: auto !important;
  height: auto !important;
  background: none !important;
  border-radius: 0 !important;
  animation: none !important;
}

.shop-menu li.has-categories .categories-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  min-width: 200px;
  z-index: 10000;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: all .3s ease;
  margin-top: 5px;
  overflow: hidden;
}
.shop-menu li.has-categories:hover .categories-dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.shop-menu li.has-categories .categories-dropdown ul { list-style: none; margin: 0; padding: 8px 0; }
.shop-menu li.has-categories .categories-dropdown ul li { margin: 0; padding: 0; }
.shop-menu li.has-categories .categories-dropdown ul li a {
  display: block;
  padding: 10px 20px;
  color: var(--text);
  font-weight: var(--fw-medium);
  text-decoration: none;
  transition: background var(--transition), color var(--transition);
  border: none;
}
.shop-menu li.has-categories .categories-dropdown ul li a:hover {
  background: var(--brand-primary-050);
  color: var(--brand-primary-700);
}

/* Cart count badge -> brand gold for pop */
.cart-dropdown .cart-count.badge-circle,
.header .cart-count {
  background: var(--gold) !important;
  color: var(--brand-navy) !important;
  font-weight: 700;
}

/* ---------------------------------------------------------------------------
   3. Section headers (home: New Arrivals / Best Sellers / Sale) — restructured
   --------------------------------------------------------------------------- */
.product-section { padding-top: var(--section-y); padding-bottom: 8px; }
.product-slider-tab .inline-title {
  position: relative;
  font-family: var(--font-sans);
  font-weight: 700 !important;
  font-size: 22px !important;
  color: var(--brand-navy) !important;
  padding-left: 16px;
  letter-spacing: -.2px;
  text-transform: none;
}
.product-slider-tab .inline-title::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  transform: translateY(-50%);
  width: 5px; height: 24px;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--brand-accent), var(--brand-primary));
}
/* "View All" chip. Stays a pill on purpose (plan conflict C7 — chips and badges
   are exempt from the 10-12px band), but its colours follow the §5 ramp: at
   12px the label is normal-size text, so the -700 step is required for AA. */
.product-slider-tab .btn-outline-primary {
  border-radius: var(--r-pill) !important;
  border-color: var(--brand-primary) !important;
  color: var(--brand-primary-700) !important;
  font-weight: 600 !important;
  text-transform: uppercase;
  letter-spacing: .4px;
  font-size: 12px;
  padding: 7px 18px !important;
}
.product-slider-tab .btn-outline-primary:hover {
  background: var(--brand-primary-600) !important;
  border-color: var(--brand-primary-600) !important;
  color: #fff !important;
}
.product-slider-tab .divider {
  height: 2px;
  background: linear-gradient(90deg, var(--brand-primary-100), transparent) !important;
  border: 0 !important;
  margin: 14px 0 22px !important;
}

/* Generic section titles used on legacy sections */
.section-top .section-title,
.about .title,
.page-content .title {
  font-family: var(--font-sans);
  font-weight: 700 !important;
  color: var(--brand-navy) !important;
}
.about .link, .about-content .link { color: var(--brand-primary) !important; font-weight: 600; }

/* ---------------------------------------------------------------------------
   4. Product cards — quieter borders, brand hover
   --------------------------------------------------------------------------- */
.product-card {
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm) !important;
}
.product-card:hover {
  border-color: var(--brand-primary-100);
  box-shadow: var(--shadow-md) !important;
}
.product-card .product-price { color: var(--brand-primary) !important; }
.product-card .product-category { color: var(--brand-primary) !important; }
.product-card .btn-add-to-cart:hover { background: var(--brand-primary) !important; color: #fff !important; }

/* Featured category tiles (home) */
.single-category { transition: all .25s ease; border-radius: var(--r-md); }
.single-category:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.single-category .title { color: var(--brand-navy); }
.single-category .count { color: var(--brand-primary); font-weight: 600; }

/* ============================================================================
   5. Buttons — ONE scale for the whole site  (PHASE 8)
   ----------------------------------------------------------------------------
   Merged from the old §5 (global, but colours only) and §13 (the real scale,
   but scoped to .main / .page-content). That split WAS the inconsistency: the
   cart dropdown, the header and the footer all live outside .main, so their
   buttons silently fell back to raw demo41 styling — different radius,
   different padding, different hover. The scale is global now, which is what
   "a single consistent button style throughout the application" requires.

   Hierarchy is kept on purpose (plan conflict C6). "One button style" is read
   as one button SYSTEM — shared radius, weight, padding ramp, focus ring and
   transitions — with a teal primary and a neutral secondary. Flattening
   View Cart and Checkout into the same appearance would delete the primary
   action from the cart dropdown and the checkout flow.

   Colour (plan conflict C2). The spec asks for a Primary Teal fill with white
   text, but white on #159EAA is 3.23:1 — below AA. Fills therefore use
   --brand-primary-600 #11838D (white text 4.51:1 ✓) and hover to the spec's
   "slightly darker teal" --brand-primary-700 #0D6873 (6.59:1 ✓). Next to the
   spec teal the difference is imperceptible; the compliance difference is not.

   Sizing: the default button is 12px+19.6px+12px = 44px tall, i.e. exactly
   --control-h, so a button and an input finally line up in the same row. It
   was 48px (demo41's em-based `padding: 1em 1.6em`) against 44px inputs.
   ============================================================================ */

/* --- 5.1 Base + size ramp ------------------------------------------------- */
.btn {
  border-radius: var(--r-sm);
  padding: 12px 22px;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-body);
  letter-spacing: .2px;
  transition: background-color var(--transition), border-color var(--transition),
              color var(--transition), box-shadow var(--transition), transform var(--transition);
}
/* Only sm / default / lg are part of the system. demo41 also ships btn-xs and
   btn-xl; neither is used in any porto view, so they are left untouched rather
   than given a home in a scale nothing calls. btn-md appears once and folds
   onto the default. */
.btn-sm { padding: 8px 16px; font-size: var(--fs-sm); }
.btn-md { padding: 12px 22px; font-size: var(--fs-body); }
.btn-lg { padding: 15px 30px; font-size: var(--fs-h5); }

/* --- 5.2 Variants --------------------------------------------------------- */
/* Primary. .btn-dark is the checkout/primary CTA in this template, not a dark
   neutral, so it maps here too. */
.btn-primary,
.btn.btn-dark {
  background: var(--brand-primary-600) !important;
  border-color: var(--brand-primary-600) !important;
  color: #fff !important;
}
.btn-primary:hover,
.btn.btn-dark:hover,
.btn-primary:focus,
.btn.btn-dark:focus {
  background: var(--brand-primary-700) !important;
  border-color: var(--brand-primary-700) !important;
  color: #fff !important;
}

/* Neutral secondary — one calm grey, not bootstrap slate and not demo41's
   #f4f4f4. Used by View Cart, Update Cart, Back links. */
.btn-gray,
.btn-secondary {
  background: var(--bg-subtle) !important;
  border-color: var(--border-strong) !important;
  color: var(--text) !important;
}
.btn-gray:hover,
.btn-secondary:hover,
.btn-gray:focus,
.btn-secondary:focus {
  background: var(--border) !important;
  border-color: var(--border-strong) !important;
  color: var(--brand-navy) !important;
}

/* Outline neutral — the quiet "Go Back"-style action. Shares the secondary
   family's colours so there are two neutral weights, not two neutral looks. */
.btn-outline-secondary {
  background: transparent !important;
  border-color: var(--border-strong) !important;
  color: var(--text) !important;
}
.btn-outline-secondary:hover,
.btn-outline-secondary:focus {
  background: var(--bg-subtle) !important;
  border-color: var(--border-strong) !important;
  color: var(--brand-navy) !important;
}

/* Outline primary. Text uses the AA-safe -700 step; the border keeps the
   brighter brand teal, which is compliant at 3:1 as a non-text element. */
.btn-outline-primary {
  background: transparent !important;
  border-color: var(--brand-primary) !important;
  color: var(--brand-primary-700) !important;
}
.btn-outline-primary:hover,
.btn-outline-primary:focus {
  background: var(--brand-primary-600) !important;
  border-color: var(--brand-primary-600) !important;
  color: #fff !important;
}

/* --- 5.3 States ----------------------------------------------------------- */
/* custom.css:1811-1826 lifts EVERY button 2px on hover with a hard black
   `0 4px 15px rgba(0,0,0,.15)`, all !important, and separately gives primary
   buttons a 20px teal glow. That is three different hover treatments and a
   shadow the Phase 4 pass explicitly softened everywhere else. Unified here
   onto the shadow tokens — !important is required only to win that fight. */
.btn:hover {
  transform: translateY(-1px) !important;
  box-shadow: var(--shadow-md) !important;
}
.btn:active {
  transform: translateY(0) !important;
  box-shadow: var(--shadow-sm) !important;
}
/* demo41:2897 kills the focus ring outright (`.btn:focus { box-shadow: none }`).
   focus-visible restores it for keyboard users without ringing on mouse click. */
.btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring) !important;
}
.btn:disabled,
.btn.disabled {
  opacity: .55;
  cursor: not-allowed;
  box-shadow: none !important;
  transform: none !important;
}

/* ---------------------------------------------------------------------------
   6. Breadcrumb / page shells
   --------------------------------------------------------------------------- */
.page-content { background: var(--bg-app); padding:30px 0; }
.about, .page-content .about { background: transparent; }

/* ============================================================================
   7. Footer — brand structure  (PHASE 7)
   ----------------------------------------------------------------------------
   Spec: navy background, white headings, light-gray links, teal hover. The
   token values were already set to exactly that in Phase 2, so this phase is
   verification plus the few things the footer was still inheriting raw from
   demo41 rather than from the token layer.

   THE CASCADE FIGHT (re-verified — all three still resolve our way):
     1. custom.css:1765  .footer { background-color: #fff !important }
        vs ours, same specificity, this file loads later  -> navy wins.
     2. custom.css:1779  .footer .widget li, .footer .widget li a
                         { color: #000 !important }
        ours adds .footer .widget ul li a (higher specificity) AND matches
        .footer .widget li exactly while loading later  -> light gray wins.
     3. demo41:13398     .footer .widget-title { color: var(--brand-primary) }
        ours is !important  -> white wins.
   Anything added to custom.css after this point can silently take the footer
   back; that is why all three carry !important here rather than relying on
   load order alone.

   Contrast on the navy (#08264A), all AA:
     link #CBD5E1 10.2:1 · teal hover #159EAA 4.7:1 · copyright #94A3B8 5.9:1
   ============================================================================ */
.footer,
.footer .footer-middle,
.footer > .container { background: var(--brand-navy) !important; }
.footer { color: var(--footer-text); }
/* The teal top rule was being drawn TWICE — custom.css puts a 3px border on
   .footer and this file put another on .footer-middle, which is .footer's first
   child, so the two stacked into a 6px band. Kept on .footer-middle (it is the
   one that survives if custom.css is ever cleaned out) and zeroed on .footer. */
.footer { border-top: 0 !important; margin:0 }
.footer .footer-middle {
  border-top: 3px solid var(--brand-primary);
  padding-top: var(--section-y);
  padding-bottom: var(--space-7);
}
.footer .widget-title {
  color: var(--footer-heading) !important;
  font-size: var(--fs-h5);      /* was demo41's raw 1.5rem = 15px at the 10px root */
  font-weight: var(--fw-bold);
  letter-spacing: .4px;
  position: relative;
  padding-bottom: 12px;
  margin-bottom: 18px;
}
.footer .widget-title::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 34px; height: 3px;
  border-radius: 2px;
  background: var(--brand-accent);
}
/* Selectors mirror custom.css's (.footer .widget ul li a) so we win the
   cascade (equal specificity, loaded later) over its color:#000 !important. */
.footer .widget li,
.footer .widget ul li a,
.footer .links li a,
.footer .widget a { color: var(--footer-link) !important; transition: color .2s ease, padding-left .2s ease; }
.footer .widget ul li a:hover,
.footer .links li a:hover,
.footer .widget a:hover { color: var(--footer-link-hover) !important; background: transparent !important; padding-left: 4px; }
.footer .links a.track-btn {
  background: transparent !important;
  color: var(--footer-link) !important;
  padding: 0 !important;
  border-radius: 0 !important;
}
.footer .links a.track-btn:hover { color: var(--footer-link-hover) !important; }
.footer .footer-bottom { border-top: 1px solid var(--footer-rule); margin-top: 30px; }
.footer .footer-copyright { color: var(--footer-copyright); font-size: var(--fs-sm); }

/* Contact strip above the copyright. Flex + wrap rather than one plain line so
   the email, phone and URL break onto their own rows on a phone instead of
   splitting mid-address; the pipes hide at that width because they only read as
   separators while the items are side by side. No !important needed — these
   links are outside .widget, so custom.css's color:#000 on .footer .widget ul li a
   never reaches them. */
.footer .footer-contact {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2) var(--space-3);
  /* .footer-bottom carries no vertical padding in any of the loaded sheets, so
     the strip has to space itself off the rule above and the copyright below. */
  padding-top: var(--space-5);
  padding-bottom: var(--space-4);
  font-size: var(--fs-sm);
  color: var(--footer-copyright);
  text-align: center;
}
.footer .footer-contact .footer-contact__label{
  color: #fff; 
}
.footer .footer-contact a {
  color: var(--footer-link);
  font-weight: var(--fw-medium);
  transition: color .2s ease;
}
.footer .footer-contact a:hover { color: var(--footer-link-hover); }
.footer .footer-contact__sep { color: rgba(255, 255, 255, .25); }

@media (max-width: 575.98px) {
  .footer .footer-contact { flex-direction: column; gap: var(--space-2); }
  .footer .footer-contact__sep { display: none; }
}
.footer .payment-methods img { background: #fff; padding: 8px; border-radius: var(--r-sm); }

/* Link list picks up the type token instead of demo41's raw 13px. The 35px
   line-height is demo41's and is left alone deliberately — it is the footer
   list rhythm, and the spec asks to maintain existing spacing. */
.footer .widget li { font-size: var(--fs-sm); }

/* The footer-bottom sits inside .container > .footer-bottom > .container, so
   the gutter is applied twice. Collapse the inner one. */
.footer .footer-bottom > .container { padding-left: 0; padding-right: 0; max-width: none; }

/* Keyboard focus on a dark surface. The global --focus-ring is a 22% teal glow
   tuned for white backgrounds; on navy it is close to invisible, so footer
   links get a white ring instead. */
.footer a:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .38);
  border-radius: 3px;
}

/* ---------------------------------------------------------------------------
   8. Misc polish
   --------------------------------------------------------------------------- */
/* Text selection. This was `background: rgba(20,169,194,.22)` with NO color —
   a 22% tint that left the text in its own colour, so a selection was barely
   distinguishable from unselected text. It also overrode demo41:10125-10133,
   which had the right idea (solid fill, white text), and it overrode only
   ::selection and not ::-moz-selection, so Firefox and Chrome disagreed.

   Solid --brand-primary-600 with white text = 4.51:1, AA for normal text, and
   it reads clearly on white, on --bg-app and on the navy footer/trust bar.
   (The old value was also a stale literal: #14A9C2 is the pre-Phase-2 accent,
   not the current brand teal. It survived the Phase 2 sweep because it was
   written in rgba() channel form rather than as a hex.) */
::selection {
  background: var(--brand-primary-600);
  color: #fff;
  text-shadow: none;
}
::-moz-selection {
  background: var(--brand-primary-600);
  color: #fff;
  text-shadow: none;
}
a { transition: color .2s ease; }
.mobile-menu-toggler { color: var(--brand-primary) !important; }

/* ---------------------------------------------------------------------------
   9. Branded custom scrollbar
   --------------------------------------------------------------------------- */
/* Firefox */
html {
  scrollbar-width: thin;
  scrollbar-color: var(--brand-primary) var(--brand-primary-050);
}

/* WebKit (Chrome, Edge, Safari) — page + any scrollable element */
::-webkit-scrollbar {
  width: 11px;
  height: 11px;
}
::-webkit-scrollbar-track {
  background: var(--brand-primary-050);
}
::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, var(--brand-primary) 0%, var(--brand-primary-700) 100%);
  border-radius: var(--r-pill);
  border: 2px solid var(--brand-primary-050); /* inset gap so the thumb reads as a pill */
}
::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(180deg, var(--brand-accent) 0%, var(--brand-primary) 100%);
}
::-webkit-scrollbar-corner {
  background: var(--brand-primary-050);
}

/* ---------------------------------------------------------------------------
   10. Branded full-screen page loader
   --------------------------------------------------------------------------- */
.page-loader {
  position: fixed;
  inset: 0;
  z-index: 99999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: radial-gradient(circle at 50% 40%, #ffffff 0%, var(--brand-primary-050) 100%);
  opacity: 1;
  visibility: visible;
  transition: opacity .5s ease, visibility 0s linear .5s;
}
.page-loader.is-hidden {
  opacity: 0;
  visibility: hidden;
}

.page-loader__spinner {
  position: relative;
  width: 68px;
  height: 68px;
}
.page-loader__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 4px solid var(--brand-primary-100);
  border-top-color: var(--brand-primary);
  border-right-color: var(--brand-accent);
  animation: page-loader-spin .9s cubic-bezier(.5, .1, .4, .9) infinite;
}
.page-loader__dot {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--brand-primary) 0%, var(--brand-primary-700) 100%);
  animation: page-loader-pulse 1.2s ease-in-out infinite;
}
.page-loader__brand {
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--brand-primary);
  opacity: .85;
}

@keyframes page-loader-spin {
  to { transform: rotate(360deg); }
}
@keyframes page-loader-pulse {
  0%, 100% { transform: scale(1);   opacity: 1; }
  50%      { transform: scale(.55); opacity: .55; }
}

/* Respect reduced-motion preferences */
@media (prefers-reduced-motion: reduce) {
  .page-loader__ring,
  .page-loader__dot { animation: none; }
}

/* ============================================================================
   11. Typography — ONE family, one scale (PHASE 3)
   ----------------------------------------------------------------------------
   The storefront previously mixed Open Sans (body), Poppins (headings/UI) and
   Oswald (display), and loaded NONE of them — everything fell back to a system
   sans. All text families across demo41/custom now resolve to --font-sans, the
   webfont is linked in layouts/porto.blade.php, and the scale below gives the
   headings/body hierarchy the spec asks for.
   ============================================================================ */
body {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text);              /* was Porto's #777 — spec Primary Text */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Heading scale — one ramp, applied wherever page content renders */
.main h1, .main h2, .main h3, .main h4, .main h5, .main h6,
.page-content h1, .page-content h2, .page-content h3,
.page-content h4, .page-content h5, .page-content h6 {
  font-family: var(--font-sans);
  color: var(--brand-navy);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: -.2px;
  margin-bottom: var(--space-3);
}
.main h1, .page-content h1 { font-size: var(--fs-h1); }
.main h2, .page-content h2 { font-size: var(--fs-h2); }
.main h3, .page-content h3 { font-size: var(--fs-h3); }
.main h4, .page-content h4 { font-size: var(--fs-h4); font-weight: var(--fw-semibold); }
.main h5, .page-content h5 { font-size: var(--fs-h5); font-weight: var(--fw-semibold); }
.main h6, .page-content h6 { font-size: var(--fs-h6); font-weight: var(--fw-semibold); }

/* Body copy + links */
.main p, .page-content p {
  color: var(--text);
  line-height: 1.65;              /* looser than UI text for reading comfort */
  margin-bottom: var(--space-4);
}
.main small, .page-content small, .main .small { font-size: var(--fs-sm); color: var(--text-muted); }
/* Links use the AA-safe darker teal — #159EAA is only 3.23:1 on white */
.main a, .page-content a { color: var(--brand-primary-700); }
.main a:hover, .page-content a:hover { color: var(--brand-primary); }
.text-muted { color: var(--text-muted) !important; }
strong, b { font-weight: var(--fw-semibold); }

/* Keyboard focus visibility (accessibility) — brand ring, never a raw outline */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
[tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--r-sm);
}

/* ============================================================================
   12. Form controls — one look for inputs, selects, textareas
   ============================================================================ */
.main .form-control,
.page-content .form-control,
.main select.form-control,
.main textarea.form-control,
.main input[type="text"],
.main input[type="email"],
.main input[type="password"],
.main input[type="number"],
.main input[type="tel"],
.main input[type="search"],
.main select,
.main textarea {
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  color: var(--text);
  background-color: var(--surface);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.main .form-control:not(textarea):not([multiple]),
.main input[type="text"],
.main input[type="email"],
.main input[type="password"],
.main input[type="number"],
.main input[type="tel"],
.main select {
  height: var(--control-h);
}
.main textarea.form-control { min-height: 120px; padding-top: 10px; }
.main .form-control:focus,
.main input:focus,
.main select:focus,
.main textarea:focus {
  border-color: var(--brand-primary);
  box-shadow: var(--focus-ring);
  outline: none;
}
.main .form-control::placeholder { color: var(--text-soft); opacity: 1; }
.main .form-control:disabled,
.main .form-control[readonly] {
  background-color: var(--bg-subtle);
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 1;
}
.main label { color: var(--text); font-weight: 500; }

/* Native checkbox / radio accents */
.main input[type="checkbox"],
.main input[type="radio"] { accent-color: var(--brand-primary); }

/* Shared helpers so pages stop repeating inline styles ---------------------- */
/* Inline validation message (replaces repeated inline error styling) */
.field-error,
.error-message,
.invalid-feedback.d-block,
.text-danger.small {
  margin-top: var(--space-1);
  font-size: .8125rem;
  color: var(--danger);
}
.main .form-control.is-invalid,
.main .is-invalid .form-control {
  border-color: var(--danger);
}
.main .form-control.is-invalid:focus {
  box-shadow: 0 0 0 3px var(--danger-100);
}
/* Password show/hide eye (replaces 8 duplicated inline blocks) */
.password-input-wrapper { position: relative; }
.password-input-wrapper .form-control { padding-right: 44px; }
.password-toggle,
.password-toggle-icon {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  font-size: 1rem;
  cursor: pointer;
  background: none;
  border: 0;
  padding: 0;
  line-height: 1;
  transition: color var(--transition);
  z-index: 3;
}
.password-toggle:hover,
.password-toggle-icon:hover { color: var(--brand-primary); }

/* ============================================================================
   13. Buttons — MERGED INTO §5 (Phase 8)
   ----------------------------------------------------------------------------
   This section used to hold the real button scale but was scoped to .main /
   .page-content, so it never reached the header cart dropdown or the footer.
   Everything it did now lives in §5, globally. Section number kept so the
   numbering below does not shift.
   ============================================================================ */

/* ============================================================================
   14. Tables — cleaner headers, readable rows, brand accents
   ============================================================================ */
.main .table { color: var(--text); }
.main .table thead th {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: .8rem;
  letter-spacing: .4px;
  text-transform: uppercase;
  color: var(--text-muted);
  border-bottom: 2px solid var(--border);
  padding-top: 14px;
  padding-bottom: 14px;
}
.main .table td { border-color: var(--border); vertical-align: middle; }
.main .table tbody tr { transition: background-color var(--transition); }
.main .table-cart tbody tr:hover,
.main .table-hover tbody tr:hover { background-color: var(--brand-primary-050); }
.main .table .product-title a { color: var(--brand-navy); font-weight: 600; }
.main .table .product-title a:hover { color: var(--brand-primary); }
.main .table .product-price,
.main .table .subtotal-price { color: var(--brand-primary); font-weight: 600; }

/* ============================================================================
   15. Badges & alerts — brand-consistent status colours
   ============================================================================ */
.main .badge-primary { background: var(--brand-primary); }
.main .alert {
  border: 1px solid transparent;
  border-radius: var(--r-md);
  padding: 14px 18px;
}
.main .alert-success { background: var(--success-050); border-color: #BCE4D2; color: #14653F; }
.main .alert-danger  { background: var(--danger-100);  border-color: #F3C7CB; color: #9A2530; }
.main .alert-info    { background: var(--brand-primary-050); border-color: var(--brand-primary-100); color: var(--brand-primary-700); }

/* ============================================================================
   16. Breadcrumb (Porto native) + generic page breadcrumb
   ============================================================================ */
.main .breadcrumb {
  background: transparent;
  padding-left: 0;
  padding-right: 0;
}
.main .breadcrumb a { color: var(--text-muted); }
.main .breadcrumb a:hover { color: var(--brand-primary); }
.main .breadcrumb .active,
.main .breadcrumb-item.active { color: var(--brand-navy); font-weight: 500; }

/* ============================================================================
   17. Cart & checkout shells
   ============================================================================ */
.checkout-progress-bar li a { color: var(--text-muted); font-weight: 600; }
.checkout-progress-bar li.active a { color: #fff; }
.cart-summary {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
}
.cart-summary h3 {
  font-family: var(--font-sans);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: .3px;
  color: var(--brand-navy);
  margin-bottom: var(--space-4);
}
.cart-summary .table-totals tfoot td { font-weight: 700; color: var(--brand-navy); font-size: 1.05rem; }
.cart-table-container {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-4) var(--space-5);
}

/* ============================================================================
   18. Product card — SINGLE canonical component (home + listing share this)
   ----------------------------------------------------------------------------
   Sub-parts are scoped under .product-card so bare .product-price /
   .product-title etc. elsewhere (cart, PDP, Porto grid) are untouched.
   ============================================================================ */
.product-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
  display: flex;
  flex-direction: column;
}
.product-card:hover {
  transform: translateY(-4px);
  border-color: var(--brand-primary-100);
  box-shadow: var(--shadow-md);
}
.product-card .product-image-wrapper {
  position: relative;
  padding-top: 100%;
  background: var(--bg-subtle);
  overflow: hidden;
}
.product-card .product-image-wrapper img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .4s ease;
}
.product-card:hover .product-image-wrapper img { transform: scale(1.05); }

.product-card .product-badge {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  background: var(--grad-discount);
  color: #fff;
  padding: .35rem .7rem;
  border-radius: var(--r-pill);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .2px;
  line-height: 1;
  z-index: 2;
  box-shadow: var(--shadow-sm);
}
/* Badge variants — replace per-type inline gradients */
.product-card .product-badge--new      { background: var(--grad-new); }
.product-card .product-badge--best     { background: var(--grad-best); }
.product-card .product-badge--sale     { background: var(--grad-sale); color: var(--brand-navy); }
.product-card .product-badge--discount { background: var(--grad-discount); }

/* "Already in your cart" state. Rendered server-side from the session on load
   and re-applied by markProductInCart() after an AJAX add, so the cue survives
   navigation instead of vanishing on the next page view.

   The marker sits OUTSIDE .product-actions on purpose: that block is hidden
   until hover, and a "this is already in your cart" cue you have to hover to
   discover is not a cue. Top-left, so it never collides with .product-badge. */
.product-card .product-in-cart {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 2;
  display: none;
  align-items: center;
  gap: 5px;
  padding: .35rem .6rem;
  border-radius: var(--r-pill);
  background: var(--brand-primary-600);
  color: #fff;
  font-size: .7rem;
  font-weight: var(--fw-bold);
  letter-spacing: .3px;
  line-height: 1;
  box-shadow: var(--shadow-sm);
}
.product-card.is-in-cart .product-in-cart { display: inline-flex; }
.product-card .product-in-cart__qty:not(:empty)::before { content: " ×"; }

/* The whole card picks up the brand edge so the state is readable at a glance
   across a grid, not just on the one card being looked at. */
.product-card.is-in-cart {
  border-color: var(--brand-primary);
  box-shadow: 0 0 0 1px var(--brand-primary), var(--shadow-sm);
}
.product-card.is-in-cart:hover {
  box-shadow: 0 0 0 1px var(--brand-primary), var(--shadow-md);
}

.product-card .product-actions {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: var(--space-4);
  background: linear-gradient(to top, rgba(var(--brand-navy-rgb),.72), transparent);
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--transition), transform var(--transition);
}
.product-card:hover .product-actions { opacity: 1; transform: translateY(0); }

.product-card .btn-add-to-cart {
  width: 100%;
  padding: .7rem;
  background: var(--surface);
  border: none;
  border-radius: var(--r-sm);
  color: var(--brand-navy);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}
.product-card .btn-add-to-cart:hover { background: var(--brand-primary); color: #fff; }

.product-card .product-info {
  padding: var(--space-5);
  flex: 1;
  display: flex;
  flex-direction: column;
}
.product-card .product-category {
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--brand-primary);
  font-weight: 600;
  margin-bottom: var(--space-2);
  text-decoration: none;
  transition: color var(--transition);
}
.product-card .product-category:hover { color: var(--brand-primary-700); }
.product-card .product-name {
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 600;
  color: var(--brand-navy);
  margin: 0 0 var(--space-3) 0;
  line-height: 1.4;
  min-height: 2.8em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.product-card .product-name a { color: inherit; text-decoration: none; transition: color var(--transition); }
.product-card .product-name a:hover { color: var(--brand-primary); }
.product-card .product-pricing {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-top: auto;
}
.product-card .product-price { font-size: 1.35rem; font-weight: 700; color: var(--brand-primary); }
.product-card .product-old-price { font-size: 1rem; color: var(--text-soft); text-decoration: line-through; }
.product-card .product-qty {
  margin-top: var(--space-3);
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .3rem .7rem;
  border-radius: var(--r-pill);
  background: var(--brand-primary-050);
  font-size: .75rem;
  font-weight: 600;
  color: var(--brand-primary);
  align-self: flex-start;
}
.product-card .product-qty .qty-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--brand-primary); flex-shrink: 0; }
.product-card .product-qty .qty-label { color: var(--text-muted); font-weight: 500; }
.product-card .product-qty .qty-value { color: var(--brand-primary); font-weight: 700; }

/* 5-across product row on wide screens (replaces repeated inline flex hacks) */
.col-5th { position: relative; width: 100%; padding-right: 15px; padding-left: 15px; }
@media (min-width: 992px) { .col-5th { flex: 0 0 20%; max-width: 20%; } }

/* ============================================================================
   19. Storefront empty state — one look for "no products / empty" panels
   ============================================================================ */
.storefront-empty {
  text-align: center;
  padding: var(--space-7) var(--space-6);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.storefront-empty .empty-icon { font-size: 3.5rem; color: var(--border-strong); margin-bottom: var(--space-4); display: block; }
.storefront-empty h3 { font-size: 1.35rem; color: var(--brand-navy); margin-bottom: var(--space-2); }
.storefront-empty p { color: var(--text-muted); margin-bottom: var(--space-5); }

/* ============================================================================
   20. Section headings — make every section title use the branded pattern
   ============================================================================ */
/* The accent bar is a FLEX ITEM, not an absolutely-positioned one.
   It used to be `position: absolute; left: 0` against a block-level title, which
   works only while the text is left-aligned. custom.css:1306 centres
   `.products-section .section-title`, so on the product page the text sat in the
   middle of a full-width block while the bar stayed pinned to the far left edge,
   with nothing between them. As a flex row the bar is always beside the text,
   whatever the alignment, and `gap` gives it real breathing room instead of a
   padding-left that the bar had to be manually kept in sync with.

   text-align is reset to left so this title matches the home page's section
   headings — one treatment for section titles across the site. */
.main .section-title,
.products-section .section-title {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-sans);
  font-weight: var(--fw-bold);
  font-size: var(--fs-h3);
  color: var(--brand-navy);
  letter-spacing: -.2px;
  text-transform: none;
  text-align: left;
  padding-left: 0;
  border: 0;
}
.main .section-title::before,
.products-section .section-title::before {
  content: "";
  flex: 0 0 5px;
  height: 24px;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--brand-accent), var(--brand-primary));
}

/* ============================================================================
   21. Fix stray non-brand accents leaking from custom.css
   ============================================================================ */
.minipopup-box .product-detail .product-name:hover { color: var(--brand-primary) !important; }

/* ============================================================================
   22. Trust bar — site-wide reassurance strip (PHASE 6)
   ----------------------------------------------------------------------------
   Rendered once from layouts/porto.blade.php via components/TrustBar.blade.php,
   directly below the header. Navy background, white text and icons, and
   deliberately soft dividers (--trustbar-divider is white at 12% — the spec
   asks for "softer and less prominent" rules).

   Items are equal-width flex columns rather than Bootstrap grid columns so the
   dividers land on the true boundaries between items regardless of how long the
   labels are; --trustbar-* were defined back in Phase 1 for exactly this block.
   ============================================================================ */
.trust-bar {
  background: var(--trustbar-bg);
  color: #fff;
}
.trust-bar__list {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
}
.trust-bar__item {
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  margin: 0;   /* neutralise the global li spacing in demo41/custom */
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: 14px var(--space-5);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: .3px;
  line-height: var(--lh-tight);
  text-align: center;
}
.trust-bar__item + .trust-bar__item { border-left: 1px solid var(--trustbar-divider); }
.trust-bar__icon {
  font-size: 18px;
  color: #fff;
  flex-shrink: 0;
}
.trust-bar__label { color: #fff; }

/* Two-up below lg. Vertical dividers are dropped here per plan — on a wrapped
   grid they read as arbitrary rules rather than separators. */
@media (max-width: 991px) {
  .trust-bar__item {
    flex: 0 0 50%;
    max-width: 50%;
    padding: 12px var(--space-4);
  }
  .trust-bar__item + .trust-bar__item { border-left: 0; }
}
@media (max-width: 575px) {
  .trust-bar__item {
    gap: var(--space-3);
    padding: 10px var(--space-3);
    font-size: var(--fs-xs);
    letter-spacing: 0;
  }
  .trust-bar__icon { font-size: 15px; }
}

/* ============================================================================
   23. Error pages — one shell for 404 / 500  (PHASE 9)
   ----------------------------------------------------------------------------
   errors/404 and errors/500 are the same page with different words, and both
   were carrying their whole appearance in inline style="" attributes — which
   sit above every stylesheet in the cascade, so neither page could be themed
   from here at all. The markup already had good class names; they just had no
   rules behind them. Now they do, and the blades are markup only.

   The accent colour is the only real difference between the two, so 500 adds
   .error-content--danger rather than duplicating the block.
   ============================================================================ */
.error-content { padding: var(--section-y) 0; }
.error-content .error-banner { max-width: 400px; }
.error-content .error-icon i {
  font-size: 96px;
  line-height: 1;
  color: var(--brand-primary);
}
.error-content .error-title {
  /* Fluid so the 72px display size doesn't overflow a 390px viewport. */
  font-size: clamp(56px, 12vw, 72px);
  font-weight: var(--fw-bold);
  line-height: 1;
  color: var(--brand-primary);
  letter-spacing: -1px;
}
.error-content .error-heading {
  font-size: var(--fs-h2);
  font-weight: var(--fw-semibold);
  color: var(--brand-navy);
}
.error-content .error-text {
  font-size: var(--fs-h5);
  color: var(--text-muted);
  max-width: 52ch;
  margin-left: auto;
  margin-right: auto;
}
/* Flex + gap so the two buttons wrap cleanly on narrow screens instead of
   relying on an ml-2 utility that does nothing once they stack. */
.error-content .error-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: center;
}
.error-content .error-actions .btn i { margin-right: var(--space-2); }

.error-content--danger .error-icon i,
.error-content--danger .error-title { color: var(--danger); }

/* ============================================================================
   24. Static page shell — .page-hero + .page-prose  (PHASE 9)
   ----------------------------------------------------------------------------
   Every static page had invented its own page-top and its own text column:
     terms/privacy   .page-content > .container > .row > .col-lg-8 > .heading
     faq             .page-content > .container > .row > .col-lg-10 > h2.title
     about           .page-content > .about > .container > .row > .col-lg-9
                     > .about-content > .about-content   (nested, twice)
     wholesale       .page-content > ... > .about-info   (divs left unclosed)
     delivery-info   no .page-content at all; an empty .breadcrumb-area instead
   Five shells for one job. These two blocks replace all of them, so page rhythm
   is set once here rather than re-guessed per page.

   Deliberately NOT a Blade component: the pages differ in whether they have a
   sidebar, so a component would need enough slots to be worse than two classes
   on the markup that is already there.
   ============================================================================ */
.page-hero {
  padding-top: var(--section-y);
  padding-bottom: var(--space-6);
  margin-bottom: var(--space-7);
  border-bottom: 1px solid var(--border);
}
.page-hero h1,
.page-hero h2,
.page-hero .title {
  font-size: var(--fs-h1);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: -.4px;
  color: var(--brand-navy);
  margin: 0;
}
.page-hero__meta {
  margin: var(--space-3) 0 0;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* Readable measure. 76ch is ~10-12 words a line at --fs-body, the band where
   long-form text stops being tiring to scan. */
.page-prose {
  max-width: 76ch;
  padding-bottom: var(--section-y);
}
.page-prose--center { margin-left: auto; margin-right: auto; }
.page-prose h2 {
  font-size: var(--fs-h3);
  margin-top: var(--space-7);
  margin-bottom: var(--space-4);
}
.page-prose h3 { margin-top: var(--space-6); margin-bottom: var(--space-3); }
.page-prose > *:first-child { margin-top: 0; }
.page-prose p { line-height: 1.65; margin-bottom: var(--space-4); }
.page-prose ul,
.page-prose ol {
  padding-left: 20px;
  margin-bottom: var(--space-4);
  color: var(--text);
}
.page-prose li { margin-bottom: var(--space-2); line-height: 1.65; }
.page-prose .section + .section { margin-top: var(--space-7); }
.page-prose .contact-info {
  margin-top: var(--space-5);
  padding: var(--space-5);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.page-prose .contact-info p:last-child { margin-bottom: 0; }

/* ============================================================================
   25. Contact — success panel  (PHASE 9)
   ----------------------------------------------------------------------------
   The whole panel was built from style="" attributes, and its keyframes lived
   in a <style> block inside @section('scripts') — so the animation loaded after
   the stylesheets and the panel itself could not be themed at all.

   #contact-success-section keeps its inline `display:none`: jQuery slideDown()
   is what reveals it, and that is behaviour, not presentation.
   ============================================================================ */
.contact-success {
  text-align: center;
  padding: var(--space-7) var(--space-6);
  background: var(--brand-primary-050);
  border: 1px solid var(--brand-primary-100);
  border-radius: var(--r-lg);
  animation: contact-fade-in-up .5s ease;
}
.contact-success__icon {
  width: 80px;
  height: 80px;
  margin: 0 auto var(--space-5);
  background: var(--brand-primary-600);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: contact-scale-in .5s ease;
}
.contact-success__icon i { font-size: 36px; color: #fff; }
.contact-success h3 {
  color: var(--brand-navy);
  font-weight: var(--fw-semibold);
  margin-bottom: var(--space-3);
}
.contact-success p {
  color: var(--text-muted);
  font-size: var(--fs-h5);
  margin-bottom: var(--space-5);
}

@keyframes contact-scale-in {
  0%   { transform: scale(0); opacity: 0; }
  60%  { transform: scale(1.15); }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes contact-fade-in-up {
  0%   { opacity: 0; transform: translateY(20px); }
  100% { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .contact-success,
  .contact-success__icon { animation: none; }
}

/* Bootstrap's .text-primary spinner is bootstrap blue, not the brand teal —
   used by the order-tracking loading state. */
.main .spinner-border.text-primary,
.page-content .spinner-border.text-primary { color: var(--brand-primary) !important; }

/* ============================================================================
   26. Product detail — the qty / Add to Cart / View cart row
   ----------------------------------------------------------------------------
   Three controls in one flex row that did not share a height. Phase 8 put every
   .btn on --control-h (44px), but the quantity field kept demo41's 36px, so the
   row read as misaligned the moment "View cart" appeared next to it.

   > .btn is a DIRECT-child selector on purpose. bootstrap-touchspin injects its
   own +/- buttons inside .product-single-qty and they also carry .btn — a
   descendant selector would stretch those tiny 20px spinners to 150px.
   ============================================================================ */
.product-single-details .product-action {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-4);
}
.product-single-details .product-single-qty .form-control,
.product-single-details .product-action > .btn {
  height: var(--control-h);
}
.product-single-details .product-single-qty .form-control {
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  padding: 0 10px;
  text-align: center;
  font-weight: var(--fw-semibold);
}
.product-single-details .product-action > .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 150px;
  margin: 0;
}
/* Touchspin's spinners are 20px absolutely-positioned glyphs — the §5 hover
   lift detaches them from the field. */
.bootstrap-touchspin .input-group-btn-vertical > .btn:hover,
.bootstrap-touchspin .input-group-btn-vertical > .btn:active {
  transform: none !important;
  box-shadow: none !important;
}

/* ============================================================================
   27. Product gallery lightbox — #gallery-viewer-modal
   ----------------------------------------------------------------------------
   THE UNREADABLE TITLE, and it was ours. §11 paints every heading inside .main
   with --brand-navy. This modal's markup sits inside <main>, so the product name
   in .modal-title rendered #08264A on a rgba(0,0,0,.8) header — about 1.3:1,
   effectively invisible. Any dark-surface component placed inside .main will hit
   the same trap; it needs an explicit light colour, not an inherited one.

   NO SCROLLBAR: the body was unconstrained while the image was capped at 70vh,
   so header + image could exceed the dialog and the branded scrollbar from §9
   appeared inside the lightbox. The body now has a fixed height and the carousel
   fills it exactly, so there is nothing to scroll.
   ============================================================================ */
#gallery-viewer-modal .modal-dialog {
  max-width: min(1100px, 92vw);
}
#gallery-viewer-modal .modal-content {
  background: var(--brand-navy);
  border: 0;
  border-radius: var(--r-md);
  overflow: hidden;          /* clip the carousel to the rounded corners */
  box-shadow: var(--shadow-lg);
}
#gallery-viewer-modal .modal-header {
  background: transparent;
  border-bottom: 1px solid rgba(255, 255, 255, .12);
  padding: var(--space-4) var(--space-5);
  align-items: center;
}
#gallery-viewer-modal .modal-title {
  color: #fff !important;    /* beats the .main h1-h6 navy — see above */
  font-size: var(--fs-h5);
  font-weight: var(--fw-semibold);
  letter-spacing: 0;
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;       /* long product names used to wrap the header */
}
#gallery-viewer-modal .close {
  color: #fff !important;
  opacity: .85;
  text-shadow: none;
  flex: 0 0 auto;
}
#gallery-viewer-modal .close:hover {
  color: #fff !important;
  opacity: 1;
  background-color: rgba(255, 255, 255, .28);
}

/* Fixed stage height, image contained inside it — deterministic, so no overflow
   and therefore no scrollbar at any viewport size. */
#gallery-viewer-modal .modal-body {
  padding: 0;
  height: 76vh;
  overflow: hidden;
}
#gallery-viewer-modal .carousel,
#gallery-viewer-modal .carousel-inner,
#gallery-viewer-modal .carousel-item {
  height: 100%;
}
#gallery-viewer-modal .carousel-item img {
  width: 100%;
  height: 100%;
  max-height: none;
  object-fit: contain;
}

/* Controls as discrete circular buttons rather than two 5% black columns
   sitting on top of the artwork. */
#gallery-viewer-modal .carousel-control-prev,
#gallery-viewer-modal .carousel-control-next {
  width: 48px;
  height: 48px;
  top: 50%;
  transform: translateY(-50%);
  margin: 0 var(--space-4);
  border-radius: 50%;
  background: rgba(255, 255, 255, .14);
  opacity: 1;
  transition: background-color var(--transition);
}
#gallery-viewer-modal .carousel-control-prev { left: 0; }
#gallery-viewer-modal .carousel-control-next { right: 0; }
#gallery-viewer-modal .carousel-control-prev:hover,
#gallery-viewer-modal .carousel-control-next:hover {
  background: rgba(255, 255, 255, .3);
}
#gallery-viewer-modal .carousel-control-prev-icon,
#gallery-viewer-modal .carousel-control-next-icon {
  width: 18px;
  height: 18px;
}
/* Single-image galleries: the JS hides these, this is the belt-and-braces. */
#gallery-viewer-modal.is-single-image .carousel-control-prev,
#gallery-viewer-modal.is-single-image .carousel-control-next { display: none; }

@media (max-width: 767px) {
  #gallery-viewer-modal .modal-body { height: 62vh; }
  #gallery-viewer-modal .modal-dialog { max-width: 96vw; }
}

/* ============================================================================
   28. Checkout — payment step  (?step=payment)
   ----------------------------------------------------------------------------
   This step had NO styling at all. Every class its markup uses —
   .payment-information, .nav-link.payment, .pay-area, .info-list, .bottom-area,
   #card-element — returned zero matches across demo41.min.css, custom.css and
   this file. The gateway list was rendering as bare stacked anchors and the
   card field as an undersized box.

   On the Stripe field specifically: the card input lives in a CROSS-ORIGIN
   IFRAME, so nothing here can style the text inside it — no font, no colour, no
   placeholder. That has to be passed as a `style` object to
   elements.create('card', ...), which is done in CheckoutStripePayment.blade.php.
   What this section styles is the WRAPPER Stripe mounts into, using the state
   classes Stripe puts on it itself: --focus, --invalid, --complete.
   ============================================================================ */

/* --- 28.1 Gateway chooser ------------------------------------------------- */
.payment-information .nav.flex-column { gap: var(--space-3); }
.payment-information .nav-link.payment {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-5);
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  transition: border-color var(--transition), background-color var(--transition), box-shadow var(--transition);
}
.payment-information .nav-link.payment:hover {
  border-color: var(--brand-primary);
  background: var(--brand-primary-050);
}
.payment-information .nav-link.payment.active {
  border-color: var(--brand-primary);
  background: var(--brand-primary-050);
  box-shadow: 0 0 0 1px var(--brand-primary);
  color: var(--text);
}
.payment-information .nav-link.payment p {
  margin: 0;
  font-weight: var(--fw-semibold);
  line-height: 1.4;
}
.payment-information .nav-link.payment p small {
  display: block;
  margin-top: 3px;
  font-weight: var(--fw-regular);
  color: var(--text-muted);
}

/* Real radio affordance — the markup ships an empty <span class="radio">. */
.payment-information .nav-link.payment .icon {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  height: 21px;         /* optically centres against the first line of the label */
}
.payment-information .nav-link.payment .radio {
  display: block;
  width: 20px;
  height: 20px;
  border: 2px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.payment-information .nav-link.payment.active .radio {
  border-color: var(--brand-primary-600);
  box-shadow: inset 0 0 0 4px var(--surface), inset 0 0 0 20px var(--brand-primary-600);
}
.payment-information .nav-link.payment:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.pay-area { margin-top: var(--space-5); }
.pay-area:empty { display: none; }

/* --- 28.2 Shipping recap list -------------------------------------------- */
.billing-info-area .info-list { margin: 0; }
.billing-info-area .info-list li {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  color: var(--text);
}
.billing-info-area .info-list i {
  color: var(--brand-primary);
  width: 16px;
  flex: 0 0 16px;
}

/* --- 28.3 Stripe card field ---------------------------------------------- */
/* Deliberately NOT .form-control: that carries a fixed height: var(--control-h)
   from §12, which clips the Stripe iframe once it renders its own line-height. */
.stripe-card-field {
  padding: 13px 16px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  transition: border-color var(--transition), box-shadow var(--transition);
}
/* Stripe adds these three classes to the mount node as the user types. */
.stripe-card-field.StripeElement--focus {
  border-color: var(--brand-primary);
  box-shadow: var(--focus-ring);
}
.stripe-card-field.StripeElement--invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-100);
}
.stripe-card-field.StripeElement--complete {
  border-color: var(--success);
}
.stripe-panel{
  padding: 20px;
}
.stripe-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}
.stripe-panel__secure {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--success);
}
/* Card brand, revealed by the change handler once Stripe detects one. */
.stripe-brand {
  display: none;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--text-muted);
  text-transform: capitalize;
}
.stripe-brand.is-visible { display: inline-flex; }

#card-errors {
  display: none;
  align-items: center;
  gap: 6px;
  margin-top: var(--space-3);
  font-size: var(--fs-sm);
  color: var(--danger);
}
#card-errors.is-visible { display: flex; }

.stripe-panel__hint {
  margin: var(--space-3) 0 0;
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

/* --- 28.4 Step action row ------------------------------------------------- */
.bottom-area,
.stripe-panel__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}
.stripe-panel__actions .btn-pay { min-width: 190px; }
.stripe-panel__actions .spacer { margin-left: auto; }

/* Full-screen submit veil that ships with the payment markup */
.submit-loader {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: none;
  background: rgba(255, 255, 255, .75);
}
.submit-loader.is-active { display: block; }

@media (max-width: 575px) {
  .payment-information .nav-link.payment { padding: var(--space-4); }
  .stripe-panel__actions { flex-direction: column-reverse; align-items: stretch; }
  .stripe-panel__actions .btn { width: 100%; }
  .stripe-panel__actions .spacer { margin-left: 0; }
}

/* ============================================================================
   29. Auth pages — login / register  (PHASE 9)
   ----------------------------------------------------------------------------
   Both pages used the same shell (.heading > h1.title, then a bare <form>) and
   both sat directly on the --bg-app grey with nothing containing them, so the
   form read as loose fields on a page rather than as one task. One panel class
   shared by both; the .auth-page wrapper only sets the vertical rhythm.
   ============================================================================ */
.auth-page { padding: var(--section-y) 0; }
.auth-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-7);
}
.auth-panel .heading { margin-bottom: var(--space-6); text-align: center; }
.auth-panel .heading .title {
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  color: var(--brand-navy);
  line-height: var(--lh-tight);
  letter-spacing: -.3px;
  margin: 0 0 var(--space-3);
}
.auth-panel .heading p {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}
.auth-panel .form-group { margin-bottom: var(--space-5); }
.auth-panel label { font-weight: var(--fw-medium); font-size: var(--fs-sm); }
.auth-panel .form-footer { margin-top: var(--space-6); }

/* "or sign in with" — a rule with the label sitting in the gap, instead of a
   bare centred line of text. */
.auth-panel .form-choice { margin-top: var(--space-6); }
/* Flex rule-either-side, so the label sits in a real gap. No absolute
   positioning and no z-index stack to keep the text above a masking box. */
.auth-panel .form-choice > p {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  color: var(--text-muted);
  font-size: var(--fs-sm);
}
.auth-panel .form-choice > p::before,
.auth-panel .form-choice > p::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--border);
}

.auth-panel .btn-login {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
}
.auth-panel .auth-alt {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
  text-align: center;
  font-size: var(--fs-sm);
}
.auth-panel .auth-alt p { margin: 0; color: var(--text-muted); }
.auth-panel .auth-alt a { font-weight: var(--fw-semibold); }

@media (max-width: 575px) {
  .auth-panel { padding: var(--space-6) var(--space-5); }
}
