/*
Theme Name:   NES Child
Theme URI:    https://nationalequipmentsales.com
Description:  Child theme of Astra for National Equipment Sales, Inc. Carries the complete design system standalone — Astra's own stylesheet is dequeued in functions.php and its header/footer/container markup is replaced by header.php/footer.php.
Author:       Nathan Kaludy
Template:     astra
Version:      0.2.0
Text Domain:  nes-child
*/

/* ==========================================================================
   Ported from the approved design build (wp-content/design/css/style.css).

   Four categories of change from that file, each marked FIX: below where it
   appears:

   1. Fixed heights with object-fit:cover, replaced with aspect-ratio boxes
      and object-fit:contain. The source photos are overwhelmingly portrait
      phone shots; a 470px-tall cover frame discards the top and bottom of
      every one. Soft-cropping the image sizes in PHP does nothing on its
      own if the CSS crops them again — both halves are needed.
   2. A SOLD state, which the design does not have at all, plus the one
      accent colour it needs.
   3. Pagination, which the design has neither markup nor CSS for.
   4. Small additions the conversion needs: skip link, empty states,
      spec list, the WordPress-generated mobile menu list.

   Everything else is the design file unchanged.
   ========================================================================== */

:root{
  --green:#2b6c1f;
  --green-dark:#1e4d15;
  --green-deep:#224f18;
  --green-deepest:#1b3f13;
  --yellow:#e9cb2c;
  --yellow-hover:#f5da4e;
  --text:#3a3a3a;
  --text-soft:#6b6b6b;
  --text-mute:#8a8a8a;
  --line:#e3e3e3;
  --line-soft:#ececec;
  --tint:#fafafa;
  --white:#fff;
  --shadow-sm:0 1px 3px rgba(0,0,0,.08);
  --shadow-md:0 2px 8px rgba(0,0,0,.10);
  --shadow-lg:0 10px 24px rgba(0,0,0,.14);
  --wrap:1240px;
  --cards:4;

  /* FIX 2: the one accent colour added for the SOLD state.
     The design's palette is green/yellow/grey and has no red at all. This
     is the only red in the stylesheet — a second one elsewhere would make
     "red" stop meaning "sold".
     Contrast against white is 6.89:1, which clears WCAG AA for normal text
     (4.5:1) with room to spare, so the banner is legible at any size. */
  --sold:#b3170f;

  /* The neutral ground a contained photo sits against. Slightly warm and
     very light, so letterboxing round a portrait photo reads as part of
     the card rather than as a rendering fault. */
  --photo-ground:#f1efeb;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;font:400 16px/1.6 Lato,'Helvetica Neue',Arial,sans-serif;color:var(--text);background:var(--white);-webkit-font-smoothing:antialiased}
img{max-width:100%;display:block}
a{color:var(--green);text-decoration:none}
a:hover{color:var(--green-dark)}
h1,h2,h3,p,ul{margin:0}
ul{list-style:none;padding:0}
button{font:inherit;cursor:pointer}
input,select,textarea{font:inherit;color:var(--text)}
::selection{background:var(--yellow);color:var(--green-dark)}
:focus-visible{outline:2px solid var(--green);outline-offset:2px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* FIX 4: skip link. Off-screen until focused, then pinned top-left over
   everything. Not .sr-only, because that would keep it invisible even while
   focused — a keyboard user needs to see where they have landed. */
.skip-link{position:absolute;left:-9999px;top:0;z-index:100;padding:12px 18px;background:var(--yellow);color:var(--green-dark);font-weight:900;letter-spacing:.06em;text-transform:uppercase;font-size:13px}
.skip-link:focus{left:0}

/* main is a landmark, not a layout box — the shell's bands (.pagehead,
   .breadcrumb) are full-bleed and manage their own padding. */
main{display:block}
main:focus{outline:none}

.wrap{max-width:var(--wrap);margin:0 auto;padding:0 24px;width:100%}
.ico{width:16px;height:16px;flex:none;fill:none;stroke:var(--green);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
.ico-yellow{stroke:var(--yellow)}
.rule{display:block;width:52px;height:4px;background:var(--yellow)}

/* header */
.topbar{background:var(--white);border-bottom:1px solid var(--line-soft)}
.topbar-inner{display:flex;align-items:center;justify-content:space-between;gap:24px;padding-top:16px;padding-bottom:16px;flex-wrap:wrap}
.brand{display:flex;align-items:center;gap:16px;color:inherit}
.brand-logo{height:62px;width:auto}
.brand-text{display:flex;flex-direction:column;gap:2px}
.brand-name{font-size:26px;font-weight:700;color:var(--text);letter-spacing:-.01em}
.brand-tag{font-size:13.5px;color:var(--text-soft)}
.topbar-contact{display:flex;flex-direction:column;gap:6px;font-size:14px}
.topbar-contact a,.topbar-contact span{display:flex;align-items:center;gap:9px;color:#4a4a4a}
.topbar-contact a:hover{color:var(--green)}

/* nav */
.nav{background:var(--green)}
.nav-inner{display:flex;align-items:stretch;justify-content:space-between;gap:8px}
.nav-links{display:flex;align-items:stretch;gap:2px;flex-wrap:wrap}
.nav-link{display:flex;align-items:center;padding:15px 20px;font-size:13.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--white)}
.nav-link:hover,.nav-link:focus-visible{background:var(--yellow);color:var(--green-dark)}
.nav-link.is-active{background:var(--yellow);color:var(--green-dark)}
.nav-quote{align-self:center;padding:10px 18px;background:var(--yellow);color:var(--green-dark);font-size:13px;font-weight:900;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap}
.nav-quote:hover{background:var(--yellow-hover);color:var(--green-dark)}
.nav-toggle{display:none;align-items:center;gap:10px;padding:14px 4px;background:none;border:0;color:var(--white);font-size:13.5px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}
.nav-toggle .ico{width:22px;height:22px;stroke:currentColor;stroke-width:2.75}
.nav-toggle .ico-close{display:none}
.nav-toggle[aria-expanded="true"] .ico-menu{display:none}
.nav-toggle[aria-expanded="true"] .ico-close{display:block}

/* FIX 4: the mobile panel is hidden on desktop by CSS, not by the `hidden`
   attribute. The markup ships it visible so that a phone with JavaScript
   off still has navigation (see assets/js/nav.js) — which means desktop
   has to suppress the duplicate itself. `:not([hidden])` lets the script's
   own hiding win at mobile widths. */
.nav-mobile{display:none;background:#25601b;border-top:1px solid rgba(255,255,255,.22)}
.nav-mobile-inner{display:flex;flex-direction:column;padding-top:6px;padding-bottom:12px}
.nav-mobile-list{display:flex;flex-direction:column}
.nav-mobile .nav-link{display:block;padding:15px 4px;font-size:14.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--white);border-bottom:1px solid rgba(255,255,255,.14);background:none}
.nav-mobile .nav-link:hover,.nav-mobile .nav-link:focus-visible{background:none;color:var(--yellow)}
.nav-mobile-list li:last-child .nav-link{border-bottom:0}
.nav-mobile .nav-link.is-active{background:none;color:var(--yellow)}
.accentbar{height:5px;background:var(--yellow)}

/* buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:48px;padding:0 26px;border:0;font-size:13.5px;font-weight:900;letter-spacing:.06em;text-transform:uppercase;transition:background .18s ease,color .18s ease}
.btn-block{width:100%;height:52px}
.btn-yellow{background:var(--yellow);color:var(--green-dark)}
.btn-yellow:hover{background:var(--yellow-hover);color:var(--green-dark)}
.btn-yellow:active{background:#dcbe1e}
.btn-green{background:var(--green);color:var(--white)}
.btn-green:hover,.btn-green:active{background:var(--green-dark);color:var(--white)}
.btn-outline-green{border:2px solid var(--green);color:var(--green);background:none}
.btn-outline-green:hover{background:var(--green);color:var(--white)}
.btn-ghost-green{background:none;border:1px solid var(--line);color:var(--green);height:44px;padding:0 20px}
.btn-ghost-green:hover{background:var(--tint)}
.btn-outline-white{border:2px solid rgba(255,255,255,.55);color:var(--white);background:none}
.btn-outline-white:hover{background:rgba(255,255,255,.12);border-color:var(--white);color:var(--white)}

/* hero slider — homepage only. */
.hero{position:relative;background:#1c1c1c;overflow:hidden}
.hero-slides{position:relative;height:460px}
.hero-slide{position:absolute;inset:0;opacity:0;transition:opacity .7s ease;pointer-events:none}
.hero-slide.is-active{opacity:1;pointer-events:auto}

/* THE HERO IMAGE — the one place on this site where cropping is allowed,
   decided by looking at real photos rather than by applying the rule.

   Measured at 1440px: the frame is 1440x460, aspect 3.13. The library is
   79% landscape (aspect 1.33) and 21% portrait (0.75) — the inverse of the
   previous project, whose 96%-portrait library is where the "never crop"
   rule came from.

   LANDSCAPE keeps `cover`. A 1.33 source in a 3.13 frame keeps its full
   width and about 43% of its height, and it still reads unmistakably as a
   complete engine on a pallet. This is a darkened backdrop with text over
   it, not a product photo — the single engine page is where the whole
   photo lives — so a crop that keeps the subject legible is fine here.

   PORTRAIT does not survive that. A 0.75 source in a 3.13 frame keeps only
   ~24% of its height: at 1440 it renders as a close-up of an alternator, a
   serial plate and a plastic bag. Machinery, but not an engine. That fails
   the test this decision was set against. So a portrait source is CONTAINED
   over a blurred, scaled copy of itself, which fills the band without
   letterbox bars and without cutting the subject. The contained photo sits
   at 78% across so it lands clear of the headline, which occupies the left.

   Detected per image from real attachment metadata in front-page.php, not
   guessed — so a portrait photo the client uploads later gets the same
   treatment automatically.

   At 390px none of this applies: the frame is 390x400 (aspect 0.98), a
   portrait source keeps ~77% of its height and the whole engine is visible,
   so the plain cover is correct and the fill is switched off. */
.hero-slide>img{width:100%;height:100%;object-fit:cover;object-position:50% 45%}

.hero-slide--portrait .hero-fill{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:blur(26px) saturate(.75) brightness(.75);transform:scale(1.12)}
.hero-slide--portrait .hero-photo{position:absolute;inset:0;object-fit:contain;object-position:78% 50%}
.hero-shade{position:absolute;inset:0;background:linear-gradient(90deg,rgba(15,20,12,.92) 0%,rgba(15,20,12,.72) 46%,rgba(15,20,12,.15) 100%)}
.hero-inner{position:absolute;inset:0;display:flex;align-items:center;left:50%;transform:translateX(-50%)}
.hero-body{max-width:560px;display:flex;flex-direction:column;gap:18px}
.hero-kickers{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.badge-featured{background:var(--yellow);color:var(--green-dark);font-size:11.5px;font-weight:900;letter-spacing:.1em;text-transform:uppercase;padding:5px 10px}
.hero-mfr{color:#cfe0c6;font-size:12.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase}
.hero-title{font-size:44px;line-height:1.08;font-weight:900;color:var(--white);letter-spacing:-.02em;text-wrap:balance}
.hero-specs{font-size:15.5px;line-height:1.65;color:#dfe6da}
.hero-actions{display:flex;gap:12px;flex-wrap:wrap}
.hero-controls{position:absolute;right:24px;bottom:26px;display:flex;align-items:center;gap:10px}
.hero-dots{display:flex;gap:10px}
.dot{width:34px;height:4px;padding:0;border:0;background:rgba(255,255,255,.45)}
.dot.is-active{background:var(--yellow)}
.icon-btn{width:38px;height:38px;display:flex;align-items:center;justify-content:center;border:0;background:rgba(255,255,255,.14);color:var(--white)}
.icon-btn .ico{stroke:currentColor;width:18px;height:18px;stroke-width:2.75}
.icon-btn:hover{background:var(--yellow);color:var(--green-dark)}

/* Pause control (not in the design — see hero.js). One button, two icons,
   whichever matches the current state. */
.icon-btn .ico-play{display:none}
.hero.is-paused .icon-btn .ico-pause{display:none}
.hero.is-paused .icon-btn .ico-play{display:block}

/* The dots are 34x4px, far below a usable touch target. This gives each one
   a 44px-tall transparent hit area via a pseudo-element, without changing
   how the dot looks or how the row lays out. */
.dot{position:relative}
.dot::after{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:44px}

/* search band (home) */
.searchband{background:var(--green)}
.searchband-inner{display:flex;flex-direction:column;gap:10px;padding-top:20px;padding-bottom:20px}
.searchband-label{display:flex;align-items:center;gap:10px;color:var(--white);font-size:13px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}
.searchband-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.searchband-row .input{flex:1;min-width:220px;border:0}
.input,.select,.textarea{height:46px;padding:0 14px;border:1px solid #d8d8d8;background:var(--white);font-size:15px;width:100%}
.select{padding:0 12px}
.textarea{height:auto;padding:12px 14px;resize:vertical;line-height:1.6}
.input:focus,.select:focus,.textarea:focus{border-color:var(--green);outline:none}
.searchband-row .select{min-width:190px;width:auto;border:0}

/* search bar (list + detail) */
.searchbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;background:var(--white);border:1px solid var(--line);box-shadow:var(--shadow-sm);padding:12px}
.searchbar-field{display:flex;align-items:center;gap:10px;flex:1;min-width:240px;border-right:1px solid var(--line-soft);padding-right:12px}
.searchbar-input{flex:1;height:40px;border:0;font-size:15.5px;background:none;width:100%}
.searchbar-input:focus{outline:none}
.searchbar .select{width:auto;min-width:190px;height:44px}
.searchbar .btn{height:44px}

/* about */
.about{display:grid;grid-template-columns:1.05fr .95fr;gap:56px;align-items:center;padding-top:64px;padding-bottom:64px}
.about-photo{box-shadow:0 3px 14px rgba(0,0,0,.14)}
.about-photo img{width:100%;height:340px;object-fit:cover}
.about-body{display:flex;flex-direction:column;gap:16px}
.about-body p{color:#4a4a4a;line-height:1.7}
.h1{font-size:34px;font-weight:900;color:var(--green);letter-spacing:-.02em;line-height:1.15}
.h2{font-size:30px;font-weight:900;color:var(--green);letter-spacing:-.02em;line-height:1.15}
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);box-shadow:var(--shadow-sm);margin-top:10px}
.stats li{background:var(--tint);padding:18px 16px;display:flex;flex-direction:column;gap:5px}
.stat-num{font-size:26px;font-weight:900;color:var(--green);line-height:1}
.stat-label{font-size:12.5px;color:var(--text-soft)}

/* sections + cards */
.section{padding-top:44px;padding-bottom:64px}
.section-sm{padding-top:48px}
.section--tint{background:var(--tint);border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft);padding-top:56px;padding-bottom:56px}
.section-head{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;margin-bottom:28px;flex-wrap:wrap}
.section-head>div{display:flex;flex-direction:column;gap:10px}
.link-more{display:flex;align-items:center;gap:8px;font-size:13.5px;font-weight:900;letter-spacing:.06em;text-transform:uppercase}
.grid-cards{display:grid;grid-template-columns:repeat(var(--cards),minmax(0,1fr));gap:22px}
.card{background:var(--white);border:1px solid var(--line);box-shadow:var(--shadow-sm);transition:box-shadow .18s ease,transform .18s ease}
.card:hover{box-shadow:var(--shadow-lg);transform:translateY(-3px)}
.card-link{display:flex;flex-direction:column;height:100%;color:inherit}

/* FIX 1: was `height:190px` on the box with `object-fit:cover` on the img,
   which cut the top and bottom off every portrait photo.
   Now a 4:3 box (so the grid still lines up — every card's media area is
   exactly the same shape) with the photo scaled to fit inside it whole. */
.card-media{position:relative;aspect-ratio:4/3;background:var(--photo-ground);overflow:hidden}
.card-media img{width:100%;height:100%;object-fit:contain}
.card-media-empty{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.card-media-empty svg{width:44px;height:44px;fill:none;stroke:#c9c4bb;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}

.card-body{padding:16px 16px 18px;display:flex;flex-direction:column;gap:9px;flex:1}
.card-meta-row{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:22px}
.card-kicker{font-size:11px;font-weight:900;letter-spacing:.1em;text-transform:uppercase;color:var(--text-mute)}
.card-badge{background:var(--green);color:var(--white);font-size:10.5px;font-weight:900;letter-spacing:.1em;text-transform:uppercase;padding:4px 8px;white-space:nowrap;margin-left:auto}
.card-title{font-size:17.5px;font-weight:700;color:var(--green);line-height:1.25;overflow-wrap:anywhere}
.card-specs{font-size:13px;line-height:1.6;color:var(--text-soft);flex:1;overflow-wrap:anywhere}
.card-foot{display:flex;align-items:center;justify-content:space-between;border-top:1px solid var(--line-soft);padding-top:11px;margin-top:3px}
.card-price{font-size:12.5px;font-weight:700;color:var(--text)}
.card-more{font-size:12px;font-weight:900;letter-spacing:.06em;text-transform:uppercase;color:var(--green)}
.empty{border:1px solid var(--line);background:var(--tint);padding:48px;text-align:center;color:var(--text-soft);margin-top:24px}

/* FIX 2: the SOLD state.
   A band right across the photo rather than a corner badge — the point is
   that it cannot be missed while scanning a grid. Rotation is deliberately
   avoided: it makes the text harder to read at card size and fights the
   design's otherwise entirely square geometry. */
.sold-banner{position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);background:var(--sold);color:var(--white);text-align:center;font-size:20px;font-weight:900;letter-spacing:.28em;text-transform:uppercase;padding:8px 4px;text-indent:.28em}
.sold-banner--lg{font-size:34px;padding:14px 4px}
.card-badge--sold{background:var(--sold)}
.tag--sold{background:var(--sold);color:var(--white)}
.note-sold{display:flex;align-items:center;gap:10px;font-size:14px;color:#7a1109;background:#fdf2f1;border-left:4px solid var(--sold);padding:12px 14px}
/* The whole card reads as unavailable, without hiding it — a sold listing
   keeps its page and its rankings (hard rule 5). */
.card.is-sold .card-media img{opacity:.72}
.card.is-sold .card-title{color:var(--text-soft)}

/* cta band */
.cta-band{background:var(--green)}
.cta-inner{display:flex;align-items:center;justify-content:space-between;gap:28px;flex-wrap:wrap;padding-top:44px;padding-bottom:44px}
.cta-title{font-size:27px;font-weight:900;color:var(--white);letter-spacing:-.01em}
.cta-copy{font-size:15.5px;color:#d6e4d0;margin-top:8px}
.cta-actions{display:flex;gap:12px;flex-wrap:wrap}

/* page heads */
.pagehead{background:var(--tint);border-bottom:1px solid var(--line-soft)}
.pagehead-inner{display:flex;flex-direction:column;gap:14px;padding-top:34px;padding-bottom:26px}
.pagehead-row{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;flex-wrap:wrap}
.pagehead-row>div{display:flex;flex-direction:column;gap:10px}
.pagehead-meta{font-size:14px;color:var(--text-soft)}
.pagehead-copy{font-size:16px;color:var(--text-soft)}
.breadcrumb{background:var(--tint);border-bottom:1px solid var(--line-soft);font-size:13px;color:var(--text-mute)}
.breadcrumb .wrap{display:flex;gap:8px;align-items:center;padding-top:14px;padding-bottom:14px;flex-wrap:wrap}
.breadcrumb a{color:var(--text-soft)}
.breadcrumb strong{color:var(--text)}

/* engine detail */
.detail{display:grid;grid-template-columns:1.15fr 1fr;gap:48px;align-items:start;padding-top:38px}
.gallery{display:flex;flex-direction:column;gap:12px}
/* FIX 1: was `height:470px` (290px on tablet) with object-fit:cover.
   This library is overwhelmingly portrait, so that discarded roughly the
   top and bottom third of the actual product photo — on the one page whose
   entire job is showing the product.
   A 4:3 box keeps the page from reflowing as photos are swapped, and
   contain shows every photo whole inside it whatever its shape.

   NOTE: THE ASPECT-RATIO MUST SIT ON THE CONTAINER, NOT ON THE <img>.
   WordPress emits real width/height ATTRIBUTES on every image it renders
   (width="1152" height="1536"). Those make the element's height definite,
   and `aspect-ratio` only ever computes a dimension the other one leaves
   `auto` — so `aspect-ratio` on the img is silently ignored and the photo
   renders at its full intrinsic height. It computes as "4 / 3" either way,
   which is why this reads as correct in DevTools and in the stylesheet.
   Caught by measuring the rendered box (610x1536 instead of 610x458), not
   by reading the CSS.

   The frame is a fixed height rather than an aspect-ratio, and the image
   is absolutely positioned inside it. Two reasons, both found by
   measuring rather than by reading:

   - An `aspect-ratio` box still GROWS to whatever height its in-flow
     content demands, so a portrait photo stretched the frame to 610x813
     while a landscape one left it at 610x457. Swapping thumbnails then
     reflowed the whole page under the reader's cursor. Taking the image
     out of flow (position:absolute) is what makes the frame authoritative.
   - A fixed RATIO would have to pick a shape, and this library is
     overwhelmingly portrait — a 4:3 frame letterboxes almost every photo
     down the sides. A height that adapts to the viewport instead keeps
     portrait photos large without cropping the occasional landscape one.

   clamp() keeps it sensible everywhere: never shorter than 320px, never
   taller than 620px, 60% of viewport height in between. */
.gallery-main{position:relative;height:clamp(320px,60vh,620px);border:1px solid var(--line);box-shadow:var(--shadow-md);background:var(--photo-ground);overflow:hidden}
.gallery-main img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;display:block}
.gallery-empty{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--text-mute);font-size:14px}

.gallery-thumbs{display:grid;grid-template-columns:repeat(6,1fr);gap:8px}
/* FIX 1: was `height:66px` + object-fit:cover. A square box with contain
   keeps the strip on a tidy grid while still showing each photo whole, so
   a thumbnail actually previews what clicking it will show.
   Ratio on the button, for the same reason as .gallery-main above. */
.thumb{aspect-ratio:1;padding:0;border:2px solid var(--line);background:var(--photo-ground);overflow:hidden}
.thumb img{width:100%;height:100%;object-fit:contain;display:block}
.thumb.is-active{border-color:var(--green)}
.thumb:hover{border-color:var(--green-dark)}

.detail-body{display:flex;flex-direction:column;gap:18px}
.detail-body .h1{color:var(--text);font-size:38px;overflow-wrap:anywhere}
.tags{display:flex;gap:8px;flex-wrap:wrap}
.tag{font-size:11px;font-weight:900;letter-spacing:.1em;text-transform:uppercase;padding:6px 11px}
.tag--green{background:var(--green);color:var(--white)}
.tag--yellow{background:#f4f1e8;border:1px solid var(--yellow);color:#7a6410}
.specbox{border:1px solid var(--line);box-shadow:var(--shadow-sm)}
.specbox-head{background:var(--tint);border-bottom:1px solid var(--line);padding:14px 18px;display:flex;align-items:center;justify-content:space-between;gap:12px}
.specbox-head span{font-size:12px;font-weight:900;letter-spacing:.09em;text-transform:uppercase;color:var(--text-mute)}
.specbox-head strong{font-size:18px;font-weight:900;color:var(--green);text-align:right}
.specbox-body{padding:18px;font-size:15.5px;line-height:1.85;color:#4a4a4a}

/* FIX 4: specs render as a real list rather than the design's <br>-joined
   run of text. They ARE a list, and the old data's own markup says so —
   9 of the 39 engines stored them as <ul>/<li> (DISCOVERY.md). */
.spec-list{display:flex;flex-direction:column;gap:2px}
.spec-list li{overflow-wrap:anywhere}
.spec-empty{color:var(--text-mute)}

.detail-actions{display:flex;gap:12px;flex-wrap:wrap}
.note-ship{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--text-soft);background:var(--tint);border-left:4px solid var(--yellow);padding:12px 14px}

/* FIX 3: pagination. The design has none — no markup, no CSS — against a
   claimed 500+ engines. Square, bordered, and using the design's own
   green/yellow relationship so it reads as part of the same system. */
.pagination{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:40px}
.pagination .page-numbers{display:inline-flex;align-items:center;justify-content:center;min-width:44px;height:44px;padding:0 14px;border:1px solid var(--line);background:var(--white);color:var(--green);font-size:14px;font-weight:700}
.pagination a.page-numbers:hover{background:var(--tint);border-color:var(--green)}
.pagination .page-numbers.current{background:var(--green);border-color:var(--green);color:var(--white)}
.pagination .page-numbers.dots{border-color:transparent;background:none;color:var(--text-mute)}
.pagination .prev,.pagination .next{font-weight:900;letter-spacing:.06em;text-transform:uppercase;font-size:12.5px}

/* forms */
.form{display:flex;flex-direction:column;gap:16px}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.field{display:flex;flex-direction:column;gap:7px}
.field label{font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:var(--text-mute)}
.panel{border:1px solid var(--line);box-shadow:var(--shadow-md);background:var(--white)}
.panel-head{background:var(--green);padding:20px 26px;color:var(--white);font-size:17px;font-weight:900}
.panel .form{padding:28px 26px}
.inquiry{display:grid;grid-template-columns:1fr 1.2fr;border:1px solid var(--line);box-shadow:var(--shadow-sm);margin-top:44px}
.inquiry-aside{background:var(--green);padding:34px;display:flex;flex-direction:column;gap:12px;color:#d6e4d0}
.inquiry-title{font-size:25px;font-weight:900;color:var(--white);letter-spacing:-.01em}
.inquiry-contact{margin-top:auto;color:var(--yellow);font-weight:700}
.inquiry .form{padding:30px}

/* contact / sell */
.contact-grid{display:grid;grid-template-columns:1.15fr .85fr;gap:44px;align-items:start;padding-top:44px;padding-bottom:64px}
.contact-aside{display:flex;flex-direction:column;gap:22px}
.info-card{border:1px solid var(--line);box-shadow:var(--shadow-sm);background:var(--white)}
.info-card-head{display:flex;align-items:center;gap:11px;border-bottom:1px solid var(--line-soft);padding:18px 22px;font-size:12px;font-weight:900;letter-spacing:.09em;text-transform:uppercase;color:var(--text-mute)}
.info-card-body{padding:18px 22px;font-size:15.5px;line-height:1.75;color:#4a4a4a;display:flex;flex-direction:column;gap:11px}
.map{width:100%;height:230px;border:0;border-top:1px solid var(--line-soft);display:block}
.ship-card{background:var(--green);padding:24px 22px;color:var(--white)}
.ship-head{font-size:12px;font-weight:900;letter-spacing:.09em;text-transform:uppercase;color:var(--yellow);margin-bottom:8px}

/* FIX 4: plain content, for any route without a design of its own —
   Pages, 404, and anything else falling through index.php. */
.prose{display:flex;flex-direction:column;gap:20px}
.prose .entry p,.prose .entry ul,.prose .entry ol{margin-bottom:16px}
.prose .entry ul,.prose .entry ol{padding-left:22px;list-style:disc}
.prose .entry ol{list-style:decimal}
.prose .entry a{text-decoration:underline}

/* footer */
.footer{background:var(--green-deep);color:#cfdcc9;margin-top:auto}
.footer-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:44px;padding-top:52px;padding-bottom:34px}
.footer-head{font-size:12px;font-weight:900;letter-spacing:.09em;text-transform:uppercase;color:var(--yellow);margin-bottom:11px}
.footer-body{font-size:14.5px;line-height:1.75}
.footer-body a{color:#cfdcc9}
.footer-body a:hover{color:var(--white)}
.footer-bottom{background:var(--green-deepest)}
.footer-bottom-inner{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;padding-top:16px;padding-bottom:16px;font-size:13px;color:#98ac91}
.footer-bottom a{color:#98ac91}
.footer-bottom a:hover{color:var(--white)}

/* ---------- responsive: tablet ---------- */
@media (max-width:900px){
  .nav-links{display:none}
  .nav-toggle{display:flex}
  .nav-mobile:not([hidden]){display:block}
  .about,.detail,.contact-grid,.inquiry,.footer-grid,.form-row{grid-template-columns:1fr;gap:26px}
  .inquiry,.form-row{gap:0}
  .form-row{gap:16px}
  .grid-cards{--cards:2}
  .hero-slides{height:auto;min-height:430px}
  .hero-title{font-size:31px}
  .gallery-thumbs{grid-template-columns:repeat(4,minmax(0,1fr))}
  .h1{font-size:27px}
  .detail-body .h1{font-size:28px}
  .h2{font-size:24px}
  .about-photo img{height:260px}
  .brand-name{font-size:21px}
  .brand-logo{height:52px}
  .searchbar-field{border-right:0;padding-right:0;min-width:100%}
  .searchbar .select,.searchbar .btn,.searchbar .btn-ghost-green,.searchband-row .select,.searchband-row .btn{flex:1}
  .sold-banner--lg{font-size:26px}
}

/* ---------- responsive: phone ---------- */
@media (max-width:600px){
  .wrap{padding:0 18px}
  .grid-cards{--cards:1}
  .hero-slides{min-height:400px}
  /* At this width the frame is nearly square and a portrait photo shows
     almost all of itself, so the blurred fill is unnecessary weight. */
  .hero-slide--portrait .hero-fill{display:none}
  .hero-slide--portrait .hero-photo{position:static;object-fit:cover;object-position:50% 45%}
  .hero-title{font-size:26px}
  .hero-controls{right:18px;bottom:18px}
  .topbar-inner{gap:14px}
  .topbar-contact{font-size:13px}
  .nav-quote{display:none}
  .section{padding-top:32px;padding-bottom:44px}
  .about{padding-top:40px;padding-bottom:40px}
  .stats{grid-template-columns:1fr}
  .cta-title{font-size:22px}
  .btn{width:100%}
  .hero-actions .btn,.detail-actions .btn,.cta-actions .btn{width:100%}
  .inquiry-aside,.inquiry .form,.panel .form{padding:22px 18px}
  .empty{padding:28px}
  /* The searchbar's controls stack rather than squeezing onto one row. */
  .searchbar .select,.searchbar .btn{min-width:100%;flex-basis:100%}
  /* Pagination links stay at least 44px square — a real touch target. */
  .pagination{margin-top:28px}
}

/* ==========================================================================
   Forms: status banners, field errors, honeypots
   ==========================================================================
   The design's stylesheet already covers .form/.field/.input/.textarea/
   .select, which is why the custom form markup reuses those class names.
   What it has no equivalent for is any FAILURE state — the static build has
   no server behind it — so these rules are the only additions.
   ========================================================================== */

/* The banner above a form after a submission.
   It is also the anchor every redirect's #dsl-form-status fragment lands
   on, which is what moves focus here with no JavaScript involved. It is
   rendered even when empty, so that fragment always has a target. */
.dsl-form-status{margin-bottom:18px}
.dsl-form-status:empty{margin:0}
.dsl-form-status--ok,.dsl-form-status--bad{padding:16px 18px;font-size:15px;line-height:1.6;border-left:4px solid}
.dsl-form-status--ok{background:#eef5ec;border-color:var(--green);color:#24571a}
.dsl-form-status--bad{background:#fdf3f2;border-color:#a32b1c;color:#8c2417}
.dsl-form-status--ok strong{display:block;font-weight:900;margin-bottom:3px}

/* The banner receives focus via the URL fragment, so it needs a visible
   focus ring like anything else that can be focused — it carries
   tabindex="-1", and a focus a keyboard user cannot see is worse than no
   focus move at all. */
.dsl-form-status:focus{outline:2px solid var(--green);outline-offset:2px}

/* Per-field error text. Red alone would carry the meaning by colour only,
   which fails for anyone who cannot distinguish it; the message is also
   plain words attached to the field via aria-describedby. */
.dsl-field-error{margin:0;font-size:13.5px;font-weight:700;color:#a32b1c}
.input[aria-invalid="true"],.select[aria-invalid="true"],.textarea[aria-invalid="true"]{border-color:#a32b1c;background:#fffafa}
.input[aria-invalid="true"]:focus,.select[aria-invalid="true"]:focus,.textarea[aria-invalid="true"]:focus{border-color:#a32b1c;outline:2px solid #a32b1c;outline-offset:1px}

/* The two honeypots.
   HIDDEN TWO DIFFERENT WAYS ON PURPOSE — a bot that evaluates CSS well
   enough to skip an off-screen field often still fills one removed with
   display:none, and vice versa.

   Neither uses `visibility:hidden` or `type="hidden"`, because a bot that
   skips hidden inputs would walk straight past them and the trap would
   never fire.

   The fields themselves carry tabindex="-1", aria-hidden and
   autocomplete="off" so no keyboard user, screen reader or browser
   autofill can trip them on a real person's behalf — which would silently
   discard a genuine enquiry. */
.dsl-hp{position:absolute;left:-9999px;top:-9999px;width:1px;height:1px;overflow:hidden}
.dsl-hp-alt{display:none}

/* Touch targets.
   The design's .input/.select are 46px tall and .btn-block is 52px, both
   already over the 40px minimum. The submit button is widened to fill its
   column on narrow viewports by the .btn rule in the 600px block above.
   This floor is here so a future style change cannot drop below it
   silently. */
.form .btn,.form .input,.form .select{min-height:44px}

@media (prefers-reduced-motion:reduce){
  *{transition:none !important}
}
