/* ============================================================
   Deviceland — product page overlay
   ============================================================

   A TOKEN OVERLAY over Elessi's markup, not a layout. The parent stylesheet
   stays loaded here because it is load-bearing: it defines .row, .columns,
   .nasa-flex, the 103 .product-info rules, and .hidden-tag, which conceals
   the seven native <select> elements behind the swatches.

   Cascade note: dynamic.css is theme-option output and writes rules of the
   form `body .selector { color: #c95928 }`. That is the same specificity as
   `body.deviceland-shop .selector`, and it used to load after this file, so
   its accent won — which is why selected chips had orange text on an ink
   ground and Add to cart came out orange. Two defences now: enqueue.php
   declares dynamic.css a dependency of this file so it always prints first,
   and the colour-critical rules below lead with `html` to outrank it outright.
   ============================================================ */

/* ------------------------------------------------------------
   Ground and rhythm
   ------------------------------------------------------------ */

body.deviceland-shop {
  background: var(--paper);
  color: var(--on-paper);
  font-family: var(--sans);
}

/* Horizontal overflow guard, scoped to phones on purpose.
   ------------------------------------------------------------
   deviceland.css carries `body { overflow-x: hidden }`, and chrome.css — what
   a WooCommerce page loads instead — is generated with every bare element
   selector stripped, so this page has never had it. That is the third thing
   the whitelist has quietly dropped, after the button reset and the :root
   token override, and it is why a stray negative margin scrolled the product
   page sideways while the homepage absorbed the same mistake silently.

   Gated to <=767px deliberately: overflow-x on a body creates a scroll
   container and breaks position:sticky in every descendant, and the gallery
   thumb rail is sticky from 768px up. Below that breakpoint the rail is
   already static, so there is nothing to break.

   This is a net, not the fix. The actual overflow is corrected at source in
   the slick rules below. */
@media (max-width: 767px) {
  /* On html AS WELL as body. overflow-x on body alone does not constrain the
     layout viewport on mobile Safari or Chrome — the previous attempt set it
     only on body, which is why the page still scrolled sideways. */
  html:has(body.deviceland-shop),
  html body.deviceland-shop {
    overflow-x: hidden;
  }
}

/* Header consistency is NOT handled here.

   Two previous attempts described the scrolled header state again in this
   file — first as a solid bar with a hairline, then as an always-visible
   island — and both drifted from the homepage: same site, two headers, one
   still showing the full lockup and tagline where the other showed the
   wordmark.

   chrome-masthead.php now applies the real .is-stuck class up front on inner
   pages, and deviceland.js leaves it alone via data-pinned. Every scrolled-
   header rule in chrome.css then applies verbatim — island opacity, 78px
   height, logo swap, the 16px inset that clears the island radius. There is
   nothing left for this file to say about it, which is the point.
   ------------------------------------------------------------ */

/* The masthead is position:fixed and therefore out of the document flow, so
   some clearance here is structural: without it the breadcrumb renders
   underneath the header instead of below it.

   The amount is no longer derived from tokens. --head-measured is written by
   deviceland.js from the masthead's real rendered bottom edge, which removes
   two sources of error that produced visibly wrong gaps twice:

     - --head-h-stuck is the BAR height (78px), but the visible element is the
       island, inset 9px inside it, so its bottom edge is at 69px;
     - a logged-in WordPress session adds a 32px admin bar and
       `html { margin-top: 32px }`, shifting the whole thing again.

   The fallback matches the island's edge for the logged-out desktop case, so
   the layout is correct before the script runs. Content passing under the
   island while scrolling is intended — it is translucent and blurred, which
   is the entire reason that treatment exists. */
/* 14px, not 4px.

   With the ID collision gone the clearance is finally the only offset in play,
   and 4px turned out to be genuinely too tight — the breadcrumb sat about 14px
   under the island and read as attached to it rather than as the start of the
   page.

   The cost is worth stating plainly, since it is the trade you asked about:
   this pushes the product image down by 10px on first view. That is a tenth of
   one line of body copy. The product is still comfortably above the fold at
   every viewport, and a breadcrumb that looks wedged under the header costs
   more than 10px of image ever will. */
body.deviceland-shop #main {
  padding-top: calc(var(--head-measured, 69px) + 14px);
  padding-bottom: 96px;
}

/* The header box measures 138px on this page while its only child measures
   78px, so roughly 60px of it is empty. That band is transparent and sits at
   z-index 800 across the full width, which means it was intercepting clicks on
   whatever scrolled under it — a real bug, not just a cosmetic one.

   Clicks now pass through the header and are re-enabled on the things inside
   it that are meant to be clickable. */
body.deviceland-shop .masthead {
  pointer-events: none;
}

body.deviceland-shop .masthead-inner > *,
body.deviceland-shop .masthead-actions > * {
  pointer-events: auto;
}

/* WordPress offsets the document for the admin bar but not fixed elements, so
   a pinned masthead would sit underneath it for logged-in users. */
body.admin-bar .masthead {
  top: 32px;
}

@media screen and (max-width: 782px) {
  body.admin-bar .masthead {
    top: 46px;
  }
}

@media (max-width: 1023px) {
  body.deviceland-shop #main {
    padding-bottom: 124px;
  }
}

/* ------------------------------------------------------------
   Mobile gutters
   ------------------------------------------------------------

   Everything below the gallery was sitting on the screen edge. The rewrite of
   this file dropped the container padding along with the layout rules it was
   bundled with, and dynamic.css only pads `.nasa-single-product-scroll > .row`
   — so the summary got a little and the tabs, description, reviews, related
   products and accessories got none.

   Padded here per section rather than on one wrapper, because the sections are
   siblings at different depths in Elessi's markup. --gut is 24px below
   1024px, which is the same gutter the homepage uses at that width. */
@media (max-width: 1023px) {
  /* Padded on the OUTERMOST container of each region only.
     ------------------------------------------------------------
     The previous version padded .product-details, .woocommerce-tabs and
     .cross-sells — and .cross-sells and .woocommerce-tabs are both nested
     inside .product-details. That compounded to 48px a side, plus Elessi's
     own 10px on .columns, so the spec table had roughly 274px of a 390px
     screen to work with and wrapped every two words. The extra scrolling was
     that, not the gutter itself. */
  html body.deviceland-shop .nasa-product-details-page,
  html body.deviceland-shop .product-details,
  html body.deviceland-shop .related-product {
    padding-left: var(--gut, 24px); padding-right: var(--gut, 24px);
  }

  /* Self-correcting guard: any padded container that turns out to be nested
     inside another gets none, so the gutter can never double no matter how
     Elessi nests these blocks. */
  html body.deviceland-shop .nasa-product-details-page .product-details,
  html body.deviceland-shop .nasa-product-details-page .related-product,
  html body.deviceland-shop .product-details .related-product,
  html body.deviceland-shop .product-details .cross-sells,
  html body.deviceland-shop .product-details .up-sells,
  html body.deviceland-shop .product-details .woocommerce-tabs,
  html body.deviceland-shop .product-details .nasa-single-product-tabs,
  html body.deviceland-shop .product-details .nasa-tabs-content {
    padding-left: 0; padding-right: 0;
  }

  /* Elessi's grid padding inside an already-padded region.

     THESE TWO RULES ARE A PAIR AND MUST CHANGE TOGETHER. Elessi's grid is
     Foundation's:

       .row .row  { margin-left: -10px; margin-right: -10px }
       .columns   { padding-left: 10px; padding-right: 10px }

     The column padding exists to cancel the negative margin on a nested row.
     The previous pass zeroed the padding to stop the gutter compounding and
     left the margins, so every nested .row on this page pushed 10px past each
     side — 20px of horizontal overflow.

     That is what widened the page, and on a phone a page wider than the screen
     widens the layout viewport, which a position:fixed header spanning
     inset-inline:0 then stretches to fill. The "massive island bar" was this
     overflow, not a header measurement. Zeroing both sides of the pair keeps
     the intended 24px gutter with nothing hanging over the edge. */
  html body.deviceland-shop .product-details .row,
  html body.deviceland-shop .product-details .row .row,
  html body.deviceland-shop .related-product,
  html body.deviceland-shop .related-product .row {
    margin-left: 0;
    margin-right: 0;
    width: auto;
  }

  html body.deviceland-shop .product-details .row > .columns,
  html body.deviceland-shop .related-product > .columns {
    padding-left: 0; padding-right: 0;
  }

  /* Headings sit closer to their content on a phone. */
  html body.deviceland-shop .ns-woo-tab-title,
  html body.deviceland-shop .nasa-title-relate,
  html body.deviceland-shop .woocommerce-Reviews-title {
    margin-bottom: 14px;
  }

  /* Related Products was the only heading indented 20px from the section edge.
     Both style-large.css and style-mobile.css ship

       .nasa-title-relate { font-size: 160%; margin-bottom: 23px; padding: 0 20px }

     and .ns-woo-tab-title has no equivalent, which is why Accessories sat
     flush and this one did not. The section container already supplies the
     mobile gutter, so the heading needs none of its own. */
  html body.deviceland-shop .nasa-title-relate {
    padding-left: 0; padding-right: 0;
  }

  html body.deviceland-shop table.shop_attributes th,
  html body.deviceland-shop table.shop_attributes td {
    padding: 9px 0;
  }

  html body.deviceland-shop table.shop_attributes th {
    width: 34%;
    padding-right: 12px;
  }

  /* Related Products wraps instead of swiping, so it matches Accessories.
     ------------------------------------------------------------
     Elessi renders Related Products as a slick carousel with
     data-columns-small="2", so two items show and the other two are reachable
     only by swipe, while Accessories is a plain grid that wraps all four. Two
     components doing the same job two different ways on one page, and the
     carousel is the worse of the two here: it hides half the items with no
     affordance that says so.

     slick writes inline transform and width onto the track and every slide, so
     these have to be !important. They are also safe if slick never
     initialises — a wrapping flex row with 50% children is the same grid the
     markup would produce on its own. */
  /* The margins are zeroed along with the overflow, and that pairing is the
     point. .slick-list ships `margin: 0 -10px` and relies on its own
     overflow:hidden to clip the result. Releasing the clip so the track can
     wrap without being cut vertically also released those -10px, so the
     carousel sat 10px past each side of the viewport — which is the horizontal
     overflow on this page. The gutter moves to the slides instead. */
  html body.deviceland-shop .related-product .slick-list {
    overflow: visible !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }

  html body.deviceland-shop .related-product .slick-track {
    display: flex !important;
    flex-wrap: wrap !important;
    width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    transform: none !important;
  }

  html body.deviceland-shop .related-product .slick-slide {
    width: 50% !important;
    float: none !important;
    height: auto !important;
    padding: 0 6px 12px !important;
  }

  /* Arrows and dots are meaningless once nothing is off-screen. */
  html body.deviceland-shop .related-product .slick-arrow,
  html body.deviceland-shop .related-product .icon-next-prev,
  html body.deviceland-shop .related-product .slick-dots,
  html body.deviceland-shop .related-product .nasa-slick-nav-wrap {
    display: none !important;
  }
}

/* ------------------------------------------------------------
   Mobile: title and price above the gallery
   Moved there by placeProductHead() in deviceland.js.
   ------------------------------------------------------------ */

/* No side padding: the ancestor region already carries the mobile gutter, and
   repeating it here was part of the same compounding problem. */
body.deviceland-shop .dl-mobile-head {
  padding: 0 0 18px;
}

html body.deviceland-shop .dl-mobile-head .product_title {
  margin-bottom: 10px;
}

html body.deviceland-shop .dl-mobile-head .woocommerce-product-details__short-description {
  margin: 0 0 10px;
  max-width: none;
}

html body.deviceland-shop .dl-mobile-head .woocommerce-product-details__short-description p {
  margin: 0;
}

html body.deviceland-shop .dl-mobile-head .dl-pdp-assurance {
  margin-top: 10px;
}

html body.deviceland-shop .dl-mobile-head p.price,
html body.deviceland-shop .dl-mobile-head .nasa-single-product-price {
  margin: 0;
}

/* The band under the header was not spacing, it was accumulated wrapper
   padding. Elessi nests .product-page > .nasa-ajax-store-wrapper >
   #nasa-ajax-store > .nasa-progress-bar-load-shop > .woocommerce-notices-
   wrapper between <main> and the first real content, and several carry their
   own vertical rhythm. Zeroed explicitly so the offset is stated in exactly
   one place — the #main rule above. */
body.deviceland-shop .product-page,
body.deviceland-shop .nasa-ajax-store-wrapper,
body.deviceland-shop #nasa-ajax-store,
body.deviceland-shop .nasa-ajax-store-content,
body.deviceland-shop .woocommerce-notices-wrapper:empty {
  padding-top: 0;
  margin-top: 0;
}

body.deviceland-shop .nasa-progress-bar-load-shop {
  display: none;
}

/* Elessi's own offset for the product block, on top of ours:
     .product-page .nasa-product-details-page          padding-top: 30px
     #main-content .product-page .nasa-product-details-page  padding-top: 10px
   Spacing above the product is set by the context strip below, so this is
   zeroed rather than fought. */
html body.deviceland-shop .product-page .nasa-product-details-page {
  padding-top: 0;
  top: 0;
}

/* ------------------------------------------------------------
   Category context strip — breadcrumb plus the lineup this
   product belongs to. Printed by deviceland_pdp_context().
   ------------------------------------------------------------ */

/* The strip reads as attached to the header, not floating below it.

   The complaint that this area "needs an image" is really a complaint about a
   missing edge: header, then undifferentiated paper, then a thin grey line
   drifting in space, then the product. Nothing tells the eye where the page
   begins. A hairline does that, and it costs no vertical space and no
   photograph. */
body.deviceland-shop .dl-context {
  padding-top: 12px; padding-bottom: 16px;
  border-bottom: 1px solid var(--hair-light);
  margin-bottom: 28px;
}

body.deviceland-shop .dl-context-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px 24px;
}

/* An "Accessories" heading with nothing under it.

   The section is a theme global tab whose body is the display_cross_sells
   shortcode. That shortcode correctly returns nothing when a product has no
   cross-sells, but the tab's heading and panel are printed by the theme
   regardless, leaving a titled rule across an empty band. Only 26 of the
   published products carry cross-sells, so this was the common case rather
   than the exception.

   Keyed on whether the panel actually rendered product cards, so a product
   that gains accessories shows the section again with no further change.

   The card is li.product-warp-item. An earlier version of this rule tested
   for li.product, which never matches, so the section was hidden on every
   product — including the ones that do have accessories. */
html body.deviceland-shop .ns-tab-item:has(.nasa-content-glb_tab):not(:has(.product-warp-item)) {
  display: none;
}

body.deviceland-shop .dl-crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

html body.deviceland-shop .dl-crumbs a,
html body.deviceland-shop .dl-crumbs span {
  color: var(--muted-fg);
  text-decoration: none;
}

html body.deviceland-shop .dl-crumbs a:hover {
  color: var(--on-paper);
}

html body.deviceland-shop .dl-crumbs [aria-current="page"] {
  color: var(--on-paper);
}

body.deviceland-shop .dl-crumb-sep {
  opacity: 0.4;
}

html body.deviceland-shop .dl-context-all {
  color: var(--on-paper);
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
}

body.deviceland-shop .product-page,
body.deviceland-shop .site-main,
body.deviceland-shop .nasa-product-details-page,
body.deviceland-shop .nasa-single-product-scroll {
  background: transparent;
}

/* ------------------------------------------------------------
   Removed: fabricated proof and borrowed credentials
   ------------------------------------------------------------

   .nasa-viewing prints "77 people are viewing this right now" from a random
   number. .safe-checkout prints a single bitmap carrying the Norton, Google
   Trusted Store, BBB and TRUSTe marks — certifications this shop does not
   hold, two of which are defunct brands. Both are the same class of thing the
   design system already rejected when it deleted a hardcoded bag count of "2":
   an unverifiable claim in the most credibility-sensitive position on the page.

   The real credentials — Apple Premier Partner, Apple Authorized Service
   Provider, 1985, the named owner, the named technician, 213 Google reviews —
   are all things this business can actually prove.

   .nasa-buy-now is also removed in PHP; this is the belt to that braces. It is
   a second primary CTA in a green that exists nowhere in the palette, and it
   competes with Add to cart for the same decision. */
body.deviceland-shop .nasa-toggle-layout-side-sidebar,
body.deviceland-shop .nasa-sidebar-single-product,
body.deviceland-shop .nasa-viewing,
body.deviceland-shop .safe-checkout,
body.deviceland-shop .nasa-buy-now,
body.deviceland-shop .nasa-detail-product-deal-countdown-label,
body.deviceland-shop .nasa-detail-product-deal-countdown,
body.deviceland-shop .nasa-product-variation-countdown,
body.deviceland-shop .nasa-single-product-deal-countdown,
body.deviceland-shop .countdown-label,
body.deviceland-shop .nasa-static-group-btn,
body.deviceland-shop .products-arrow {
  display: none !important;
}

/* Free shipping under Add to bag: one quiet line, the first half in ink. */
body.deviceland-shop .dl-pdp-ship {
  margin: 12px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted-fg, #6b6259);
}

body.deviceland-shop .dl-pdp-ship span {
  color: var(--on-paper, #1d1a17);
}

/* ------------------------------------------------------------
   Breadcrumb — restyled, not hidden. It is the only "where am I"
   affordance on a page reached from a category listing.
   ------------------------------------------------------------ */

body.deviceland-shop .nasa-breadcrumb,
body.deviceland-shop .woocommerce-breadcrumb {
  margin-bottom: 24px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

html body.deviceland-shop .nasa-breadcrumb,
html body.deviceland-shop .nasa-breadcrumb a,
html body.deviceland-shop .woocommerce-breadcrumb,
html body.deviceland-shop .woocommerce-breadcrumb a {
  color: var(--muted-fg);
}

html body.deviceland-shop .nasa-breadcrumb a:hover,
html body.deviceland-shop .woocommerce-breadcrumb a:hover {
  color: var(--on-paper);
}

/* ------------------------------------------------------------
   Gallery
   ------------------------------------------------------------

   The plate is WHITE, not the cream --surface used elsewhere.

   --surface exists because the homepage category photographs carry their own
   warm cream ground (sampled 251-255, 237-248, 209-227), so the tile has to
   sit just above the lightest of them or a seam shows. Apple's product
   photography is the opposite case: it is shot on pure white. Putting a white
   cutout on a cream plate draws exactly the seam --surface was invented to
   avoid, which is what you can see as a rectangle around each watch.

   So the well matches the photography, and the card reads as one white
   surface on cream paper — the same hairline-plus-radius treatment the
   homepage gives .spec-card and .proof-card. */
/* The card moved OFF the gallery wrapper and ONTO each image panel.

   Two things forced this. The wrapper needed overflow:hidden to clip its own
   radius, and position:sticky cannot function inside a clipped ancestor — so
   the thumbnail rail could never stick while that card existed. Separately,
   the thumbnails sat flush against the wrapper's rounded corner, so their 1px
   borders were being shaved off at the top and bottom of the column, which is
   the clipping visible in the screenshot.

   Panelling each image instead gives the stack the same card language the
   homepage uses for .spec-card and .proof-card, leaves the overflow chain
   clear for sticky, and lets the rail have real padding. */
/* ------------------------------------------------------------
   Product gallery (assets/js/pdp-gallery.js; owner feedback, Oct 15)
   One fixed-size main image, thumbnails beside it, a white lightbox.
   Elessi's stacked gallery stays in the page, hidden, as the source the
   script redraws from when a colour changes its photos.
   ------------------------------------------------------------ */
html body.deviceland-shop .product-gallery .dl-gal-source {
  display: none !important;
}

html body.deviceland-shop .dl-gal {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}

html body.deviceland-shop .dl-gal.is-single {
  grid-template-columns: minmax(0, 1fr);
}

html body.deviceland-shop .dl-gal-thumbs {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

html body.deviceland-shop .dl-gal.is-single .dl-gal-thumbs,
html body.deviceland-shop .dl-gal.is-single .dl-gal-nav,
html body.deviceland-shop .dl-gal.is-single .dl-gal-count {
  display: none;
}

html body.deviceland-shop .dl-gal-thumb,
html body.deviceland-shop .dl-gal-more {
  width: 76px;
  height: 76px;
  margin: 0;
  padding: 5px;
  border: 1px solid var(--hair-light);
  border-radius: var(--r-sm);
  background: #fff;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

html body.deviceland-shop .dl-gal-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

html body.deviceland-shop .dl-gal-thumb:hover,
html body.deviceland-shop .dl-gal-more:hover {
  border-color: var(--hair-light-2, rgba(22, 19, 15, 0.22));
}

html body.deviceland-shop .dl-gal-thumb.is-on,
html body.deviceland-shop .dl-gal-more.is-on {
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
}

html body.deviceland-shop .dl-gal-more {
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink);
}

/* The main image: one size whatever the photo, the photo contained. */
html body.deviceland-shop .dl-gal-stage {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--r-xl);
  background: #fff;
  box-shadow: 0 0 0 1px var(--hair-light), var(--e2);
  overflow: hidden;
}

html body.deviceland-shop .dl-gal-open {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 7%;
  border: 0;
  background: transparent;
  cursor: pointer;
}

html body.deviceland-shop .dl-gal-main {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

html body.deviceland-shop .dl-gal-nav,
html body.deviceland-shop .dl-lb-nav {
  position: absolute;
  top: 50%;
  z-index: 2;
  width: 42px;
  height: 42px;
  margin: -21px 0 0;
  padding: 0;
  border: 1px solid var(--hair-light);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 10px rgba(22, 19, 15, 0.12);
  cursor: pointer;
  transition: opacity 0.2s ease;
}

/* Chevrons drawn with borders, so no glyph can render as a box. */
html body.deviceland-shop .dl-gal-nav::before,
html body.deviceland-shop .dl-lb-nav::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 9px;
  height: 9px;
  border-top: 1.6px solid var(--ink);
  border-right: 1.6px solid var(--ink);
}

html body.deviceland-shop .dl-gal-prev::before,
html body.deviceland-shop .dl-lb-prev::before {
  transform: translate(-30%, -50%) rotate(-135deg);
}

html body.deviceland-shop .dl-gal-next::before,
html body.deviceland-shop .dl-lb-next::before {
  transform: translate(-70%, -50%) rotate(45deg);
}

html body.deviceland-shop .dl-gal-prev {
  left: 14px;
}

html body.deviceland-shop .dl-gal-next {
  right: 14px;
}

/* Shown on hover (and to the keyboard); always shown where there is no
   hover, alongside swipe. */
html body.deviceland-shop .dl-gal-nav {
  opacity: 0;
}

html body.deviceland-shop .dl-gal-stage:hover .dl-gal-nav,
html body.deviceland-shop .dl-gal-nav:focus-visible {
  opacity: 1;
}

@media (hover: none) {
  html body.deviceland-shop .dl-gal-nav {
    opacity: 1;
  }
}

html body.deviceland-shop .dl-gal-count {
  position: absolute;
  right: 14px;
  bottom: 12px;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.94);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--muted-fg);
}

html body.deviceland-shop .dl-gal-stage .btn-wishlist {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 3;
}

/* Scroll naturally past the gallery to the description: nothing pinned. */
html body.deviceland-shop .nasa-single-product-scroll .product-gallery,
html body.deviceland-shop .nasa-single-product-scroll .product-info {
  position: relative !important;
  top: auto !important;
  transform: none !important;
}

/* Phones and narrow tablets: the main image first, thumbnails in a row
   below it that scrolls sideways. */
@media (max-width: 849px) {
  html body.deviceland-shop .dl-gal {
    grid-template-columns: minmax(0, 1fr);
  }

  html body.deviceland-shop .dl-gal-thumbs {
    order: 2;
    flex-direction: row;
    overflow-x: auto;
    padding-bottom: 4px;
    scrollbar-width: none;
  }

  html body.deviceland-shop .dl-gal-thumb,
  html body.deviceland-shop .dl-gal-more {
    flex: none;
    width: 62px;
    height: 62px;
  }

  html body.deviceland-shop .dl-gal-nav {
    width: 36px;
    height: 36px;
    margin-top: -18px;
  }
}

/* The lightbox: white, the photo as large as the screen allows. */
html.dl-lb-open,
html.dl-lb-open body {
  overflow: hidden;
}

html body .dl-lb {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  z-index: 100000;
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr) 72px;
  grid-template-rows: minmax(0, 1fr) auto;
  background: #fff;
}

html body .dl-lb[hidden] {
  display: none;
}

html body .dl-lb-figure {
  grid-column: 2;
  grid-row: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 56px 0 16px;
  min-height: 0;
}

html body .dl-lb-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

html body .dl-lb-close {
  position: absolute;
  top: 18px;
  right: 18px;
  z-index: 2;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(22, 19, 15, 0.14);
  border-radius: 50%;
  background: #fff;
  cursor: pointer;
}

html body .dl-lb-close::before,
html body .dl-lb-close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 1.6px;
  background: #16130f;
}

html body .dl-lb-close::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

html body .dl-lb-close::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

html body .dl-lb .dl-lb-nav {
  position: relative;
  top: auto;
  align-self: center;
  justify-self: center;
  margin: 0;
}

html body .dl-lb .dl-lb-prev {
  grid-column: 1;
  grid-row: 1;
}

html body .dl-lb .dl-lb-next {
  grid-column: 3;
  grid-row: 1;
}

html body .dl-lb-foot {
  grid-column: 1 / -1;
  grid-row: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 0 16px 18px;
}

html body .dl-lb-strip {
  display: flex;
  gap: 8px;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}

html body .dl-lb-thumb {
  flex: none;
  width: 56px;
  height: 56px;
  padding: 4px;
  border: 1px solid rgba(22, 19, 15, 0.12);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
}

html body .dl-lb-thumb.is-on {
  border-color: #16130f;
  box-shadow: 0 0 0 1px #16130f;
}

html body .dl-lb-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

html body .dl-lb-count {
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: #6b6259;
}

html body .dl-lb.is-single .dl-lb-nav,
html body .dl-lb.is-single .dl-lb-foot {
  display: none;
}

@media (max-width: 849px) {
  html body .dl-lb {
    grid-template-columns: 0 minmax(0, 1fr) 0;
  }

  html body .dl-lb .dl-lb-nav {
    display: none;
  }

  html body .dl-lb-figure {
    padding: 72px 12px 12px;
  }
}

html body.deviceland-shop .woocommerce-product-gallery {
  background: transparent;
  border-radius: 0;
  overflow: visible;
  box-shadow: none;
}

/* Sticky needs an unclipped ancestor chain all the way up. */
body.deviceland-shop .woocommerce-product-gallery__wrapper,
body.deviceland-shop .woocommerce-product-gallery__wrapper > .columns,
body.deviceland-shop .product-gallery,
body.deviceland-shop .nasa-single-product-scroll,
body.deviceland-shop .nasa-product-details-page,
body.deviceland-shop .row.focus-info {
  overflow: visible;
}

/* One well, not six cards.

   The previous pass panelled each image and then tried to space them with
   `.nasa-item-main-image-wrap + .nasa-item-main-image-wrap`, which never
   matched: Elessi wraps every image in its own `.item-wrap`, so no two image
   wraps are ever adjacent siblings. Hence six borders touching.

   Rather than fix the selector, the treatment changed. Six identically
   bordered cards stacked vertically is repetitive — it reads as a pile of
   components rather than one product — and it puts six competing outlines
   opposite the swatch chips. This is one white surface holding many views of
   a single object, which is what the stack actually is, and it matches how
   the design treats the hero: one photographic ground.

   Inside a white well a gap is invisible, so the separator is a hairline and
   the breathing room is padding. .nasa-main-wrap is a sibling of the thumb
   rail, not an ancestor, so clipping it here does not affect sticky. */
html body.deviceland-shop .nasa-main-wrap {
  background: #fff;
  border-radius: var(--r-xl);
  overflow: hidden;
  box-shadow: 0 0 0 1px var(--hair-light), var(--e2);
}

html body.deviceland-shop .nasa-item-main-image-wrap,
html body.deviceland-shop .woocommerce-product-gallery__image {
  background: #fff;
  border-radius: 0;
  box-shadow: none;
}

body.deviceland-shop .main-images .item-wrap {
  padding: 20px;
}

body.deviceland-shop .main-images .item-wrap + .item-wrap {
  border-top: 1px solid var(--hair-light);
}

/* The rail: sticky, padded so the chip borders are never shaved, and no
   longer carrying a background of its own now that it sits on paper. */
html body.deviceland-shop .nasa-thumb-wrap {
  position: sticky;
  top: calc(var(--head-measured, 69px) + 20px);
  align-self: flex-start;
  padding: 2px 14px 2px 2px;
  background: transparent;
  border-right: 0;
  max-height: calc(100vh - var(--head-measured, 69px) - 40px);
  overflow-y: auto;
  scrollbar-width: thin;
}

html body.deviceland-shop .nasa-thumbnail-default-wrap {
  background: transparent;
}

body.deviceland-shop .nasa-wrap-item-thumb {
  border-radius: var(--r-sm);
  overflow: hidden;
  border: 1px solid var(--hair-light);
  background: #fff;
}

html body.deviceland-shop .nasa-wrap-item-thumb.nasa-active {
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
}

/* The black hairline above the Mac mini's photograph.
   ------------------------------------------------------------
   Not a border bug — an empty chip wearing the active outline.

   Measured in the live markup for Mac mini M4, whose parent product carries
   one image and no gallery:

     <div class="nasa-wrap-item-thumb nasa-active" data-key="0"
          data-thumb_org=".../woocommerce-placeholder-350x350.png">
       <a href="javascript:void(0);" class="active-thumbnail"></a>
     </div>

   The anchor has no <img> inside it, and data-thumb_org resolved to
   WooCommerce's placeholder. So the chip has no content, collapses to zero
   height, and the rules above then paint its 1px border and 1px ink shadow —
   giving a thumb-width, ~3px tall black bar sitting above the image well.

   The rail is also meaningless at a single image: there is nothing to navigate
   between. So an imageless chip is removed, and a rail left holding only one
   chip stops reserving a column. Both are display decisions and write nothing,
   so a product that gains real gallery images gets its rail back with no
   further change.

   This is a guard, not the cure. A Mac mini with one photograph is an import
   defect — its variations each carry six localized images — and it is fixed
   where the parent gallery is composed, not here. This only stops the missing
   data from being drawn as an artifact. */
html body.deviceland-shop .nasa-wrap-item-thumb:not(:has(img)) {
  display: none;
}

html body.deviceland-shop .nasa-thumb-wrap:not(:has(.nasa-wrap-item-thumb img)) {
  display: none;
}

/* Below the two-column breakpoint the rail stops being a column, so sticky
   would pin it over the content it belongs to.

   The !important on position and height is deliberate, and is the only place
   in this file where !important overrides geometry rather than simply hiding
   theme furniture. Elessi's load_scroll_single_product() writes inline
   position, top, width and height onto .nasa-product-info-scroll and
   .nasa-single-product-thumbnails to drive its scroll-synced two-column
   layout. Inline styles outrank any selector, so a stylesheet cannot undo
   them — and stale desktop values are the most likely source of the tall cream
   void between the gallery and the product details on a phone. */
@media (max-width: 767px) {
  html body.deviceland-shop .nasa-product-info-scroll,
  html body.deviceland-shop .nasa-single-product-thumbnails,
  html body.deviceland-shop .nasa-main-image-default-wrap {
    position: static !important;
    top: auto !important;
    left: auto !important;
    width: 100% !important;
    height: auto !important;
    margin-top: 0 !important;
  }

  html body.deviceland-shop .product-gallery,
  html body.deviceland-shop .product-info {
    float: none;
    margin-bottom: 0;
  }

  html body.deviceland-shop .nasa-thumb-wrap {
    position: static;
    max-height: none;
    overflow: visible;
    padding: 2px;
  }
}

/* The 2998px void — at EVERY width, not just phones.
   ------------------------------------------------------------
   Elessi's load_scroll_single_product() writes a min-height onto the two
   columns after load so they match, which is what its scroll-synced layout
   needs. DevTools caught it as min-height: 2998px.

   That equalisation is pure cost here. The thumbnail rail is sticky through
   CSS, so nothing in this design depends on the columns being the same height,
   and whichever column is shorter gets the taller one's height reserved as
   empty paper below its content. The first version of this reset was scoped to
   <=767px, which fixed the phone and left the desktop gap — the regression
   after the gallery became one white well and stopped coincidentally matching
   the summary's height.

   Ungated now: the columns size to their content at all widths and the tabs
   follow immediately after the taller one. !important is required because the
   value arrives as a JS-written inline style. */
html body.deviceland-shop .nasa-single-product-scroll,
html body.deviceland-shop .nasa-product-info-wrap,
html body.deviceland-shop .nasa-product-info-scroll,
html body.deviceland-shop .row.focus-info,
html body.deviceland-shop .product-gallery,
html body.deviceland-shop .product-info,
html body.deviceland-shop .woocommerce-product-gallery,
html body.deviceland-shop .nasa-main-wrap {
  min-height: 0 !important;
  height: auto !important;
}

/* ============================================================
   Sticky buy bar — kept, but reduced to one job
   ============================================================

   KEPT, because the argument for it is real: this page runs several screens
   past the buy box — description, spec table, reviews, accessories, related —
   and without a persistent control someone who has decided has to scroll back
   up to act. That is the strongest case there is for sticky chrome.

   REDUCED, because what it was doing is the opposite of what this design does
   everywhere else. Elessi clones the entire buy form into it, so a 64px strip
   carried the whole seven-axis configurator: six rows of swatches, several of
   them struck through for unavailable combinations. The densest, most
   conditional thing on the page, rendered in the least space, with
   strikethroughs that read as broken rather than unavailable — and directly
   competing with the real picker it was copied from.

   A sticky bar should re-offer the ACTION, not re-offer the DECISION. The
   configuration belongs where there is room to think about it. So the swatch
   matrix, the attribute labels and the availability rows come out, and what
   stays is what someone who has already chosen needs: what it is, what it
   costs, how many, add it, or call.

   Elessi marks .nasa-not-in-sticky on the pieces it already knew to exclude,
   which is the same judgement one step short.
   ============================================================ */

html body.deviceland-shop .nasa-add-to-cart-fixed {
  background: rgba(248, 242, 232, 0.94);
  backdrop-filter: blur(18px) saturate(1.5);
  -webkit-backdrop-filter: blur(18px) saturate(1.5);
  border-top: 1px solid var(--hair-light);
  box-shadow: 0 -6px 24px -12px rgba(20, 17, 14, 0.18);
  padding: 12px 0;
  z-index: 700;
}

/* The configurator comes out.
   ------------------------------------------------------------
   Every selector here used to name the page's own classes, and none of them
   matched, because Elessi does not move the buy form into the bar -- it builds
   a parallel copy whose every class carries a "-clone" suffix:

     .nasa-attr-ux        ->  .nasa-attr-ux-clone
     .nasa-attr-ux_wrap   ->  .nasa-attr-ux_wrap-clone
     table.variations     ->  (absent; the markup is rebuilt, not copied)

   So the whole block was inert and the seven-axis matrix this section exists
   to remove was still being rendered into a 64px strip. It also explains the
   second symptom: the swatch clones are inert proxies that delegate through
   data-target, and while the real picker is offscreen there is nothing for
   them to delegate to -- they look interactive, do nothing, and go on showing
   whatever was selected when the clone was built.

   Hiding the wrapper rather than the individual chips means a future Elessi
   change to the chip markup cannot quietly resurrect the matrix. */
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-fixed-product-variations-wrap,
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-fixed-product-variations,
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-attr-ux_wrap-clone,
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-attr-ux-clone,
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-toggle-variation_wrap,
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-attr-ux,
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-attrs-ux,
html body.deviceland-shop .nasa-add-to-cart-fixed table.variations,
html body.deviceland-shop .nasa-add-to-cart-fixed .variations,
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-wrap-label,
html body.deviceland-shop .nasa-add-to-cart-fixed .woocommerce-variation-availability,
html body.deviceland-shop .nasa-add-to-cart-fixed .woocommerce-variation-description,
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-single-variation-wrap-desc,
html body.deviceland-shop .nasa-add-to-cart-fixed .reset_variations,
html body.deviceland-shop .nasa-add-to-cart-fixed .dl-pdp-assurance,
html body.deviceland-shop .nasa-add-to-cart-fixed .dl-pdp-trust,
html body.deviceland-shop .nasa-add-to-cart-fixed .woocommerce-product-details__short-description {
  display: none !important;
}

/* Two prices, one of them wrong.
   ------------------------------------------------------------
   .nasa-title-clone carries the parent's "From $449.00" and never updates,
   while .nasa-single-btn-clone carries the configured price and does. Showing
   both puts a stale figure beside a live one; on the iPad (A16) that read
   "From $449.00" next to $978.00. The title keeps the name, the button side
   keeps the price. */
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-title-clone .price {
  display: none !important;
}

/* What remains, on one line, on the same measure as everything else.
   ------------------------------------------------------------
   Removing the matrix left the bar with two groups and nothing holding them
   to the page's measure, so on a wide screen the name sat against the far
   left and the buttons against the far right with a screen of nothing
   between. The masthead and footer both sit on --shell; the bar reads as part
   of the same chrome once it does too. */
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-wrap-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  max-width: var(--shell);
  margin-left: auto; margin-right: auto;
  padding-left: var(--gut); padding-right: var(--gut);
}

html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-fixed-product-info {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

/* The configuration, stated rather than offered.
   ------------------------------------------------------------
   Written by updateStickyConfigSummary() from the form's own selects on every
   variation event, so it cannot drift from the picker the way Elessi's cloned
   chips did. Secondary to the product name: this is confirmation of a decision
   already made, not a second place to make it. */
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-title-clone {
  min-width: 0;
}

html body.deviceland-shop .nasa-add-to-cart-fixed .dl-sticky-config {
  display: block;
  margin-top: 1px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.004em;
  line-height: 1.35;
  color: rgba(20, 17, 14, 0.58);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The clone's title is .nasa-title-clone h3, not .product_title -- the same
   suffix mismatch as the block above, which is why the bar was inheriting the
   page's 3.1rem display heading instead of this. */
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-title-clone h3,
html body.deviceland-shop .nasa-add-to-cart-fixed .product_title,
html body.deviceland-shop .nasa-add-to-cart-fixed .nasa-title-fixed {
  margin: 0;
  font-family: var(--sans);
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: -0.008em;
  line-height: 1.3;
  color: var(--on-paper);
}

html body.deviceland-shop .nasa-add-to-cart-fixed .price,
html body.deviceland-shop .nasa-add-to-cart-fixed .price .amount {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--on-paper);
}

html body.deviceland-shop .nasa-add-to-cart-fixed img {
  width: 44px;
  height: 44px;
  object-fit: contain;
  padding: 4px;
  background: #fff;
  border: 1px solid var(--hair-light);
  border-radius: var(--r-sm);
}

/* Wishlist and compare sit over white now, so they need ink rather than the
   theme's grey-on-grey. */
html body.deviceland-shop .product-gallery .nasa-wishlist-icon,
html body.deviceland-shop .product-gallery .compare,
html body.deviceland-shop .product-gallery .quick-view {
  color: rgba(20, 17, 14, 0.55);
}

html body.deviceland-shop .product-gallery .nasa-wishlist-icon:hover,
html body.deviceland-shop .product-gallery .compare:hover {
  color: var(--ember);
}

/* ------------------------------------------------------------
   Title, price, description
   ------------------------------------------------------------ */

body.deviceland-shop .product_title,
body.deviceland-shop h1.product_title {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2rem, 3.4vw, 3.1rem);
  line-height: 0.97;
  letter-spacing: -0.02em;
  color: var(--on-paper);
}

/* Prices are DM Sans across the whole site.
   The display serif is reserved for editorial numerals — 1985, 3pm, $0 in
   .spec-val / .stat-val / .score-val. On the homepage .prod-price and
   .tile-price are both DM Sans, so setting this page's price in Instrument
   Serif made the same number render in two different faces depending on which
   page you were looking at. Corrected to match the homepage.

   Both price slots get identical type: the summary carries the "From" floor,
   the one above Add to cart carries the exact configuration. Same face, same
   size, so they read as one system rather than two components. */
/* One price: the build's price is shown under the title (chrome.php,
   deviceland_pdp_single_price), so WooCommerce's second copy below the
   options is not drawn. */
html body.deviceland-shop .single_variation .woocommerce-variation-price {
  display: none;
}

html body.deviceland-shop .product-info > .price,
html body.deviceland-shop p.price,
html body.deviceland-shop .nasa-single-product-price,
html body.deviceland-shop .woocommerce-variation-price .price {
  font-family: var(--sans);
  font-size: clamp(1.35rem, 1.9vw, 1.7rem);
  font-weight: 500;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
  color: var(--on-paper);
}

html body.deviceland-shop .price del {
  color: var(--muted-fg);
  font-weight: 400;
}

html body.deviceland-shop .price ins {
  text-decoration: none;
}

/* A special (inc/specials.php): the price, then "Was $1,299 · Save $39"
   on its own quiet line. */
html body.deviceland-shop .price .dl-was {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--muted-fg);
}

html body.deviceland-shop .price .dl-was del {
  color: inherit;
  text-decoration-thickness: 1px;
}

html body.deviceland-shop .price .dl-was .amount {
  font-size: inherit;
}

body.deviceland-shop .woocommerce-product-details__short-description {
  max-width: 34rem;
}

html body.deviceland-shop .woocommerce-product-details__short-description,
html body.deviceland-shop .woocommerce-product-details__short-description p {
  color: rgba(22, 19, 15, 0.72);
  font-size: 15.5px;
  line-height: 1.62;
}

/* "Touch display · every configuration" under the tagline, on Macs whose
   Display spec lists touch (deviceland_pdp_touch_tag). The homepage hero's
   glyph, in ink: one press-and-ripple after load, then still;
   no motion under reduced motion. Keyframes repeat deviceland.css's, which the
   product page does not load. */
body.deviceland-shop .dl-pdp-touch {
  display: flex;
  align-items: center;
  gap: 8px;
  /* The tagline above ends in 20px (margins collapse), so 20px below keeps the
     tag centred between it and the availability line (owner saw 20 vs ~4). */
  margin: 0 0 20px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--ink);
}

body.deviceland-shop .dl-pdp-touch .dl-touch-glyph {
  flex: none;
  overflow: visible;
}

body.deviceland-shop .dl-pdp-touch .dl-touch-ripple,
body.deviceland-shop .dl-pdp-touch .dl-touch-hand {
  transform-box: view-box;
  transform-origin: 11px 11.5px;
}

body.deviceland-shop .dl-pdp-touch .dl-touch-ripple {
  animation: dl-touch-ripple 1.6s ease-out 0.9s 1 both;
}

body.deviceland-shop .dl-pdp-touch .dl-touch-ripple.r2 {
  animation-delay: 1.05s;
}

body.deviceland-shop .dl-pdp-touch .dl-touch-hand {
  animation: dl-touch-press 1.6s ease-out 0.9s 1 both;
}

/* Every cycle starts and ends fully drawn, so the icon is complete before,
   between and after pulses in every engine. No hover replay: CSS can only
   replay by switching animation names, and switching back on mouse-out
   re-ran the load pulse with a blink (reviewer, Nov 7). */
@keyframes dl-touch-ripple {
  0%   { opacity: 1; transform: scale(1); }
  8%   { opacity: 0; transform: scale(0.45); }
  20%  { opacity: 0; transform: scale(0.45); }
  60%  { opacity: 1; transform: scale(1); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes dl-touch-press {
  0%, 100% { transform: translateY(0); }
  10%      { transform: translateY(1.2px); }
  25%      { transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  body.deviceland-shop .dl-pdp-touch .dl-touch-ripple,
  body.deviceland-shop .dl-pdp-touch .dl-touch-hand {
    animation: none !important;
  }
}

html body.deviceland-shop .dl-mobile-head .dl-pdp-touch {
  margin: 0 0 10px;
}

html body.deviceland-shop .nasa-add-to-cart-fixed .dl-pdp-touch {
  display: none !important;
}

/* Store, availability and selected SKU, printed by deviceland_pdp_assurance(). */
body.deviceland-shop .dl-pdp-assurance {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  margin: 16px 0 0;
  font-size: 13px;
  font-weight: 500;
  color: var(--muted-fg);
}

body.deviceland-shop .dl-pdp-assurance-dot {
  opacity: 0.45;
}

body.deviceland-shop .dl-pdp-sku,
body.deviceland-shop .dl-pdp-stock-qty {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
}

body.deviceland-shop .dl-pdp-sku[hidden],
body.deviceland-shop .dl-pdp-stock-qty[hidden] {
  display: none;
}

/* Staff-only source proof under the assurance line (deviceland_pdp_assurance). */
body.deviceland-shop .dl-pdp-sources {
  margin: 10px 0 0;
  padding: 10px 12px;
  border: 1px dashed rgba(22, 19, 15, 0.18);
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted-fg);
}

body.deviceland-shop .dl-pdp-sources[hidden] {
  display: none;
}

body.deviceland-shop .dl-pdp-sources ul {
  margin: 4px 0;
  padding: 0;
  list-style: none;
}

body.deviceland-shop .dl-pdp-source {
  display: grid;
  grid-template-columns: 9em 1fr;
  column-gap: 10px;
}

body.deviceland-shop .dl-pdp-source-when {
  grid-column: 2;
  opacity: 0.8;
}

body.deviceland-shop .dl-pdp-source-name,
body.deviceland-shop .dl-pdp-sources-title {
  font-weight: 600;
}

body.deviceland-shop .dl-pdp-sources-title,
body.deviceland-shop .dl-pdp-sources-shown {
  margin: 0;
}

body.deviceland-shop .dl-pdp-source.is-used .dl-pdp-source-value {
  font-weight: 600;
  color: var(--fg, #16130f);
}

body.deviceland-shop .dl-pdp-source.is-stale .dl-pdp-source-when {
  color: #9a5b00;
}

/* The shelf (accessories, related products) lives in shelf.css. */

/* Ingram per warehouse, under the sources. */
body.deviceland-shop .dl-pdp-wh {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed rgba(22, 19, 15, 0.18);
}

body.deviceland-shop .dl-pdp-wh .dl-pdp-source-when:empty {
  display: none;
}

body.deviceland-shop .dl-pdp-wh-again {
  margin-top: 6px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--fg, #16130f);
  text-decoration: underline;
  cursor: pointer;
}

body.deviceland-shop .dl-pdp-sku b,
body.deviceland-shop .dl-pdp-stock-qty b {
  font-weight: 600;
  letter-spacing: 0.025em;
  color: var(--ink-2);
}

/* ------------------------------------------------------------
   Attribute swatches
   ------------------------------------------------------------

   Elessi's layout for .nasa-attr-ux_wrap is left alone; only the chip surface
   changes. The ink/paper pair is the same one .btn-ink uses on the homepage,
   so a selected chip and a primary button are visibly the same material.
   ------------------------------------------------------------ */

body.deviceland-shop table.variations .label label,
body.deviceland-shop table.variations th.label label {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

html body.deviceland-shop table.variations .label label {
  color: var(--muted-fg);
}

body.deviceland-shop .nasa-attr-ux {
  border-radius: var(--r-pill);
  font-size: 13.5px;
  font-weight: 500;
  transition: border-color var(--dur-ui) var(--ease),
    background var(--dur-ui) var(--ease), color var(--dur-ui) var(--ease);
}

html body.deviceland-shop .nasa-attr-ux {
  border: 1px solid var(--hair-light-2);
  background: var(--bone);
  color: var(--on-paper);
}

html body.deviceland-shop .nasa-attr-ux:hover {
  border-color: var(--ink);
  background: var(--bone);
  color: var(--on-paper);
}

/* The state dynamic.css was recolouring: ink ground, warm off-white text. */
html body.deviceland-shop .nasa-attr-ux.selected,
html body.deviceland-shop .nasa-attr-ux.nasa-active,
html body.deviceland-shop .nasa-attr-ux-label.selected,
html body.deviceland-shop .nasa-attr-ux-label.nasa-active,
html body.deviceland-shop .nasa-color-small-square .nasa-attr-ux-label.selected,
html body.deviceland-shop .nasa-label-small-square-1 .nasa-attr-ux-label.selected {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--on-ink);
}

/* Colour chips keep their swatch legible, so the selected state is a ring
   rather than an ink fill. */
html body.deviceland-shop .nasa-attr-ux-color.selected,
html body.deviceland-shop .nasa-attr-ux-color.nasa-active,
html body.deviceland-shop .nasa-color-small-square .nasa-attr-ux-color.selected,
html body.deviceland-shop .nasa-color-small-square .nasa-attr-ux-color:hover {
  background: var(--bone);
  color: var(--on-paper);
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}

html body.deviceland-shop .reset_variations {
  font-size: 12px;
  color: var(--muted-fg);
}

/* ------------------------------------------------------------
   Add to cart row
   ------------------------------------------------------------ */

body.deviceland-shop .woocommerce-variation-availability p {
  font-size: 13px;
  color: var(--muted-fg);
}

html body.deviceland-shop .single_add_to_cart_button,
html body.deviceland-shop .product-info .cart .single_add_to_cart_button {
  border: 1px solid var(--ink);
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--on-ink);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-transform: none;
  box-shadow: var(--sh-1);
  transition: transform var(--dur-ui) var(--ease),
    box-shadow var(--dur-ui) var(--ease), background var(--dur-ui) var(--ease);
}

html body.deviceland-shop .single_add_to_cart_button:hover,
html body.deviceland-shop .product-info .cart .single_add_to_cart_button:hover {
  background: var(--ink-2);
  border-color: var(--ink-2);
  color: var(--on-ink);
  transform: translateY(-1px);
  box-shadow: var(--sh-2);
}

/* The inventory phone CTA, printed by deviceland_pdp_call().

   Rendered only for on-order and explicitly-zero stock. Add to cart is hidden
   in both, so this is the only action on the page and has to be a filled
   primary. Dropping it to the cream outline would leave the page with no
   primary at all, which is the one change that really would suppress calls.

   Two earlier passes got this wrong in the same direction, and it is worth
   recording why. The button was a phone number set as the largest thing in
   the pill, over an uppercased tracked caption, and then the pill was filled
   with saturated ember. Each step read louder than the last: a number as the
   payload is the grammar of a local service ad, caps is grammar this page
   reserves for LABELS (COLOR:, CAPACITY:) and never for controls, and a
   saturated fill made it the most urgent object in a cream-and-espresso
   column — louder than the price it sat under. Three urgency signals stacked
   on the one control that should feel like service.

   The elevated version of this exact control was already in the header:

     .masthead-call   cream pill, hairline, 15px ember handset, sentence case

   and the page's own voice for calling is the quiet "Walk in — no appointment
   · Call to confirm" under the title. So the button drops to that register:
   sentence case at 14px/500 — identical type to .single_add_to_cart_button,
   the control it replaces — with the handset as the only ember on it. Ember
   as an icon accent is precisely what the hierarchy note below describes, and
   it measures 4.01:1 on ink, clear of the 3:1 floor for graphics; the darker
   --ember-deep measured 2.55:1 here and would have failed.

   Ink, not ember, for the fill. Calling IS the commercial action in these
   states, and ink is what the commercial action looks like on every other
   page. Filling it ember spent the loudest colour in the system on it and
   competed with the price; the handset carries "this dials" at a fraction of
   the volume.

   The number is no longer in the button at all — see the note in chrome.php
   for why it moved into the caption, which is a desktop functionality fix as
   much as a visual one. */
html body.deviceland-shop .dl-pdp-call {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 46px;
  padding: 0 24px;
  border: 1px solid var(--ink);
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--on-ink);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: var(--sh-1);
  transition: transform var(--dur-ui) var(--ease),
    box-shadow var(--dur-ui) var(--ease), background var(--dur-ui) var(--ease);
}

/* The one ember on the control, and the only thing signalling "this dials".
   Matches the masthead handset at 15px.

   overflow: visible because the icon's own geometry overflows its viewBox.
   Traced, the path spans x 6.1-24.6 and stroke-width 2 adds a unit each side,
   so the painted edge lands at x 25.6 inside a `0 0 24 24` box — 1.6 units
   clipped, which is a flat 1.0px cut off the handset at 15px. The viewBox is
   left alone rather than retuned so this stays byte-identical to the masthead
   markup; .masthead-call carries the same path and the same 1px clip. */
html body.deviceland-shop .dl-pdp-call-icon {
  flex: 0 0 auto;
  overflow: visible;
  color: var(--ember);
}

/* One flex item holding both spans, so the 9px gap applies only between the
   handset and the copy and " · " can space itself as normal text. */
html body.deviceland-shop .dl-pdp-call-copy {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--on-ink);
}

html body.deviceland-shop .dl-pdp-call-label {
  font-size: inherit;
  font-weight: inherit;
  text-transform: none;
  color: inherit;
}

/* The number appears exactly once near the CTA, on the surface that can use
   it, and the breakpoint decides which surface that is.

   Touch  — tel: works, so the button is a verb and the number sits in the
            caption, which is the only visible copy of it on a phone because
            .masthead-call is display:none below 768px.
   Desktop — tel: is unreliable, so the button carries the number and the
            caption drops it. "Built to order · call to confirm your delivery
            date" is still a grammatical sentence without it, which is why the
            anchor can simply be hidden rather than the copy rewritten.

   Same 14px/500 as the label. The number being in the button is not what made
   the old design read as an ad; that was 19px/600 under a tracked uppercase
   caption on a saturated fill. At button type size it is just a label. */
html body.deviceland-shop .dl-pdp-call-dial {
  display: none;
  font-variant-numeric: tabular-nums;
}

@media (hover: hover) and (pointer: fine) {
  html body.deviceland-shop .dl-pdp-call-dial {
    display: inline;
  }

  html body.deviceland-shop .dl-pdp-note-tel {
    display: none;
  }
}

html body.deviceland-shop .dl-pdp-call:hover,
html body.deviceland-shop .dl-pdp-call:focus-visible {
  background: var(--ink-2);
  border-color: var(--ink-2);
  color: var(--on-ink);
  transform: translateY(-1px);
  box-shadow: var(--sh-2);
}

/* The number, in the sentence. Ink rather than --muted-fg so it is the
   scannable part of the caption (17.6:1 on paper against the sentence's
   4.89:1) without being another loud element. */
html body.deviceland-shop .dl-pdp-note-tel {
  color: var(--on-paper);
  font-weight: 500;
  text-decoration: none;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  border-bottom: 1px solid var(--hair-light-2);
}

html body.deviceland-shop .dl-pdp-note-tel:hover,
html body.deviceland-shop .dl-pdp-note-tel:focus-visible {
  color: var(--ember-deep);
  border-bottom-color: var(--ember-deep);
}

html body.deviceland-shop .dl-pdp-call[hidden],
html body.deviceland-shop .dl-pdp-inventory-note[hidden] {
  display: none !important;
}

/* Sits on its own line under the button, not beside it: flex-basis 100% is
   what stops it from squeezing the pill in the add-to-cart row. */
html body.deviceland-shop .dl-pdp-inventory-note {
  display: block;
  flex-basis: 100%;
  width: 100%;
  margin-top: 10px;
  color: var(--muted-fg);
  font-size: 12px;
  line-height: 1.45;
  letter-spacing: 0.01em;
}

html body.deviceland-shop form.variations_form.dl-inventory-call-only .quantity,
html body.deviceland-shop form.variations_form.dl-inventory-call-only .single_add_to_cart_button,
html body.deviceland-shop .nasa-add-to-cart-fixed.dl-inventory-call-only .quantity,
html body.deviceland-shop .nasa-add-to-cart-fixed.dl-inventory-call-only .single_add_to_cart_button,
/* Simple products carry it on the body, because they have no variation
   script to put it on the form — which is why a whole class of product
   showed Add to cart and Order by phone together. */
html body.deviceland-shop.dl-inventory-call-only form.cart .quantity,
html body.deviceland-shop.dl-inventory-call-only form.cart .single_add_to_cart_button,
html body.deviceland-shop.dl-inventory-call-only .nasa-add-to-cart-fixed .quantity,
html body.deviceland-shop.dl-inventory-call-only .nasa-add-to-cart-fixed .single_add_to_cart_button {
  display: none !important;
}

/* The gallery's "Sold Out" badge, on the products where it is a lie.
   ------------------------------------------------------------
   Set by the parent theme from Woo's stock_status, which is outofstock for an
   on-order part even though Apple still supplies it. Measured on the USB-C to
   3.5mm cable: badge said Sold Out, CTA beside it said Call to order. The
   badge is the wrong one, and its job — "you cannot buy this right now" — is
   already done by the absent Add to cart and the phone CTA that replaced it.

   body.dl-inventory-on-order is added for an on_order simple product or a
   variable parent with at least one on_order child. The variation-change
   handler removes it again for an explicitly unavailable selection. */
html body.deviceland-shop.dl-inventory-on-order .out-of-stock-label {
  display: none !important;
}

/* Woo's own availability line is suppressed in the two call states, and only
   there.

   Measured on the on-order iPad: the page stacked "Out of stock", then CALL TO
   SPECIAL ORDER, then "Made to order · allow several weeks" — three sentences
   for one fact, and the first of them argues with the other two. A made-to-
   order unit is not a dead end, which is precisely what "Out of stock" reads
   as.

   The button and its caption already carry both the state and the action, so
   the generic line is the one that goes. It is untouched everywhere else,
   including ordinary in-stock and back-order products. */
html body.deviceland-shop form.variations_form.dl-inventory-call-only .woocommerce-variation-availability,
html body.deviceland-shop .product-info .dl-inventory-call-only .woocommerce-variation-availability {
  display: none !important;
}

/* Quantity stepper.

   Elessi builds this as an absolutely-positioned pair against a fixed-height
   input: .plus and .minus are 21px tall each, stacked at right:0, against a
   42px input. The previous pass restyled the borders and radius of those three
   parts independently and broke the arithmetic — 21+21 plus their own borders
   no longer equalled the input, so the pair stood taller than the box it was
   attached to.

   Rather than patch three sets of numbers, the border and radius move to the
   .quantity container and the parts inside become borderless. The stepper is
   then one object by construction: 46px tall, 44px of interior, two 22px
   halves. It cannot drift again, and it applies to the sticky clone Elessi
   injects on scroll because nothing here is scoped to .product-info. */
html body.deviceland-shop .quantity {
  position: relative;
  float: none;
  display: inline-block;
  vertical-align: middle;
  width: 76px;
  height: 46px;
  border: 1px solid var(--hair-light-2);
  border-radius: var(--r-sm);
  background: var(--bone);
  overflow: hidden;
}

html body.deviceland-shop .quantity .input-text.qty,
html body.deviceland-shop .quantity input.qty {
  width: 48px;
  height: 44px;
  line-height: 44px;
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--on-paper);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 500;
  text-align: center;
  font-variant-numeric: tabular-nums;
  box-shadow: none;
}

html body.deviceland-shop .quantity .plus,
html body.deviceland-shop .quantity .minus {
  position: absolute;
  right: 0;
  left: auto;
  width: 27px;
  height: 22px;
  min-height: 0;
  padding: 0;
  margin: 0;
  border: 0;
  border-left: 1px solid var(--hair-light-2);
  border-radius: 0;
  background: transparent;
  color: var(--muted-fg);
  line-height: 22px;
  display: grid;
  place-items: center;
  transition: color var(--dur-ui) var(--ease),
    background var(--dur-ui) var(--ease);
}

html body.deviceland-shop .quantity .plus {
  top: 0;
  bottom: auto;
  border-bottom: 1px solid var(--hair-light-2);
}

html body.deviceland-shop .quantity .minus {
  bottom: 0;
  top: auto;
  border-top: 0;
}

html body.deviceland-shop .quantity .plus svg,
html body.deviceland-shop .quantity .minus svg {
  width: 12px;
  height: 12px;
}

html body.deviceland-shop .quantity .plus:hover,
html body.deviceland-shop .quantity .minus:hover {
  background: rgba(20, 17, 14, 0.05);
  color: var(--on-paper);
}

/* ------------------------------------------------------------
   Credentials under the buy row, printed by
   deviceland_pdp_credentials(). Sits at the decision point rather
   than as a banner above the product.
   ------------------------------------------------------------ */

body.deviceland-shop .dl-pdp-trust {
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid var(--hair-light);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px 28px;
}

body.deviceland-shop .dl-trust-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
  flex: 1 1 20rem;
  min-width: 0;
}

@media (min-width: 620px) {
  body.deviceland-shop .dl-trust-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px 24px;
  }
}

body.deviceland-shop .dl-trust-list li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0;
  padding: 0;
  list-style: none;
}

body.deviceland-shop .dl-trust-list svg {
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--ember);
}

body.deviceland-shop .dl-trust-list span {
  display: block;
  min-width: 0;
}

html body.deviceland-shop .dl-trust-list b {
  display: block;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.005em;
  color: var(--on-paper);
}

html body.deviceland-shop .dl-trust-list i {
  display: block;
  margin-top: 2px;
  font-style: normal;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted-fg);
}

/* .dl-trust-badge is gone with the signature it sized. It set width:76px,
   overriding the shared .badge-apple width downward to a 31px Apple logo —
   under Apple's 35px onscreen floor — and it placed a second authorization
   inside a product promotion. See deviceland_pdp_credentials() in
   inc/chrome.php for the three rules involved. .dl-pdp-trust keeps
   space-between: with one child it is inert, and the rule is left alone so
   the block can take a second element later without re-deriving the layout. */

/* ------------------------------------------------------------
   Meta links under the buttons — Size Guide, Delivery & Return,
   Ask a Question. Kept because they are real features, brought
   down to the weight of a caption rather than a control.
   ------------------------------------------------------------ */

html body.deviceland-shop .size-guide,
html body.deviceland-shop .nasa-delivery-return,
html body.deviceland-shop .nasa-single-product-meta a,
html body.deviceland-shop .product-info .nasa-ask-question,
html body.deviceland-shop .nasa-share-social .nasa-social-title {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--muted-fg);
}

html body.deviceland-shop .size-guide:hover,
html body.deviceland-shop .nasa-delivery-return:hover {
  color: var(--on-paper);
}

/* ------------------------------------------------------------
   Tabs and attribute table
   ------------------------------------------------------------ */

body.deviceland-shop .woocommerce-tabs ul.tabs li a,
body.deviceland-shop .nasa-tabs li a {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.03em;
}

html body.deviceland-shop .woocommerce-tabs ul.tabs li a,
html body.deviceland-shop .nasa-tabs li a {
  color: var(--muted-fg);
}

html body.deviceland-shop .woocommerce-tabs ul.tabs li.active a,
html body.deviceland-shop .nasa-tabs li.active a,
html body.deviceland-shop .woocommerce-tabs ul.tabs li a:hover {
  color: var(--on-paper);
}

html body.deviceland-shop .woocommerce-Tabs-panel,
html body.deviceland-shop .nasa-panel {
  font-size: 15px;
  line-height: 1.65;
  color: rgba(22, 19, 15, 0.78);
}

/* Description rhythm, answering the balance question directly.

   The page already has a spacing rule for a list of facts: the attribute table
   sets 9px above and below each row, so a row occupies its line-height plus
   18px. A bulleted spec list is the same kind of content, so it takes the same
   measure — 9px between items — and then Description and Additional
   information scan at identical speed instead of one feeling tighter.

   Only the gaps BETWEEN items grow. Adding padding around the whole block
   instead would have pushed the section apart without making any single line
   easier to find, which is the usual way "more spacing" makes a page longer
   and no clearer. Paragraphs get a full line because they are prose, not
   entries in a list. */
html body.deviceland-shop .woocommerce-Tabs-panel li + li,
html body.deviceland-shop .nasa-content-panel li + li,
html body.deviceland-shop .nasa-content-description li + li {
  margin-top: 9px;
}

html body.deviceland-shop .woocommerce-Tabs-panel p + p,
html body.deviceland-shop .nasa-content-panel p + p,
html body.deviceland-shop .nasa-content-description p + p {
  margin-top: 1em;
}

html body.deviceland-shop .woocommerce-Tabs-panel ul,
html body.deviceland-shop .nasa-content-panel ul,
html body.deviceland-shop .nasa-content-description ul {
  margin: 0 0 1em;
  padding-left: 1.15em;
}

html body.deviceland-shop .woocommerce-Tabs-panel li,
html body.deviceland-shop .nasa-content-panel li,
html body.deviceland-shop .nasa-content-description li {
  padding-left: 2px;
}

/* ------------------------------------------------------------
   Related products: match the section indent
   ------------------------------------------------------------

   Description, Additional information, Reviews and Accessories are all
   .nasa-content-panel inside .nasa-vertical-notabs, and Elessi indents that by
   150px at >=1024px so the headings form a left column. Related Products is
   rendered outside that structure as a .row, so it never picked the indent up
   and its cards started 150px to the left of every other section's content.

   The heading stays flush like the others; only the content moves. */
@media (min-width: 1024px) {
  html body.deviceland-shop .related-product > .columns + .columns {
    padding-left: 150px;
  }
}

body.deviceland-shop .woocommerce-Tabs-panel h2,
body.deviceland-shop .woocommerce-Tabs-panel h3 {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: -0.015em;
  color: var(--on-paper);
}

/* ------------------------------------------------------------
   Button hierarchy — one primary, and ember is not a button fill
   ------------------------------------------------------------

   The orange "Be the first to review" button was Elessi's default, not a
   decision. It matters because it broke the only rule the design has about
   buttons:

     ink filled   the single commercial action on the page, whether that is
                  Add to cart or the phone CTA that replaces it
     outline      a real alternative to it (call the shop, alongside a cart)
     quiet link   everything else (reviews, size guide, delivery, share)

   Ember is an accent — the italic word in a headline, an icon, a live pip. It
   is deliberately never a button fill, because a filled ember button next to a
   filled ink button asks the eye to choose between two primaries, and "leave a
   review" is not competing with "buy this watch". Colour carries rank here, so
   spending the loudest colour on the least important control inverts it.

   .dl-pdp-call tested that rule and lost. It was filled --ember-deep on the
   argument that ember means "phone" in the chrome (.callbar-call is a filled
   ember Call, .masthead-call's handset is ember) and that nothing competed
   with it, since Add to cart is hidden in those states. Both premises were
   true and the result still read as desperate: in the product summary the
   filled pill became the most saturated object on the page and outshouted the
   price. The chrome precedent does not transfer, because .callbar is a fixed
   utility bar rather than the buying column. Ember went back to being the
   handset icon on that button, which is what this note says it is for.

   Reviews, comment submit and the Woo generic .button all drop to outline.

   Reviews, comment submit and the Woo generic .button all drop to outline.
   ------------------------------------------------------------ */

/* "Be the first to review ..." is not a button.

   It is <span id="reply-title" class="comment-reply-title">, a heading for the
   review form, and the previous pass swept it into the outline-button rule
   below. That is why it reads as a box: a full sentence wrapped in a pill
   border. My error, not the theme's.

   It gets heading treatment instead — and the orange was never intentional
   either; the real control below drops to outline like every other secondary
   action on the page. */
html body.deviceland-shop .comment-reply-title,
html body.deviceland-shop #reply-title {
  display: block;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font-family: var(--sans);
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: 0;
  text-transform: none;
  color: var(--on-paper);
  margin: 0 0 16px;
}

html body.deviceland-shop .comment-reply-title small a {
  font-size: 12.5px;
  font-weight: 400;
  color: var(--muted-fg);
}

/* .btn-add-new-review is the one that was still orange and boxy, and my
   selectors had never matched it. It is not the submit input I restyled — it is

     <a class="button btn-add-new-review" href="javascript:void(0);">

   inside .nasa_reviewed_images_wrap, so it took Elessi's generic .button
   styling: ember fill, square corners. Not intentional. */
html body.deviceland-shop .btn-add-new-review,
html body.deviceland-shop a.button.btn-add-new-review,
html body.deviceland-shop #nasa-submit,
html body.deviceland-shop #respond input.submit,
html body.deviceland-shop #respond input[type="submit"],
html body.deviceland-shop #review_form .form-submit .submit,
html body.deviceland-shop .woocommerce-review-link,
html body.deviceland-shop .nasa-single-product-tabs .button:not(.single_add_to_cart_button),
html body.deviceland-shop .woocommerce-Tabs-panel .button:not(.single_add_to_cart_button) {
  background: transparent;
  border: 1px solid var(--hair-light-2);
  border-radius: var(--r-pill);
  color: var(--on-paper);
  font-family: var(--sans);
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-transform: none;
  box-shadow: none;
}

html body.deviceland-shop #nasa-submit,
html body.deviceland-shop #respond input.submit,
html body.deviceland-shop #respond input[type="submit"] {
  min-height: 44px;
  padding: 0 22px;
  cursor: pointer;
}

html body.deviceland-shop .btn-add-new-review {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 22px;
}

html body.deviceland-shop .btn-add-new-review:hover,
html body.deviceland-shop #nasa-submit:hover,
html body.deviceland-shop #respond input[type="submit"]:hover,
html body.deviceland-shop #review_form .form-submit .submit:hover,
html body.deviceland-shop .nasa-single-product-tabs .button:not(.single_add_to_cart_button):hover,
html body.deviceland-shop .woocommerce-Tabs-panel .button:not(.single_add_to_cart_button):hover {
  background: rgba(20, 17, 14, 0.05);
  border-color: rgba(20, 17, 14, 0.38);
  color: var(--on-paper);
}

/* Review stars keep ember: an accent on a small mark is exactly what it is
   for. The point was never that orange is banned, only that it is not a
   button. */
html body.deviceland-shop .star-rating span,
html body.deviceland-shop .comment-form-rating .stars a {
  color: var(--ember);
}

html body.deviceland-shop table.shop_attributes th {
  color: var(--muted-fg);
  font-weight: 500;
}

body.deviceland-shop table.shop_attributes th,
body.deviceland-shop table.shop_attributes td {
  border-bottom: 1px solid var(--hair-light);
  font-size: 14px;
}

/* A long VALUE may break rather than push the table past a 320px screen
   (Nov 11: the iPhone 18 Pro's specs ran off the right edge). Only the values:
   on the labels it let the column shrink below its own words ("Communicatio /
   ns" on iPad mini at 390px; reviewer, Nov 11). */
body.deviceland-shop table.shop_attributes td {
  overflow-wrap: anywhere;
}

/* Spec values in ink, labels in taupe (Oct 24): the values read Elessi's
   #777, 4.0:1 on paper, under the 4.5:1 minimum. */
html body.deviceland-shop table.shop_attributes td,
html body.deviceland-shop table.shop_attributes td p {
  color: var(--on-paper);
}

/* ------------------------------------------------------------
   Colour swatches: one shape, not a circle inside a square
   ------------------------------------------------------------
   Measured in the rendered DOM:

     a.nasa-attr-ux-color   33x33  radius 2px   <- chip, squared by --r-sm
     span.nasa-attr-bg      25x25  radius 50%   <- Elessi dot, hardcoded round

   Squaring the radius scale fixed the chip and left the dot round, so each
   colour read as a circle floating in a box with cream between the two —
   directly above the storage chips, which are solid squared rectangles.

   ONE PROPERTY. The first attempt also set padding:0 on the chip and sized the
   dot to 100%, intending a solid swatch. The chip got its 33x33 FROM that
   padding, so removing it collapsed the chip and 100% then resolved against a
   collapsed box: the three colours rendered as specks. The dot keeps its own
   25x25 and its inset; only the corners change. A squared dot inside a squared
   chip reads as a framed colour chip and agrees with the row below it. */
.deviceland-shop .nasa-attr-ux-color .nasa-attr-bg,
.deviceland-shop .nasa-attr-ux-color .ns-colors-wrap,
.deviceland-shop .nasa-attr-ux-color .nasa-attr-bg *,
.deviceland-shop .nasa-attr-ux-color .nasa-attr-bg::before,
.deviceland-shop .nasa-attr-ux-color .nasa-attr-bg::after {
  border-radius: 0;
}

/* No claim, no separator.
   ------------------------------------------------------------
   The dot lives inside the SKU chip, so hiding an unevidenced availability
   label left the line opening with "· SKU MEHG4LW/A". */
.dl-pdp-availability[hidden] + .dl-pdp-sku > .dl-pdp-assurance-dot,
.dl-pdp-availability[hidden] + .dl-pdp-sku[hidden] + .dl-pdp-stock-qty > .dl-pdp-assurance-dot {
  display: none;
}

/* Unavailable configurations.
   ------------------------------------------------------------
   Measured on the Watch SE: WooCommerce held 12 of 16 variations out of
   stock while every swatch stayed selectable, because our own guard hands
   pointer events back to each one. Greyed, struck, and not clickable.

   Deliberately NOT applied to configurations the feed simply does not
   mention: 536 of the 600 MacBook Air builds have no row in the bulletin,
   and greying those would invent unavailability instead of stating it. */
/* Dimmed by colour, never by opacity (Oct 15). Opacity dims a swatch's
   whole subtree, and its tooltip is a child: the bubble came out at 38%,
   grey and see-through over the options behind it. */
html body.deviceland-shop form.variations_form .nasa-attr-ux.dl-attr-unavailable {
  position: relative;
  opacity: 1;
  background: var(--paper-2);
  border-color: var(--hair-light);
  color: var(--muted-fg);
}

/* The swatch's own content (label text or colour chip) fades instead; the
   tooltip, also a child, is left at full strength. */
html body.deviceland-shop form.variations_form .nasa-attr-ux.dl-attr-unavailable > :not(.nasa-tip-content) {
  opacity: 0.4;
}

/* A diagonal is unambiguous where a faded label is only quiet. */
html body.deviceland-shop form.variations_form .nasa-attr-ux.dl-attr-unavailable::after {
  content: "";
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background: linear-gradient(
    to top left,
    transparent calc(50% - 0.5px),
    var(--hair-light-2) calc(50% - 0.5px),
    var(--hair-light-2) calc(50% + 0.5px),
    transparent calc(50% + 0.5px)
  );
  pointer-events: none;
}

html body.deviceland-shop form.variations_form .nasa-attr-ux.dl-attr-unavailable:hover {
  border-color: var(--hair-light);
  color: var(--muted-fg);
}

/* Ready today.
   ------------------------------------------------------------
   A single ember dot on the options that can still be had today given the
   rest of the selection. Marking the opposite would have put a warning on
   almost every control — 16 of 600 MacBook Air builds are evidenced in
   stock — and a page of warnings for the ordinary case reads as an apology.

   The dot is positioned on the swatch rather than inline in the label so it
   works on a colour chip, which has no text to sit beside. */
html body.deviceland-shop form.variations_form .nasa-attr-ux.dl-attr-ready {
  position: relative;
}

html body.deviceland-shop form.variations_form .nasa-attr-ux.dl-attr-ready::before {
  content: "";
  position: absolute;
  top: 4px;
  right: 4px;
  z-index: 2;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ember);
  /* A ring, so the dot survives both the cream swatch and a dark colour
     chip without a second rule per finish. */
  box-shadow: 0 0 0 1.5px var(--paper);
  pointer-events: none;
}

/* On the selected swatch the ground is ink, so the ring matches it. */
html body.deviceland-shop form.variations_form .nasa-attr-ux.dl-attr-ready.selected::before {
  box-shadow: 0 0 0 1.5px var(--ink);
}

html body.deviceland-shop .dl-swatch-legend {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 2px 0 18px;
  font-family: var(--sans);
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--muted-fg);
}

html body.deviceland-shop .dl-swatch-legend[hidden] {
  display: none;
}

html body.deviceland-shop .dl-swatch-legend-dot {
  flex: 0 0 auto;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ember);
}

/* Every swatch can host the tooltip, not just colour chips.
   ------------------------------------------------------------
   .nasa-tip-content is absolutely positioned, so its offset parent has to be
   the swatch. Elessi only guaranteed that on the chips it tipped itself. */
html body.deviceland-shop form.variations_form .nasa-attr-ux {
  position: relative;
}

/* The bubble sits above the swatch it describes; without a stacking context
   a neighbouring selected swatch paints over it. */
html body.deviceland-shop form.variations_form .nasa-attr-ux:hover {
  z-index: 3;
}

/* A tooltip not showing takes no room: hidden by opacity alone, the one on
   a swatch at the buy column's right edge widened the page by a few pixels
   at 1024px, so the page scrolled sideways. */
html body.deviceland-shop form.variations_form .nasa-attr-ux:not(:hover):not(:focus-visible):not(.dl-tip-open) .nasa-tip-content {
  display: none;
}

/* The site-wide tooltip (chrome.css): solid ink, white, 12px, wrapping at
   260px. A long reason ("Natural Titanium · Not made with your earlier
   choices") wraps to two lines instead of running past the column. */
html body.deviceland-shop form.variations_form .nasa-attr-ux .nasa-tip-content {
  width: max-content;
  max-width: 260px;
  padding: 7px 11px;
  border-radius: 8px;
  background: #16130f;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0;
  text-align: center;
  text-decoration: none;
  text-transform: none;
  white-space: normal;
  color: #fff;
}

/* The legend's second job: the way back.
   ------------------------------------------------------------
   With no dots on the page the key has nothing to explain, so it becomes the
   shortcut instead. Same line, same position — the customer is not asked to
   look somewhere new at the moment they are already lost. */
html body.deviceland-shop .dl-swatch-legend.is-offering-route .dl-swatch-legend-dot {
  background: var(--hair-light-2);
}

html body.deviceland-shop .dl-swatch-legend-jump {
  appearance: none;
  margin: 0;
  padding: 0;
  border: 0;
  border-bottom: 1px solid var(--hair-light-2);
  background: transparent;
  font: inherit;
  color: var(--on-paper);
  cursor: pointer;
  transition: border-color var(--dur-micro) var(--ease),
    color var(--dur-micro) var(--ease);
}

html body.deviceland-shop .dl-swatch-legend-jump[hidden] {
  display: none;
}

html body.deviceland-shop .dl-swatch-legend-jump:hover,
html body.deviceland-shop .dl-swatch-legend-jump:focus-visible {
  border-bottom-color: var(--ember);
  color: var(--ember-deep);
}

/* We own the three states, so Elessi renders none of them.
   ------------------------------------------------------------
   The theme marks anything WooCommerce filters out with .nasa-disable and
   draws it at opacity 0.6 with a diagonal cross — the same treatment for
   "cannot be combined with your other choices" as for "gone forever". With
   592 of this iMac's 1,008 combinations simply not made, that cross landed
   on perfectly orderable colours: Orange has 82 purchasable variations and
   was struck through.

   Every one of those crossing rules is neutralised here, and the swatch
   states come from our own classes instead:

     (no class)            selectable; a click changes only lower rungs
     .dl-attr-ready        an ember dot — still ships today if you pick it
     .dl-attr-unavailable  no build can follow the choices ABOVE it

   Listed exhaustively rather than with a blanket rule because Elessi keys
   the cross off the shape class (round / small-square / big-square), and a
   theme option that changes the shape would quietly bring it back. */
html body.deviceland-shop form.variations_form .nasa-attr-ux.nasa-disable,
html body.deviceland-shop form.variations_form .nasa-attr-ux-item.nasa-disable,
html body.deviceland-shop form.variations_form .nasa-attr-ux-clone.nasa-disable {
  opacity: 1;
  cursor: pointer;
}

html body.deviceland-shop form.variations_form .nasa-attr-ux.nasa-disable::before,
html body.deviceland-shop form.variations_form .nasa-attr-ux.nasa-disable::after,
html body.deviceland-shop form.variations_form .nasa-attr-ux-item.nasa-disable::before,
html body.deviceland-shop form.variations_form .nasa-attr-ux-item.nasa-disable::after,
html body.deviceland-shop form.variations_form .nasa-attr-ux.nasa-disable .nasa-attr-bg::before,
html body.deviceland-shop form.variations_form .nasa-attr-ux.nasa-disable .nasa-attr-bg::after,
html body.deviceland-shop form.variations_form .nasa-attr-ux.nasa-disable .nasa-attr-bg-img::before,
html body.deviceland-shop form.variations_form .nasa-attr-ux.nasa-disable .nasa-attr-bg-img::after,
html body.deviceland-shop form.variations_form .nasa-attr-ux-clone.nasa-disable .nasa-attr-bg::before,
html body.deviceland-shop form.variations_form .nasa-attr-ux-clone.nasa-disable .nasa-attr-bg::after {
  content: none;
  display: none;
  border-top: 0;
}

/* The ember dot must survive the reset above: it is also a ::before, on the
   swatch itself, and the rule that kills the cross would take it too. */
html body.deviceland-shop form.variations_form .nasa-attr-ux.dl-attr-ready::before {
  content: "";
  display: block;
  border-top: 0;
}

/* The only state that reads as closed: nothing buyable follows the choices
   above it. Struck through, dimmed, and not clickable — here it is true. */
html body.deviceland-shop form.variations_form .nasa-attr-ux.dl-attr-unavailable {
  opacity: 1;
  cursor: not-allowed;
  text-decoration: line-through;
}


/* The switch is an anchor now, so it needs the link reset the button did
   not: no underline of its own, and the same quiet rule underneath. */
html body.deviceland-shop a.dl-swatch-legend-jump {
  text-decoration: none;
  white-space: nowrap;
}

/* The promise line, loud enough to be read before the click.
   ------------------------------------------------------------
   Reported, fairly: as plain small grey text under the button it was
   "basically unnoticeable to a person just pressing add to cart". A
   disclosure nobody reads is compliance theatre — the surprise it was meant
   to prevent still lands, just later and with a refund attached.

   This is Apple's own treatment in their buy box: a small delivery glyph
   and one legible line. No warning colour, no border, no alarm — an icon
   earns the eye without claiming something is wrong, which is the whole
   difference between informing a customer and nagging one. */
html body.deviceland-shop .dl-pdp-inventory-note.is-promise {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 12px;
  color: var(--on-paper);
  font-size: 12.5px;
  line-height: 1.5;
}

html body.deviceland-shop .dl-pdp-note-icon {
  display: none;
}

html body.deviceland-shop .dl-pdp-inventory-note.is-promise .dl-pdp-note-icon-wait {
  display: block;
  flex: 0 0 auto;
  margin-top: 1px;
  color: var(--ember-deep);
}

/* One glyph at a time. Both live in the markup because a variable
   product's notice is rendered once and re-labelled by script; the state
   class picks which is shown, and must also hide the other. */
html body.deviceland-shop .dl-pdp-inventory-note.is-promise .dl-pdp-note-icon-ship {
  display: none !important;
}

/* With no call button on the page, this note is the only thing carrying the
   number — so the desktop rule that hides it must not apply here. */
html body.deviceland-shop .dl-pdp-inventory-note.is-promise .dl-pdp-note-tel {
  display: inline !important;
}

/* Above the button, in a band of its own.
   ------------------------------------------------------------
   Reported: as a line under the button it said nothing a person pressing
   Add to cart would see, and it never said the plain thing — that this one
   is not here today. Both are fixed: the fact leads the sentence, and the
   note sits above the control it qualifies, because information after a
   decision is a receipt rather than a warning.

   The band is paper-2 with a hairline, not a tinted alert. It reads as part
   of the buy box — the way Apple's own delivery module does — rather than
   as something gone wrong. At what cost to the quiet: a 1px rule and a
   shade of cream. */
html body.deviceland-shop .dl-pdp-inventory-note.is-promise {
  padding: 11px 13px;
  margin: 0 0 14px;
  background: var(--paper-2);
  border: 1px solid var(--hair-light);
  border-radius: var(--r-sm, 4px);
}

/* No phone number inside the promise band.
   ------------------------------------------------------------
   A support number printed inside a shipping notice reads as "this order
   is the kind that goes wrong". The masthead carries the number on every
   page for anyone who wants it; the buy box stays self-serve. */
html body.deviceland-shop .dl-pdp-inventory-note.is-promise .dl-pdp-note-tel {
  display: none !important;
}

/* The faster build, inside the box that announced the wait.
   ------------------------------------------------------------
   Same ember dot as the swatches, so the mark means one thing everywhere,
   on its own line under the promise. It is an offer, not an instruction:
   quieter than the sentence above it, and ignorable. */
html body.deviceland-shop .dl-pdp-note-offer {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-top: 7px;
  padding-top: 7px;
  border-top: 1px solid var(--hair-light);
  font-size: 12.5px;
  line-height: 1.5;
}

html body.deviceland-shop .dl-pdp-note-offer[hidden] {
  display: none;
}

html body.deviceland-shop .dl-pdp-note-offer-dot {
  flex: 0 0 auto;
  width: 5px;
  height: 5px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--ember);
}

html body.deviceland-shop a.dl-pdp-note-offer-jump {
  color: var(--on-paper);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  white-space: nowrap;
}

/* A heading for the notice, so the eye has somewhere to land.
   ------------------------------------------------------------
   The same words as one run-on paragraph were skipped entirely, icon and
   all — "basically unnoticeable to a person just pressing add to cart".
   Two lines instead of one sentence is the whole fix. */
html body.deviceland-shop .dl-pdp-note-head {
  display: block;
  margin-bottom: 2px;
  font-weight: 500;
  letter-spacing: 0.005em;
  color: var(--on-paper);
}

html body.deviceland-shop .dl-pdp-note-head[hidden] {
  display: none;
}

/* No tooltips on a touch screen.
   ------------------------------------------------------------
   Reported on mobile: tap M4 Pro, tap M4, and the M4 Pro bubble is still
   on screen. That is not stale content — the label was measured correct at
   every step — it is a hover affordance being fired by a tap. A touch
   device has no pointer to move away, so the bubble has no event that
   dismisses it, and it sits over the controls covering the next choice.

   They were never usable here anyway: a tooltip that needs hover cannot be
   read on a phone without also selecting the thing it describes. The
   notice above Add to cart carries what a phone needs — what this
   configuration means, and what ships instead — at full size. */
@media (hover: none) {
  html body.deviceland-shop .nasa-attr-ux .nasa-tip-content {
    display: none !important;
  }

  /* ...except the one a tap on an unavailable option opens on purpose
     (dl-tip-open, set for a few seconds and cleared on the next tap). */
  html body.deviceland-shop .nasa-attr-ux.dl-tip-open .nasa-tip-content {
    display: block !important;
    visibility: visible !important;
    opacity: 1 !important;
  }
}

/* The same slot, filled positively.
   ------------------------------------------------------------
   The notice used to appear only when something was wrong, so its presence
   was the message — and its absence said nothing at all. Looking at the
   ladder alone, a customer could not tell that a different processor had a
   path to stock. One box in one place on every configuration means there
   is somewhere to look, rather than something to notice.

   Identical furniture to the wait, so the eye learns one position. Only
   the glyph and the words change. */
html body.deviceland-shop .dl-pdp-inventory-note.is-ready {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 11px 13px;
  margin: 0 0 14px;
  background: var(--paper-2);
  border: 1px solid var(--hair-light);
  border-radius: var(--r-sm, 4px);
  color: var(--on-paper);
  font-size: 12.5px;
  line-height: 1.5;
}

html body.deviceland-shop .dl-pdp-inventory-note.is-ready .dl-pdp-note-icon-ship {
  display: block;
  flex: 0 0 auto;
  margin-top: 1px;
  color: var(--ember-deep);
}

html body.deviceland-shop .dl-pdp-inventory-note.is-ready .dl-pdp-note-tel,
html body.deviceland-shop .dl-pdp-inventory-note.is-ready .dl-pdp-note-icon-wait {
  display: none !important;
}

/* Discontinued and gone: the one state with nothing to offer.
   ------------------------------------------------------------
   Same furniture again, and deliberately no ember: the dot and the glyph
   both mean "you can have this", and here you cannot. Muted ink, the
   empty-carton glyph, and no promise of a ship date — because for a part
   Apple has stopped making there is nothing to order in. */
html body.deviceland-shop .dl-pdp-inventory-note.is-discontinued {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 11px 13px;
  margin: 0 0 14px;
  background: var(--paper-2);
  border: 1px solid var(--hair-light);
  border-radius: var(--r-sm, 4px);
  color: var(--muted-fg);
  font-size: 12.5px;
  line-height: 1.5;
}

/* Out of stock: the same box, in the place Add to cart would take.
   ------------------------------------------------------------
   Same furniture as ready and processing so every state reads from one
   position, muted like discontinued because there is nothing to buy, and
   its own glyph — a carton with a cross — since a clock promises a wait and
   a van a dispatch. Discontinued shares the glyph for the same reason. */
html body.deviceland-shop .dl-pdp-inventory-note.is-unavailable {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 11px 13px;
  margin: 0 0 14px;
  background: var(--paper-2);
  border: 1px solid var(--hair-light);
  border-radius: var(--r-sm, 4px);
  color: var(--muted-fg);
  font-size: 12.5px;
  line-height: 1.5;
}

html body.deviceland-shop .dl-pdp-inventory-note.is-unavailable .dl-pdp-note-icon-none,
html body.deviceland-shop .dl-pdp-inventory-note.is-discontinued .dl-pdp-note-icon-none {
  display: block;
  flex: 0 0 auto;
  margin-top: 1px;
  color: var(--muted-fg);
}

html body.deviceland-shop .dl-pdp-inventory-note.is-unavailable .dl-pdp-note-icon-wait,
html body.deviceland-shop .dl-pdp-inventory-note.is-unavailable .dl-pdp-note-icon-ship,
html body.deviceland-shop .dl-pdp-inventory-note.is-unavailable .dl-pdp-note-tel,
html body.deviceland-shop .dl-pdp-inventory-note.is-discontinued .dl-pdp-note-icon-wait,
html body.deviceland-shop .dl-pdp-inventory-note.is-discontinued .dl-pdp-note-icon-ship,
html body.deviceland-shop .dl-pdp-inventory-note.is-discontinued .dl-pdp-note-tel,
html body.deviceland-shop .dl-pdp-inventory-note.is-promise .dl-pdp-note-icon-none,
html body.deviceland-shop .dl-pdp-inventory-note.is-ready .dl-pdp-note-icon-none {
  display: none !important;
}

/* Financing, under the price (deviceland_pdp_financing_line): one quiet
   line with a link, as Apple does, never a popup or a monthly figure. */
body.deviceland-shop .dl-pdp-finance {
  margin: 8px 0 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--muted-fg);
}

body.deviceland-shop .dl-pdp-finance a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* "Made-to-order terms", under a build's note. */
body.deviceland-shop .dl-pdp-note-terms {
  display: inline-block;
  margin-top: 4px;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* The AppleCare+ tile inside the AppleCare+ Warranty options only (owner,
   Oct 24), the same mark the bag shows beside "AppleCare+ part ...".
   "Standard 1-year" has no logo, as Apple shows plain no-coverage choices.
   Scoped to the Warranty row: a value-prefix rule for "standard" also put a
   logo on "Standard Glass". On the text span: the button's own ::before is
   the ember ready dot. */
html body.deviceland-shop form.variations_form .nasa-attr-ux_wrap[data-attribute_name="attribute_pa_warranty"] .nasa-attr-ux[data-value*="applecare"] .nasa-attr-text::before {
  content: "";
  display: inline-block;
  width: 22px;
  height: 22px;
  margin-right: 8px;
  vertical-align: -6px;
  border-radius: 23%;
  box-shadow: 0 0 0 0.5px rgba(22, 19, 15, 0.14);
  background: url("../img/applecare-plus-mark.png") center / contain no-repeat;
}

/* ------------------------------------------------------------
   AppleCare+ "What's covered" (owner, Oct 25; inc/applecare.php)
   ------------------------------------------------------------
   A text link right after the Warranty row's caption, with a small (i),
   opens one quiet panel comparing Standard with AppleCare+ (owner, Oct 25:
   at the far right it did not look clickable). Same paper, hairlines and
   serif heading as the page; the AppleCare+ column is told apart by a soft
   paper tint, its mark and ink-coloured values, Standard by muted ones. A
   sheet from the bottom on phones. */
html body.deviceland-shop form.variations_form tr:has([data-attribute_name="attribute_pa_warranty"]) > th.label {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: 6px 16px;
}

html body.deviceland-shop form.variations_form tr:has([data-attribute_name="attribute_pa_warranty"]) > th.label > label {
  flex: 0 1 auto;
  min-width: 0;
}

/* A theme-wide button rule made this 42px tall, so the caption row grew
   from 31px to 58px: every size is set here. */
html body.deviceland-shop form.variations_form .dl-ac-open {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  width: auto;
  height: auto;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 15px;
  text-transform: none;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--hair-light-2, rgba(22, 19, 15, 0.35));
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* The (i): says "more about this" before the words are read. */
html body.deviceland-shop form.variations_form .dl-ac-open::before {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: no-repeat center / 14px 14px
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Ccircle cx='7' cy='7' r='6.2' fill='none' stroke='%23000' stroke-width='1.2'/%3E%3Ccircle cx='7' cy='4.3' r='.85'/%3E%3Cpath d='M7 6.4v4' stroke='%23000' stroke-width='1.3' stroke-linecap='round'/%3E%3C/svg%3E");
  mask: no-repeat center / 14px 14px
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Ccircle cx='7' cy='7' r='6.2' fill='none' stroke='%23000' stroke-width='1.2'/%3E%3Ccircle cx='7' cy='4.3' r='.85'/%3E%3Cpath d='M7 6.4v4' stroke='%23000' stroke-width='1.3' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* The words are small; the tap area is not. */
html body.deviceland-shop form.variations_form .dl-ac-open::after {
  content: "";
  position: absolute;
  top: -12px; right: -8px; bottom: -12px; left: -8px;
}

html body.deviceland-shop form.variations_form .dl-ac-open:hover,
html body.deviceland-shop form.variations_form .dl-ac-open:focus-visible {
  text-decoration-color: currentColor;
}

html body.deviceland-shop .dl-ac {
  width: min(600px, calc(100vw - 32px));
  max-width: none;
  max-height: calc(100vh - 48px);
  margin: auto;
  padding: 0;
  overflow: auto;
  border: 1px solid var(--hair-light);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--on-paper);
  box-shadow: 0 24px 64px rgba(22, 19, 15, 0.18), 0 2px 8px rgba(22, 19, 15, 0.06);
}

html body.deviceland-shop .dl-ac::backdrop {
  background: rgba(22, 19, 15, 0.32);
}

html body.deviceland-shop .dl-ac[open] {
  animation: dl-ac-in 220ms var(--ease, ease-out);
}

@keyframes dl-ac-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

html body.deviceland-shop .dl-ac-sheet {
  position: relative;
  padding: 32px 32px 24px;
}

html body.deviceland-shop .dl-ac-close {
  position: absolute;
  top: 14px;
  right: 14px;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: none;
  color: var(--muted-fg);
  cursor: pointer;
}

html body.deviceland-shop .dl-ac-close::before {
  content: "";
  width: 12px;
  height: 12px;
  background: currentColor;
  -webkit-mask: no-repeat center / 12px 12px
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.5 1.5l9 9M10.5 1.5l-9 9' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
  mask: no-repeat center / 12px 12px
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.5 1.5l9 9M10.5 1.5l-9 9' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
}

html body.deviceland-shop .dl-ac-close:hover,
html body.deviceland-shop .dl-ac-close:focus-visible {
  background: var(--paper-2);
  color: var(--ink);
}

html body.deviceland-shop .dl-ac-title {
  margin: 0 44px 8px 0;
  font-family: var(--display);
  font-size: 30px;
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
}

html body.deviceland-shop .dl-ac-lede {
  max-width: 46ch;
  margin: 0 0 24px;
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.55;
  color: var(--muted-fg);
}

html body.deviceland-shop .dl-ac-table {
  width: 100%;
  margin: 0;
  table-layout: fixed;
  border: 0;
  border-collapse: separate;
  border-spacing: 0;
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.45;
}

html body.deviceland-shop .dl-ac-table th,
html body.deviceland-shop .dl-ac-table td {
  padding: 14px;
  border: 0;
  background: transparent;
  text-align: left;
  vertical-align: top;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
}

html body.deviceland-shop .dl-ac-table thead th,
html body.deviceland-shop .dl-ac-table thead td {
  padding-top: 16px;
  padding-bottom: 14px;
  vertical-align: bottom;
}

html body.deviceland-shop .dl-ac-table tr > :first-child {
  width: 32%;
  padding-left: 0;
}

html body.deviceland-shop .dl-ac-table .dl-ac-std {
  width: 30%;
}

html body.deviceland-shop .dl-ac-table tbody th,
html body.deviceland-shop .dl-ac-table tbody td {
  border-top: 1px solid var(--hair-light);
}

html body.deviceland-shop .dl-ac-table tbody th {
  font-weight: 500;
  color: var(--ink);
}

html body.deviceland-shop .dl-ac-table tbody .dl-ac-std {
  color: var(--muted-fg);
}

html body.deviceland-shop .dl-ac-table tbody .dl-ac-std.is-none {
  color: rgba(22, 19, 15, 0.42);
}

html body.deviceland-shop .dl-ac-table tbody .dl-ac-plus {
  color: var(--ink);
}

/* The AppleCare+ column: one soft tint, top to bottom. */
html body.deviceland-shop .dl-ac-table .dl-ac-plus {
  background: var(--paper-2);
}

html body.deviceland-shop .dl-ac-table thead .dl-ac-plus {
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}

html body.deviceland-shop .dl-ac-table tbody tr:last-child .dl-ac-plus {
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}

html body.deviceland-shop .dl-ac-table thead .dl-ac-std,
html body.deviceland-shop .dl-ac-table thead .dl-ac-plus-name {
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
}

html body.deviceland-shop .dl-ac-table thead .dl-ac-std span {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  font-weight: 400;
  color: var(--muted-fg);
}

html body.deviceland-shop .dl-ac-table thead .dl-ac-plus {
  white-space: nowrap;
}

/* The owner's AppleCare+ tile as the column's heading, 44px so the word in
   it reads (owner, Oct 26); same rounding and hairline as on the option. */
html body.deviceland-shop .dl-ac-table .dl-ac-mark {
  display: block;
  width: 44px;
  height: 44px;
  margin: 0;
  border-radius: 23%;
  box-shadow: 0 0 0 0.5px rgba(22, 19, 15, 0.14);
}

/* The battery benefit, true only of devices with one: a line, not a row. */
html body.deviceland-shop .dl-ac-note {
  margin: 18px 0 0;
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.5;
  color: var(--on-paper);
}

html body.deviceland-shop .dl-ac-fine {
  margin: 8px 0 0;
  font-family: var(--sans);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted-fg);
}

html body.deviceland-shop .dl-ac-fine a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--hair-light-2, rgba(22, 19, 15, 0.35));
  text-underline-offset: 3px;
}

/* Phones: a sheet from the bottom, the table kept in three columns. */
@media (max-width: 600px) {
  html body.deviceland-shop .dl-ac {
    width: 100%;
    max-height: 88vh;
    margin: auto 0 0;
    border-width: 1px 0 0;
    border-radius: 14px 14px 0 0;
  }

  html body.deviceland-shop .dl-ac[open] {
    animation-name: dl-ac-up;
  }

  html body.deviceland-shop .dl-ac-sheet {
    padding: 26px 16px calc(20px + env(safe-area-inset-bottom, 0px));
  }

  html body.deviceland-shop .dl-ac-title {
    font-size: 26px;
  }

  html body.deviceland-shop .dl-ac-lede {
    margin-bottom: 18px;
    font-size: 13.5px;
  }

  html body.deviceland-shop .dl-ac-table {
    font-size: 13px;
  }

  html body.deviceland-shop .dl-ac-table th,
  html body.deviceland-shop .dl-ac-table td {
    padding: 12px 8px;
  }

  html body.deviceland-shop .dl-ac-table tr > :first-child {
    width: 28%;
  }

  html body.deviceland-shop .dl-ac-table thead .dl-ac-plus {
    white-space: normal;
  }

  html body.deviceland-shop .dl-ac-table thead .dl-ac-std,
  html body.deviceland-shop .dl-ac-table thead .dl-ac-plus-name {
    font-size: 14px;
  }
}

@keyframes dl-ac-up {
  from { transform: translateY(24px); opacity: 0; }
  to { transform: none; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  html body.deviceland-shop .dl-ac[open] {
    animation: none;
  }
}
