/*
Theme Name: PlayForge
Theme URI: https://shopaii.net/playforge
Author: PlayForge
Author URI: https://shopaii.net
Description: Commercial WordPress theme for indoor playground, trampoline park and family entertainment center manufacturers. Built on Bootstrap 5, fully compatible with Elementor and WooCommerce, with a serial-key activated theme options panel, four menu locations and nine selectable page layouts including edge-to-edge three-column ones and an edge-to-edge product page. Ported from the Hugo theme of the same name.
Version: 1.18.4
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: playforge
Tags: business, e-commerce, portfolio, custom-logo, custom-menu, featured-images, footer-widgets, left-sidebar, right-sidebar, full-width-template, translation-ready, block-styles, wide-blocks, threaded-comments

PlayForge is distributed under the terms of the GNU GPL v2 or later.
Bundled Bootstrap 5.3.3 and Bootstrap Icons 1.11.3 are MIT licensed.
*/

/* ==========================================================================
   1. Design tokens

   Every colour, font, weight, radius, shadow and band background in this file
   is read from a custom property declared below. Nothing outside section 1
   contains a literal colour, so a whole new look can be produced by
   redefining tokens alone — in a child theme's style.css, in Appearance →
   Customise → Additional CSS, or per page from Elementor's custom CSS. See
   playforge-child-blue/style.css for a worked example.

   Tokens come in two kinds:

     Scale tokens  (--brand, --radius, --fw-bold, --shadow-card …) are the raw
                   values: the palette, the type weights, the radius steps.
     Role tokens   (--radius-btn, --fw-nav, --card-hover-border …) point at a
                   scale token and name the job it does. Redefine a scale token
                   to move everything that uses it; redefine a role token to
                   move one component. Roles are listed with the scale they
                   default to, so either level works.
   ========================================================================== */

:root {

  /* --- Palette ---------------------------------------------------------- */

  --ink: #17202a;
  --muted: #667085;
  --line: #e6e9ef;
  --brand: #0f766e;
  --brand-dark: #115e59;
  --accent: #f59e0b;
  --soft: #f7fafc;

  /* Spare palette slot. No rule in the theme reads it — it is here so page
     content, Elementor widgets and child-theme rules have a documented tint
     to reach for that moves with the rest of the palette. */
  --sky: #e0f2fe;

  /* Comma-separated channels for the same three colours. CSS cannot take a
     hex apart, so any rgba() built from the palette needs these alongside it.
     Redefine them together with the hex above or translucent overlays will
     keep the old hue. */
  --brand-rgb: 15, 118, 110;
  --brand-dark-rgb: 17, 94, 89;
  --accent-rgb: 245, 158, 11;

  /* Surfaces and rules. */
  --surface: #fff;            /* cards, navbar, dropdowns, widgets, inputs */
  --surface-alt: #f8fafc;     /* quiet fill: price block, table label column */
  --body-bg: var(--surface);
  --line-soft: #f1f4f7;       /* faintest divider, between list items */
  --line-alt: #e8edf2;        /* one step stronger */

  /* Text on a filled background. The accent is too light for white, so it
     carries its own ink. */
  --on-brand: #fff;
  --on-accent: #3a2a00;

  /* Brand washes, for outlined controls and their hover state. */
  --brand-tint: #d9f5f1;
  --brand-edge: #90d7d0;
  --brand-ring: #7bcac3;
  --hover-wash: rgba(15, 23, 42, .06);   /* neutral hover on a bare button */

  /* Long-form copy sits a shade softer than --ink so headings stay dominant. */
  --ink-prose: #2b3542;
  --ink-quote: #334155;

  --icon-ink: var(--brand);   /* icons in capability lists and cards */

  /* Status colours. Used by assets/css/woocommerce.css for stock, price and
     message states, where hue carries meaning and must not follow the brand.
     The tints are the notice backgrounds those colours sit on. */
  --ok: #15803d;
  --info: #0284c7;
  --danger: #b91c1c;
  --neutral: #64748b;
  --ok-tint: #f0fdf4;
  --info-tint: #f0f9ff;
  --danger-tint: #fef2f2;

  /* Dark bands. --panel-texture and --footer-texture are extra background
     layers painted over the flat colour — `none` by default, a repeating
     gradient or an image in a child theme. */
  --panel: #10202f;           /* top strip, quote band */
  --panel-deep: #08131f;      /* footer */
  --panel-ink: #dce6ef;
  --panel-icon-ink: inherit;
  --panel-border: 0;
  --panel-texture: none;
  --footer-ink: #b8c4cf;
  --footer-link-ink: #c8d3dc;
  --footer-heading-ink: var(--surface);
  --footer-icon-ink: inherit;
  --footer-border-top: 0;
  --footer-texture: none;

  /* Licence notice. Deliberately off-palette: it is enforcement copy and has
     to stay conspicuous. */
  --notice-bg: #3f1d1d;
  --notice-border: #5b2a2a;
  --notice-ink: #ffd9d9;

  /* WhatsApp keeps its own brand green — recolouring it costs recognition. */
  --whatsapp: #25d366;
  --whatsapp-hover: #1eb857;

  --selection-bg: var(--brand);
  --selection-ink: var(--on-brand);

  /* --- Typography ------------------------------------------------------- */

  --font-body: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-heading: var(--font-body);

  /* Weight scale, then the roles drawn from it. Dropping --fw-black to 700
     quietens the whole theme in one line; the roles below let single
     components move on their own. */
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-extrabold: 800;
  --fw-black: 900;

  --fw-heading: var(--fw-medium);        /* bare h1–h6; Bootstrap's own weight */
  --fw-display: var(--fw-black);         /* hero, section and page titles */
  --fw-brand: var(--fw-black);           /* the wordmark */
  --fw-btn: var(--fw-bold);
  --fw-nav: var(--fw-bold);
  --fw-menu: var(--fw-semibold);
  --fw-menu-active: var(--fw-extrabold);
  --fw-kicker: var(--fw-black);          /* section kicker */
  --fw-label: var(--fw-extrabold);       /* eyebrow, tag, chip, badge */
  --fw-card-title: var(--fw-extrabold);  /* product title in a listing */
  --fw-price: var(--fw-extrabold);
  --fw-prose-heading: var(--fw-extrabold);
  --fw-widget-title: var(--fw-extrabold);
  --fw-table-label: var(--fw-bold);
  --fw-pagination: var(--fw-bold);
  --fw-form-label: inherit;

  --tracking-heading: normal;
  --tracking-display: normal;
  --tracking-label: .08em;               /* uppercase eyebrow and kicker */
  --tracking-btn: normal;

  /* Tabular figures, for anywhere numbers should line up in a column. Set to
     `tabular-nums` in a child theme selling on specifications. */
  --numeric-figures: normal;

  --prose-width: 100%;
  --prose-size: 1.06rem;
  --prose-line-height: 1.75;
  --prose-link-ink: #000;

  /* --- Geometry --------------------------------------------------------- */

  --radius-sm: 4px;
  --radius: 6px;
  --radius-lg: 8px;

  --radius-btn: var(--radius);
  --radius-control: var(--radius);       /* inputs and selects */
  --radius-card: var(--radius-lg);       /* cards, panels, widgets, media */
  --radius-chip: var(--radius-sm);       /* tag, badge, sale flash */
  --radius-media: var(--radius);         /* gallery thumbnails */
  --radius-pill: 999px;
  --radius-badge: var(--radius-pill);    /* header cart count */
  --radius-float: 50%;                   /* floating CTA buttons */

  /* --- Elevation -------------------------------------------------------- */

  --shadow-navbar: 0 8px 28px rgba(15, 23, 42, .08);
  --shadow-dropdown: 0 12px 32px rgba(15, 23, 42, .10);
  --shadow-card: none;
  --shadow-card-hover: 0 16px 40px rgba(15, 23, 42, .10);
  --shadow-blog-hover: 0 14px 34px rgba(15, 23, 42, .08);
  --shadow-float: 0 8px 24px rgba(var(--brand-rgb), .35);
  --shadow-form: none;
  --ring: 0 0 0 .25rem rgba(var(--brand-rgb), .15);   /* focus ring on inputs */

  /* The skip link's own focus outline. Deliberately neutral rather than brand
     tinted, and deliberately heavy: it has to be obvious against whatever the
     page happens to put behind it. Lighten it and it stops doing its job. */
  --shadow-skiplink: 0 0 2px 2px rgba(0, 0, 0, .6);

  /* Card hover. A lift plus a shadow by default; set --card-hover-lift to
     `none` and give --card-hover-border a colour for a flatter, more technical
     treatment that does not shift the layout. */
  --card-hover-lift: translateY(-4px);
  --card-hover-border: var(--line);
  --blog-hover-lift: translateY(-3px);

  /* --- Page metrics ----------------------------------------------------- */

  /*   --box-width     Widest the boxed .container ever gets. 1320px is
                       Bootstrap's own xxl container, so the default changes
                       nothing. Narrowing takes effect at every breakpoint;
                       widening past 1320px takes effect from 1400px up, where
                       there is room for it. See section 14.
       --page-padding  Padding on the content area (.pf-content), as a padding
                       shorthand — "4rem 0", "3rem 1.5rem", "0", anything.
       --page-margin   Margin on the same element, same shorthand freedom.

     The Elementor Full Canvas layout ignores all three by design. */
  --box-width: 1320px;
  --page-padding: 2rem 0;
  --page-padding-sm: 2.5rem 0;
  --page-margin: 0;

  /* Side breathing room for a full-width header (Theme Options → Header & Footer
     → Header width). Bootstrap's .container-fluid carries only the boxed
     container's own .75rem gutter, which leaves the logo all but touching the
     edge of a wide screen, so the header uses this instead. Ignored while the
     header is boxed, where the container's gutter applies as usual. */
  --header-fluid-gutter: 1.5rem;

  /* Width of the sidebar column in the two-column layouts, from 992px up; the
     main column takes the rest. Bootstrap's grid steps in twelfths, so the
     markup keeps col-lg-4/col-lg-8 as the no-CSS fallback and section 14
     overrides the pair from this one token. */
  --sidebar-width: 25%;

  /* The right sidebar tracks the left unless given its own value, so the
     three-column layout is symmetric by default and either side can be tuned
     alone. The main column always takes what is left of the two. */
  --sidebar-width-right: var(--sidebar-width);

  /* Side breathing room for the edge-to-edge three-column layouts, which have no
     .container gutters of their own. Floored at 1.5rem in section 14: the row's
     g-5 gutter pulls its columns 1.5rem outwards, so anything less would put the
     content past the viewport edge and produce a horizontal scrollbar. */
  --fullscreen-sidebar-gutter: 2rem;

  /* The "Fullscreen - single col" product detail layout, from 992px up. The
     gallery is this share of the inset row — a third, as the layout's name in
     the options screen promises — with the summary column taking whatever is
     left, so widening the gallery narrows the summary and nothing has to be kept
     in step by hand.

     The gutter is both the product's side padding (the wrapper itself has none)
     and the flex gap between the two columns, which is what lines the gallery's
     left edge and the summary's right edge up with the description tabs and the
     related products below them. Until 1.17.1 this layout ran the gallery flush
     to the screen edge; that treatment survives only under the legacy
     woo-full-screen slug as a playforge_layout filter fallback. */
  --woo-fullscreen-gallery-width: 33.3333%;
  --woo-fullscreen-gutter: clamp(1.5rem, 3vw, 3.5rem);

  /* Homepage sections track --page-padding unless given their own value. */
  --section-padding: var(--page-padding);
  --section-padding-sm: 3.5rem 0;

  --alignwide-width: 1140px;

  /* --- Bands ------------------------------------------------------------ */

  /* Hero. The background stacks four layers, top to bottom: texture, overlay
     gradient, the image from --hero-image, then a flat colour so the band is
     never bare while the image loads or when none is set. */
  --hero-min-height: calc(100vh - 112px);
  --hero-texture: none;
  --hero-overlay: linear-gradient(90deg, rgba(10, 23, 38, .82) 0%, rgba(10, 23, 38, .58) 45%, rgba(10, 23, 38, .16) 100%);
  --hero-bg: #234155;
  --hero-ink: #fff;
  --hero-lead-ink: #e7edf3;
  --hero-fade: linear-gradient(180deg, rgba(255, 255, 255, 0), var(--surface) 90%);
  --hero-title-size: clamp(2.35rem, 5vw, 5.2rem);
  --hero-title-size-sm: 2.55rem;
  --hero-title-line-height: 1.02;
  /* The hero title can be set tighter than the other display type. */
  --tracking-hero: var(--tracking-display);

  --eyebrow-ink: #fef3c7;
  --eyebrow-icon-ink: inherit;
  --eyebrow-size: .82rem;
  --kicker-size: .78rem;

  --metric-grid: rgba(255, 255, 255, .2);   /* shows through the 1px gaps */
  --metric-bg: rgba(8, 18, 31, .48);
  --metric-ink: #d7e4ee;
  --metric-value-ink: inherit;
  /* `bolder` is what <strong> resolves to on its own, so this changes nothing
     until a child theme pins it to a number. */
  --fw-metric-value: bolder;
  --metric-label-size: .88rem;
  --metric-label-transform: none;
  --metric-label-tracking: normal;

  /* Page header banner. Same layer order as the hero. --page-header-bg is
     transparent by default so the gradient alone paints the band. */
  --page-header-texture: none;
  --page-header-overlay: linear-gradient(90deg, rgba(var(--brand-rgb), .96), rgba(var(--brand-dark-rgb), .88));
  --page-header-bg: transparent;
  --page-header-ink: #fff;
  --page-header-lead-ink: #e5f3f1;
  --page-header-padding: 4rem 0 3rem;
  --page-header-padding-sm: var(--page-header-padding);
  --page-header-border-bottom: 0;
  /* Single posts only, applied by .single-post .page-header. Pages, archives and
     other single post types are left sizing to their content. */
  --page-header-single-min-height: 400px;
  --page-title-size: clamp(2rem, 4vw, 3.4rem);

  /* Used in place of the band when "Show page-header with big title" is off.
     --breadcrumb-title-* style the <h1> the breadcrumb's last item then carries;
     it is deliberately sized to the trail around it, so the heading is semantic
     rather than another banner. --entry-title-size is the visible <h1> a single
     post prints above its date line — a step below the banner title, because
     without the band's colour behind it the banner size reads as shouting.
     --page-lead-* style the band's old sub-heading where one survives: the search
     result count, the 404 notice, an archive description. */
  --breadcrumb-title-size: inherit;
  --breadcrumb-title-weight: inherit;
  --breadcrumb-title-ink: inherit;
  --entry-title-size: clamp(1.6rem, 2.6vw, 2.4rem);
  --page-lead-padding: 1.6rem 0 0;
  --page-lead-ink: var(--muted);
  /* Space between an archive description and the card grid under it. The gap above
     it comes from .pf-content's own padding, so only this side needs a token. */
  --archive-intro-gap: 1.75rem;

  --breadcrumb-bg: #f2f5f7;
  --breadcrumb-divider-ink: inherit;

  --factory-min-height: 520px;
  --factory-min-height-md: 360px;
  --factory-overlay: linear-gradient(180deg, rgba(var(--brand-rgb), .08), rgba(var(--accent-rgb), .08));
  --factory-bg: #d9e6e8;

  /* Homepage builder. The About Us media and the play button over a video cover;
     see section 18. */
  --home-media-radius: var(--radius-card);
  --home-media-shadow: var(--shadow-card-hover);
  --home-play-size: 76px;
  --home-play-size-sm: 56px;
  --home-play-bg: var(--brand);
  --home-play-ink: #fff;
  --home-play-hover-bg: var(--brand-dark);
  --home-play-shadow: 0 10px 30px rgba(var(--brand-rgb), .45);
  --home-video-scrim: linear-gradient(180deg, rgba(10, 23, 38, .10), rgba(10, 23, 38, .34));

  --quote-band-padding: 5rem 0;
  --quote-band-padding-sm: var(--section-padding-sm);
  --quote-form-bg: var(--surface);
  --quote-form-border: rgba(255, 255, 255, .24);

  /* --- Components ------------------------------------------------------- */

  --card-bg: var(--surface);
  --card-image-height: 220px;
  --blog-image-height: 210px;
  --blog-list-image-width: 260px;   /* thumbnail column of a list-style card */
  --blog-list-image-height: 190px;  /* its floor, for a card whose text is short */
  --cert-border-top: 1px solid var(--line);   /* rule across the top of a certification card */
  --band-border-top: 0;
  --band-border-bottom: 0;

  --tag-bg: #e7f7f5;
  --tag-border: transparent;
  --tag-ink: var(--brand-dark);
  --tag-size: .78rem;
  --tag-transform: none;
  --tag-tracking: normal;
  --tag-hover-bg: var(--tag-bg);
  --tag-hover-border: var(--tag-border);

  --step-bg: #fff3d5;         /* numbered process step */
  --step-ink: #925a00;
  --step-shadow: none;

  --control-border: #d7dde5;
  --control-focus-border: var(--brand-ring);
  --control-min-height: 46px;
  --label-ink: inherit;
  --label-size: inherit;
  --label-transform: none;
  --label-tracking: normal;

  /* Block-editor buttons inside WooCommerce blocks: the product grid the cart
     page renders when the cart is empty, and the All Products block. The block
     editor gives those buttons a dark slate fill of its own that ignores the
     palette completely, and against a light page it reads as a hole punched in
     the grid. assets/css/woocommerce.css repaints them from these tokens.

     Grey border rather than --brand-edge on purpose: several of these sit in a
     row under the product images, and a row of brand-edged buttons competes
     with the products it belongs to. The brand only appears on hover. */
  --block-btn-bg: var(--surface);
  --block-btn-ink: var(--ink);
  --block-btn-border: var(--line);
  --block-btn-bg-hover: var(--soft);
  --block-btn-ink-hover: var(--brand-dark);
  --block-btn-border-hover: var(--brand-edge);

  --price-block-bg: var(--surface-alt);
  --price-block-border: var(--line);
  /* Overridden on its own to put a coloured rule down the leading edge. */
  --price-block-edge: 1px solid var(--price-block-border);

  --spec-label-width: 34%;
  --spec-label-width-sm: var(--spec-label-width);
  --spec-label-bg: var(--surface-alt);
  /* Bootstrap paints table text with --bs-emphasis-color; naming it here means
     a child theme can quieten the label column without touching the values. */
  --spec-label-ink: var(--bs-emphasis-color);
  --spec-value-ink: var(--bs-emphasis-color);
  --spec-label-size: inherit;
  --spec-label-transform: none;
  --spec-label-tracking: normal;

  --widget-title-ink: inherit;
  --widget-title-size: 1.05rem;
  --widget-title-border: 2px solid var(--brand);
  --widget-divider: var(--line-soft);
  /* One step of indent per level in a hierarchical widget list, so a third level
     indents twice. The guide line down the leading edge is what makes the nesting
     legible at a glance — a 1rem indent on its own reads as a ragged margin once a
     few long category names wrap. */
  --widget-nest-indent: 1rem;
  --widget-nest-guide: 1px solid var(--line);
  --widget-nest-ink: var(--muted);
  --widget-nest-size: .92em;
  --widget-parent-weight: var(--fw-semibold);

  --pagination-hover-bg: var(--brand-tint);
  --pagination-hover-border: var(--brand-ring);
  --pagination-hover-ink: var(--brand-dark);

  --map-hint-bg: rgba(var(--brand-rgb), .94);
  --map-hint-weight: var(--fw-semibold);

  --nav-ink: #263241;
  --nav-hover-ink: var(--brand);

  /* The first row of the two-row header (Theme Options → Header & Footer → Main
     menu width → "Full width"), which carries the logo and the search while the
     menu takes the row below. It answers to --surface by default, so the two-row
     header is the same white as the one-row bar it replaces and a child theme that
     retints --surface carries this along; give it a value of its own to set the two
     rows apart. Read by nothing while the menu is inline. */
  --headline-bg: var(--surface);
  --headline-padding: .5rem 0;
}

/* Bootstrap's own tokens, pointed at the palette above. Without this, anything
   Bootstrap, Elementor or a plugin renders from its defaults — utilities,
   links, alerts, tables, focus rings — stays Bootstrap indigo while the theme
   is teal. Everything here is expressed through theme tokens, so retinting
   :root above carries Bootstrap along with it. */
:root {
  --bs-primary: var(--brand);
  --bs-primary-rgb: var(--brand-rgb);
  --bs-link-color: var(--brand-dark);
  --bs-link-color-rgb: var(--brand-dark-rgb);
  --bs-link-hover-color: var(--brand);
  --bs-border-color: var(--line);
  --bs-border-radius: var(--radius);
  --bs-focus-ring-color: rgba(var(--brand-rgb), .25);
}

body {
  color: var(--ink);
  background-color: var(--body-bg);
  font-family: var(--font-body);
}

a { color: inherit; }

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: var(--fw-heading);
  letter-spacing: var(--tracking-heading);
}

.wp-block-heading {font-size: 1.5em;}

::selection { background: var(--selection-bg); color: var(--selection-ink); }

/* Figures line up in a column wherever numbers carry meaning — but only if
   --numeric-figures asks for it. */
.spec-table,
.price-block,
.metric,
.pf-pagination,
table.shop_attributes,
.woocommerce-Price-amount {
  font-variant-numeric: var(--numeric-figures);
}

/* ==========================================================================
   2. Buttons
   ========================================================================== */

.btn {
  border-radius: var(--radius-btn);
  font-weight: var(--fw-btn);
  letter-spacing: var(--tracking-btn);
}

/* Bootstrap leaves the hover, active, disabled and focus-ring variables unset
   on a bare .btn, so a custom variant that fills only --bs-btn-bg turns
   transparent when pressed or disabled and shows no focus ring at all. Each
   variant below therefore states the full set. */
.btn-brand {
  --bs-btn-bg: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand-dark);
  --bs-btn-hover-border-color: var(--brand-dark);
  --bs-btn-active-bg: var(--brand-dark);
  --bs-btn-active-border-color: var(--brand-dark);
  --bs-btn-disabled-bg: var(--brand);
  --bs-btn-disabled-border-color: var(--brand);
  --bs-btn-color: var(--on-brand);
  --bs-btn-hover-color: var(--on-brand);
  --bs-btn-active-color: var(--on-brand);
  --bs-btn-disabled-color: var(--on-brand);
  --bs-btn-focus-shadow-rgb: var(--brand-rgb);
}

.btn-outline-brand {
  --bs-btn-color: var(--brand-dark);
  /* Transparent rather than --surface, so the button reads as an outline on a
     tinted .band too. On the white surfaces it started life on, the two are
     indistinguishable. */
  --bs-btn-bg: transparent;
  --bs-btn-border-color: var(--brand-edge);
  --bs-btn-hover-bg: var(--brand-tint);
  --bs-btn-hover-border-color: var(--brand-ring);
  --bs-btn-hover-color: var(--brand-dark);
  --bs-btn-active-bg: var(--brand-tint);
  --bs-btn-active-border-color: var(--brand-ring);
  --bs-btn-active-color: var(--brand-dark);
  --bs-btn-disabled-color: var(--muted);
  --bs-btn-disabled-bg: transparent;
  --bs-btn-disabled-border-color: var(--line);
  --bs-btn-focus-shadow-rgb: var(--brand-rgb);
}

/* Secondary call to action, for the request that should not compete with the
   primary one — "Download catalogue" beside "Get a quote". */
.btn-accent {
  --bs-btn-bg: var(--accent);
  --bs-btn-border-color: var(--accent);
  --bs-btn-hover-bg: var(--accent);
  --bs-btn-hover-border-color: var(--accent);
  --bs-btn-active-bg: var(--accent);
  --bs-btn-active-border-color: var(--accent);
  --bs-btn-disabled-bg: var(--accent);
  --bs-btn-disabled-border-color: var(--accent);
  --bs-btn-color: var(--on-accent);
  --bs-btn-hover-color: var(--on-accent);
  --bs-btn-active-color: var(--on-accent);
  --bs-btn-disabled-color: var(--on-accent);
  --bs-btn-focus-shadow-rgb: var(--accent-rgb);
}

/* Bootstrap compiles .btn-primary to literal hex, so retinting --bs-primary
   does not reach it. Elementor widgets and many plugins emit .btn-primary, so
   it is mapped onto the brand explicitly. */
.btn-primary {
  --bs-btn-bg: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand-dark);
  --bs-btn-hover-border-color: var(--brand-dark);
  --bs-btn-active-bg: var(--brand-dark);
  --bs-btn-active-border-color: var(--brand-dark);
  --bs-btn-disabled-bg: var(--brand);
  --bs-btn-disabled-border-color: var(--brand);
  --bs-btn-color: var(--on-brand);
  --bs-btn-hover-color: var(--on-brand);
  --bs-btn-active-color: var(--on-brand);
  --bs-btn-disabled-color: var(--on-brand);
  --bs-btn-focus-shadow-rgb: var(--brand-rgb);
}

.btn-outline-primary {
  --bs-btn-color: var(--brand-dark);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand);
  --bs-btn-hover-border-color: var(--brand);
  --bs-btn-hover-color: var(--on-brand);
  --bs-btn-active-bg: var(--brand-dark);
  --bs-btn-active-border-color: var(--brand-dark);
  --bs-btn-active-color: var(--on-brand);
  --bs-btn-focus-shadow-rgb: var(--brand-rgb);
}

/* ==========================================================================
   3. Header — top strip and navbar
   ========================================================================== */

.top-strip {
  background: var(--panel-texture), var(--panel);
  color: var(--panel-ink);
  font-size: .875rem;
  border-bottom: var(--panel-border);
}
.top-strip a { text-decoration: none; color: inherit; }
.top-strip a:hover { color: var(--surface); }
.top-strip i { color: var(--panel-icon-ink); }

.navbar { background-color: var(--surface); box-shadow: var(--shadow-navbar); }

/* The two-row header: row 1, the logo and the search. Only present while Main menu
   width is "Full width", where template-parts/nav_fullwidth.php prints it above the
   .navbar that then carries the menu alone. Deliberately not a .navbar itself —
   initNav() in assets/js/site.js takes the first .navbar on the page and looks
   inside it for the menu, so a second one here would break every submenu.

   The row is a flex line rather than Bootstrap's navbar flex, so the two rules
   below are all it takes to place its two children. */
.pf-headline { background-color: var(--headline-bg); padding: var(--headline-padding); }
.pf-headline > .container,
.pf-headline > .container-fluid { display: flex; flex-wrap: wrap; align-items: center; }
.pf-headline .navbar-brand { margin-inline-end: 1rem; }

/* Both of these override a rule written for the one-row bar, and both are needed
   for the same reason: that bar places the search by pushing it past
   .navbar-collapse, and this row has no collapse to push past.

   The icon's own margin-left: auto already puts it at the right-hand end, but the
   992px rule further down replaces it with a fixed .5rem — which in a row containing
   only the logo would leave the icon sitting against the wordmark. The pill takes the
   same fixed margin there. Weight, not order, is what settles these: (0,2,0) beats
   the (0,1,0) inside the media query either way. The `order` is restated at the value
   the media query uses so the icon stays last in this row at every width, behind the
   before-search slot and the pill. */
.pf-headline .pf-search-toggle { order: 3; margin-inline-start: auto; margin-inline-end: 0; }

@media (min-width: 992px) {
  .pf-headline .pf-search-inline { margin-inline-start: auto; }
}

/* The author's own slot immediately before the header search — Theme Options →
   Header & Footer → Content before Search ICON, a language switcher on most sites.
   Nothing is printed for it while the field is empty, so on a site that has not
   filled it in these rules match no element at all.

   What they do is fit whatever markup arrives into a bar that was sized for
   controls: a flex line, so a switcher made of several links reads as one group
   rather than as loose words; the nav's own ink and link colours, so it belongs to
   the header rather than to the page; and no bottom margin on the block elements a
   plugin's switcher tends to bring with it. Its width is deliberately not capped —
   a switcher too wide for a phone is one to shorten in the field, and silently
   clipping it would hide the problem instead of showing it. */
.pf-header-before-search {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .5rem;
  font-size: .875rem;
  line-height: 1.2;
  color: var(--nav-ink);
}
.pf-header-before-search > * { margin-bottom: 0; }
.pf-header-before-search a { color: inherit; text-decoration: none; }
.pf-header-before-search a:hover,
.pf-header-before-search a:focus-visible { color: var(--nav-hover-ink); }
.pf-header-before-search img { display: block; max-height: 1.25rem; width: auto; }

/* Which element carries the auto margin that pushes the search group to the
   right-hand end depends on whether this slot is there — and it has to be exactly
   one of them, because two auto margins split the free space between them and would
   leave the slot stranded in the middle of the row. So the slot takes it, and the
   two search controls give theirs up to a fixed gap whenever the slot precedes them.

   These come after the .pf-headline rules above on purpose: they carry the same
   (0,2,0) weight, so source order is what settles which wins, and in the two-row
   header the answer has to be these. Below 992px the one-row bar reaches the same
   arrangement the same way — there the free space is real, since .navbar-collapse
   only grows to fill the bar from 992px up. */
.pf-header-before-search { margin-inline-start: auto; }
.pf-header-before-search ~ .pf-search-toggle,
.pf-header-before-search ~ .pf-search-inline { margin-inline-start: .5rem; }

/* The hero asks for the viewport less the header, and the header is a row taller
   under "Full width". Measured at 1400px rather than assumed: the one-row header
   runs 99px (37 strip + 62 bar) and the two-row one 147px (37 + 54 + 56), so the
   extra row costs 48px — less than its own 54px, because the logo leaves the bar
   and the bar loses the 36px it was sized around. 112 + 48 = 160. The 112px base
   above already carries its own slack for a taller logo; this only adds the row.
   Set on the body class playforge_body_classes() adds for the setting, so it
   reaches the token by inheritance and a child theme has a hook for the rest of
   the two-row header. */
.pf-menu-fullwidth { --hero-min-height: calc(100vh - 160px); }

/* Full-width header. Both header rows swap their .container for .container-fluid
   together — the top strip and the bar — and the search panel with them, so the
   three keep one left edge; this is the gutter that keeps their contents off the
   edge of the screen. Only present while Header width is "Full width". */
.pf-header-fluid { padding-inline: var(--header-fluid-gutter); }

.navbar-brand { font-weight: var(--fw-brand); }
.navbar-brand span { color: var(--brand); }
.navbar-brand img { max-height: 48px; width: auto; height: auto; }
.nav-link { font-weight: var(--fw-nav); color: var(--nav-ink); }
.nav-link:hover, .nav-link:focus { color: var(--nav-hover-ink); }
.navbar-nav .dropdown-menu { border-color: var(--line); border-radius: var(--radius); box-shadow: var(--shadow-dropdown); }
.navbar-nav .dropdown-item { font-weight: var(--fw-menu); border-radius: var(--radius-sm); }

/* Bootstrap marks the current item with its blue --bs-dropdown-link-active-bg,
   which turns a whole branch blue on any page whose menu item lives inside a
   dropdown — a post filed under a parent item, say. The menu stays white; the
   current item is marked by weight instead. */
.navbar-nav .dropdown-menu {
  --bs-dropdown-link-active-color: var(--ink);
  --bs-dropdown-link-active-bg: transparent;
}
.navbar-nav .dropdown-item.active { font-weight: var(--fw-menu-active); }
/* Bootstrap's .active rule comes after its :hover rule, so without this the
   current item is the one item that does not respond to the pointer. */
.navbar-nav .dropdown-item.active:hover,
.navbar-nav .dropdown-item.active:focus { background-color: var(--bs-dropdown-link-hover-bg); }

/* Pressed, as opposed to current: a brief brand-coloured flash. */
.navbar-nav .dropdown-item:active { background-color: var(--brand); color: var(--on-brand); }

/* Chevron button beside a parent item. It opens the level below; the text next
   to it stays an ordinary link. Hidden where hover can do the job — see the
   "Multi-level navigation" block in assets/js/site.js. */
.pf-submenu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 2.5rem;
  padding: .4rem;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: inherit;
  line-height: 1;
}
.pf-submenu-toggle:hover, .pf-submenu-toggle:focus-visible { background: var(--hover-wash); }
.pf-submenu-toggle .bi { transition: transform .15s ease-in-out; }
.pf-open > .pf-submenu-toggle .bi { transform: rotate(180deg); }

/* Search icon in the bar, and the panel it opens under it.

   The button is a sibling of .navbar-collapse rather than a child of it, so the
   icon is there on a phone without opening the menu first. That DOM position
   would place it left of the menu on the wide layout, so `order` below moves it
   behind the collapse — which grows to fill the bar — leaving the icon at the
   right end, next to the CTA button. */
.pf-search-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 2.5rem;
  height: 2.5rem;
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--nav-ink);
  font-size: 1.125rem;
  line-height: 1;
}
.pf-search-toggle:hover,
.pf-search-toggle:focus-visible,
.pf-search-toggle[aria-expanded="true"] { background: var(--hover-wash); color: var(--nav-hover-ink); }

/* The panel hangs off the bar instead of sitting inside it: absolute keeps the
   bar the same height open or closed, so opening the search shifts nothing on
   the page behind it. .sticky-top makes the bar a positioned ancestor, so this
   resolves against the bar and not the page. */
.pf-search-panel {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  padding: .875rem 0;
  background-color: var(--surface);
  border-top: 1px solid var(--line);
  box-shadow: var(--shadow-navbar);
}
/* Bootstrap's reboot already carries [hidden] { display: none !important }, but
   stating it here means the panel is not left open by a child theme or a build
   that loads style.css without Bootstrap. */
.pf-search-panel[hidden] { display: none; }

/* The pill field of the "inline" search style (template-parts/nav.php).

   Hidden here rather than shown, because it is a wide-layout control only: below
   992px the bar already holds the logo and the hamburger, so that width keeps the
   icon and the panel and this stays out of the way. The @media block further down
   is what turns it on and switches the icon off. */
.pf-search-inline { display: none; }

@media (max-width: 991.98px) {
  /* Between the brand and the hamburger, pushed over to sit beside it. */
  .pf-search-toggle { margin-right: .25rem; }
}

@media (max-width: 991.98px) {
  /* Stacked menu: link and chevron share a row, the submenu takes the next one. */
  .navbar-nav li { display: flex; flex-wrap: wrap; align-items: center; }
  /* Bootstrap gives .dropdown-item width: 100%, which would wrap the chevron
     onto its own line — grow from zero instead. */
  .navbar-nav li > .nav-link,
  .navbar-nav li > .dropdown-item { flex: 1 1 0; width: auto; min-width: 0; }
  .navbar-nav li > .dropdown-divider { flex: 1 0 100%; }
  .navbar-nav li > .dropdown-menu { flex: 1 0 100%; margin: 0 0 .25rem; padding-left: .5rem; border: 0; border-left: 2px solid var(--line); border-radius: 0; box-shadow: none; }
  /* The chevron already says there is more below. */
  .navbar-nav .dropdown-toggle::after { display: none; }
}

@media (min-width: 992px) {
  /* Levels two and deeper open to the side of their parent. */
  .navbar-nav .dropdown-menu li { position: relative; }
  .navbar-nav .dropdown-menu .dropdown-menu { top: 0; left: 100%; margin-top: -.5rem; }
  /* Flipped by site.js when the default side would leave the viewport. */
  .navbar-nav .dropdown-menu .dropdown-menu.pf-flip { left: auto; right: 100%; }
  .navbar-nav > li > .dropdown-menu.pf-menu-end { left: auto; right: 0; }
  /* A caret pointing into the submenu reads better than one pointing down. */
  .navbar-nav .dropdown-menu .dropdown-item.dropdown-toggle { display: flex; align-items: center; justify-content: space-between; }
  .navbar-nav .dropdown-menu .dropdown-item.dropdown-toggle::after { margin-left: .75rem; border-top: .3em solid transparent; border-right: 0; border-bottom: .3em solid transparent; border-left: .3em solid; }

  /* Hover opens the submenu, so the chevron is redundant on the wide layout. */
  .pf-submenu-toggle { display: none; }

  /* …unless the pointer cannot hover (a tablet in landscape), where the chevron
     is the only way in and shares a row with the link. site.js sets the class. */
  .navbar.pf-no-hover .pf-submenu-toggle { display: inline-flex; }
  .navbar.pf-no-hover .navbar-nav li { display: flex; flex-wrap: wrap; align-items: center; }
  .navbar.pf-no-hover .navbar-nav li > .nav-link,
  .navbar.pf-no-hover .navbar-nav li > .dropdown-item { flex: 1 1 0; width: auto; min-width: 0; }
  .navbar.pf-no-hover .navbar-nav .dropdown-toggle::after { display: none; }

  /* Past the collapse, so the search lands to the right of the CTA button — the
     collapse grows to fill the bar, and everything left on order: 0 stays in front
     of it. The three values keep the group in the sequence the fields describe:
     the before-search slot, then whichever search control the style prints. */
  .pf-header-before-search { order: 1; }
  .pf-search-toggle { order: 3; margin-left: .5rem; }

  /* A field the full width of the container reads as a section of the page
     rather than as something the icon opened; this keeps it under the icon. */
  .pf-search-panel .input-group { max-width: 26rem; margin-left: auto; }

  /* Inline style, wide layout: the pill takes over and the icon it replaces goes,
     along with the panel that icon would have opened. Only .pf-search-inline-mode
     carries these, so the dropdown style is untouched. */
  .pf-search-inline-mode .pf-search-toggle,
  .pf-search-inline-mode .pf-search-panel { display: none; }

  /* The pill itself. It comes after .navbar-collapse in the markup and the
     collapse grows to fill the bar, so DOM order alone would already place it —
     unlike the icon, which sits before the collapse and has to be moved past it.
     The order is written out only to settle it against the before-search slot,
     which has to stay in front of the pill and is earlier in the markup. */
  .pf-search-inline {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    order: 2;
    width: 14rem;
    margin-left: .5rem;
    padding: .125rem .125rem .125rem .875rem;
    background-color: var(--surface);
    border: 1px solid var(--control-border);
    /* Half of any plausible height, which is what makes the ends semicircular
       however tall the row inside turns out to be. */
    border-radius: 999px;
  }
  /* The ring goes on the pill rather than on the field, so what lights up is the
     whole control and not a rectangle inside a rounded border. :focus-within is
     what carries it there from the field. The two tokens are the ones every other
     input in the theme focuses with, so a child theme retints this along with the
     rest of its forms. */
  .pf-search-inline:focus-within { border-color: var(--control-focus-border); box-shadow: var(--ring); }

  .pf-search-inline-field {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--nav-ink);
    font-size: .9375rem;
    line-height: 1.5;
  }
  /* The pill shows focus for it; a second ring inside the first reads as an error. */
  .pf-search-inline-field:focus, .pf-search-inline-field:focus-visible { outline: 0; box-shadow: none; }
  /* WebKit draws its own clear button on type="search" and it collides with the
     submit button beside it. */
  .pf-search-inline-field::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

  .pf-search-inline-submit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background-color: var(--brand);
    color: var(--on-brand);
    font-size: .875rem;
    line-height: 1;
  }
  .pf-search-inline-submit:hover, .pf-search-inline-submit:focus-visible { background-color: var(--brand-dark); color: var(--on-brand); }
}

/* ==========================================================================
   4. Hero
   Retained for rebuilding the homepage hero in Elementor with original styling.
   ========================================================================== */

.hero {
  min-height: var(--hero-min-height);
  display: flex;
  align-items: center;
  position: relative;
  overflow: hidden;
  background:
    var(--hero-texture),
    var(--hero-overlay),
    var(--hero-image, none) center / cover no-repeat,
    var(--hero-bg);
}
.hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 88px;
  background: var(--hero-fade);
}
.hero-content { position: relative; z-index: 1; max-width: 720px; color: var(--hero-ink); padding: 5rem 0 7rem; }
.eyebrow {
  display: inline-flex; align-items: center; gap: .5rem;
  color: var(--eyebrow-ink); font-size: var(--eyebrow-size); font-weight: var(--fw-label);
  text-transform: uppercase; letter-spacing: var(--tracking-label);
}
.eyebrow i { color: var(--eyebrow-icon-ink); }
.hero h1 {
  font-size: var(--hero-title-size);
  line-height: var(--hero-title-line-height);
  font-weight: var(--fw-display);
  letter-spacing: var(--tracking-hero);
  margin: 1rem 0 1.25rem;
}
.hero .lead { color: var(--hero-lead-ink); max-width: 620px; }

.metric-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  max-width: 640px;
  background: var(--metric-grid);
  margin-top: 2rem;
}
.metric { background: var(--metric-bg); padding: 1rem; }
.metric strong { display: block; font-size: 1.5rem; font-weight: var(--fw-metric-value); color: var(--metric-value-ink); }
.metric span {
  display: block; color: var(--metric-ink);
  font-size: var(--metric-label-size);
  text-transform: var(--metric-label-transform);
  letter-spacing: var(--metric-label-tracking);
}

/* ==========================================================================
   5. Sections and utilities
   ========================================================================== */

.pf-section { padding: var(--section-padding); margin: var(--page-margin); }
.section-kicker { color: var(--brand-dark); font-weight: var(--fw-kicker); text-transform: uppercase; font-size: var(--kicker-size); letter-spacing: var(--tracking-label); }
.section-title { font-weight: var(--fw-display); letter-spacing: var(--tracking-display); }
.text-muted-2 { color: var(--muted); }
.text-brand { color: var(--brand); }
.fw-black { font-weight: var(--fw-display); }
.band { background: var(--soft); border-top: var(--band-border-top); border-bottom: var(--band-border-bottom); }

/* ==========================================================================
   6. Cards
   ========================================================================== */

.product-card, .case-card, .process-item, .cert-item {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--card-bg);
  height: 100%;
  box-shadow: var(--shadow-card);
}
.product-card img, .case-card img { width: 100%; height: var(--card-image-height); object-fit: cover; border-radius: var(--radius-card) var(--radius-card) 0 0; }
.product-card { transition: transform .2s, box-shadow .2s, border-color .2s; }
.product-card:hover { transform: var(--card-hover-lift); box-shadow: var(--shadow-card-hover); border-color: var(--card-hover-border); }
.cert-item { border-top: var(--cert-border-top); }
.cert-item i { color: var(--icon-ink); }

/* Scope to the meta-line badge: on tag archives WordPress puts `tag` on
   <body>, so a bare .tag would match body itself and shrink-wrap the page. */
.meta .tag {
  display: inline-flex; align-items: center; min-height: 28px;
  padding: .25rem .55rem; border-radius: var(--radius-chip);
  background: var(--tag-bg); border: 1px solid var(--tag-border); color: var(--tag-ink);
  font-size: var(--tag-size); font-weight: var(--fw-label);
  text-transform: var(--tag-transform); letter-spacing: var(--tag-tracking);
  text-decoration: none;
  transition: background-color .15s ease, border-color .15s ease;
}
.meta .tag:hover { background: var(--tag-hover-bg); border-color: var(--tag-hover-border); }

.capability-list { list-style: none; padding: 0; margin: 0; }
.capability-list li { display: flex; gap: .75rem; padding: .7rem 0; border-bottom: 1px solid var(--line-alt); }
.capability-list li:last-child { border-bottom: 0; }
.capability-list i { color: var(--icon-ink); font-size: 1.15rem; }

.factory-photo {
  min-height: var(--factory-min-height); border-radius: var(--radius-card);
  background:
    var(--factory-overlay),
    var(--factory-image, none) center / cover no-repeat,
    var(--factory-bg);
}

.process-number {
  width: 42px; height: 42px;
  display: inline-grid; place-items: center;
  border-radius: var(--radius);
  background: var(--step-bg); color: var(--step-ink); font-weight: var(--fw-display);
  box-shadow: var(--step-shadow);
}

/* ==========================================================================
   7. Quote band and forms
   ========================================================================== */

.quote-band { background: var(--panel-texture), var(--panel); color: var(--on-brand); padding: var(--quote-band-padding); }
.quote-form {
  background: var(--quote-form-bg); color: var(--ink);
  border-radius: var(--radius-card);
  border: 1px solid var(--quote-form-border);
  box-shadow: var(--shadow-form);
}
.form-control, .form-select { border-radius: var(--radius-control); border-color: var(--control-border); min-height: var(--control-min-height); }
.form-control:focus, .form-select:focus {
  border-color: var(--control-focus-border);
  box-shadow: var(--ring);
}
.form-label {
  font-weight: var(--fw-form-label);
  font-size: var(--label-size);
  color: var(--label-ink);
  text-transform: var(--label-transform);
  letter-spacing: var(--label-tracking);
}
.form-check-input:checked { background-color: var(--brand); border-color: var(--brand); }
.form-check-input:focus { border-color: var(--control-focus-border); box-shadow: var(--ring); }

/* ==========================================================================
   8. Page header and breadcrumb
   ========================================================================== */

.page-header {
  background:
    var(--page-header-texture),
    var(--page-header-overlay),
    var(--page-header-image, none) center / cover no-repeat,
    var(--page-header-bg);
  color: var(--page-header-ink);
  padding: var(--page-header-padding);
  border: 0;
  border-bottom: var(--page-header-border-bottom);
  /* Vertical centring for every banner. It only becomes visible once the band
     is taller than its content — a min-height, or an Elementor/child theme
     height — but it is set here so any such band centres without extra rules. */
  display: flex;
  align-items: center;
}
/* Required by the flex centring above: as a flex item the container would
   shrink to its text, and its own margin-inline: auto would then pull the title
   to the horizontal centre. */
.page-header > .container { width: 100%; }
.page-header h1 { font-weight: var(--fw-display); font-size: var(--page-title-size); letter-spacing: var(--tracking-display); margin: 0; }
.page-header .lead { color: var(--page-header-lead-ink); max-width: 780px; margin-top: .8rem; }

/* Taller banner on single posts. Scoped to .single-post, not .single, so
   products and other single post types keep the content-sized band. */
.single-post .page-header { min-height: var(--page-header-single-min-height); }

/* The band's stand-in when "Show page-header with big title" is off. Nothing here
   paints a background: the heading moves into the breadcrumb's last item, or into
   the article on a single post, and only the sub-heading keeps a block of its own.
   Bottom padding is left at zero deliberately, so the gap below is the top padding
   of whatever follows (.pf-content's --page-padding) rather than the two added. */
.pf-page-lead { padding: var(--page-lead-padding); }
.pf-page-lead .lead { color: var(--page-lead-ink); max-width: 780px; margin: 0; }

/* The <h1> inside .breadcrumb-item.active. Sized and weighted to the trail, so
   the trail still reads as a trail — `display: inline` keeps it on the same line
   as the separators either side of it. */
.breadcrumb-title {
  display: inline;
  font-size: var(--breadcrumb-title-size); font-weight: var(--breadcrumb-title-weight);
  color: var(--breadcrumb-title-ink); letter-spacing: inherit; line-height: inherit;
  margin: 0;
}

/* A single post's own heading, above its category and date line. */
.entry > .entry-title {
  font-weight: var(--fw-display); font-size: var(--entry-title-size);
  letter-spacing: var(--tracking-display); margin: 0 0 .6rem;
}

.breadcrumb-wrap {
  background: var(--breadcrumb-bg); border-bottom: 1px solid var(--line); padding: .8rem 0; font-size: .9rem;
}
.breadcrumb-wrap .breadcrumb { margin: 0; }
.breadcrumb-item a { color: var(--brand-dark); text-decoration: none; }
.breadcrumb-item a:hover { text-decoration: underline; }
.breadcrumb-item.active { color: var(--muted); }
.breadcrumb-item + .breadcrumb-item::before { color: var(--breadcrumb-divider-ink); }

/* ==========================================================================
   9. Product detail
   ========================================================================== */

.product-gallery-main {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radius-card); border: 1px solid var(--line);
  background: var(--surface-alt);
}
.thumb-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem; margin-top: .6rem; }
.thumb-row img {
  width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--radius-media);
  border: 2px solid transparent; cursor: pointer; transition: border-color .15s;
}
.thumb-row img.active, .thumb-row img:hover { border-color: var(--brand); }
.price-block {
  border: 1px solid var(--price-block-border);
  border-left: var(--price-block-edge);
  border-radius: var(--radius-card); padding: 1.2rem 1.4rem;
  background: var(--price-block-bg); margin: 1rem 0 1.4rem;
}

/* The specification table is what closes the sale, so it is treated as a
   datasheet: a label column on the left, quiet rules, and cell padding set
   through Bootstrap's own table variables. */
.spec-table, table.shop_attributes { border-color: var(--line); }
.spec-table th, table.shop_attributes th {
  width: var(--spec-label-width);
  background: var(--spec-label-bg);
  color: var(--spec-label-ink);
  font-weight: var(--fw-table-label);
  font-size: var(--spec-label-size);
  text-transform: var(--spec-label-transform);
  letter-spacing: var(--spec-label-tracking);
}
.spec-table td, table.shop_attributes td { color: var(--spec-value-ink); }

/* ==========================================================================
   10. Blog
   ========================================================================== */

/* The category/tag description, from playforge_archive_intro(). It sits inside
   .pf-main-col, directly above the card grid, so it needs no width of its own —
   the column already gives it one, and that shared left edge is the whole point of
   putting it there rather than in the full-width lead band. Only the gap below it
   and the prose treatment are set here. */
.pf-archive-intro {
  max-width: var(--prose-width);
  margin-bottom: var(--archive-intro-gap);
  color: var(--ink-prose);
}
/* A description is authored text, so it can arrive as more than one paragraph, a
   list or a heading. Trimming the outer margins keeps the first line level with
   the top of the column and stops a trailing margin from doubling the gap above
   the grid. */
.pf-archive-intro > :first-child { margin-top: 0; }
.pf-archive-intro > :last-child { margin-bottom: 0; }
.pf-archive-intro p,
.pf-archive-intro ul,
.pf-archive-intro ol { line-height: var(--prose-line-height); font-size: var(--prose-size); }
.pf-archive-intro a { color: var(--prose-link-ink); }

.blog-card { border: 1px solid var(--line); border-radius: var(--radius-card); overflow: hidden; background: var(--card-bg); height: 100%; box-shadow: var(--shadow-card); transition: transform .2s, box-shadow .2s, border-color .2s; }
.blog-card:hover { transform: var(--blog-hover-lift); box-shadow: var(--shadow-blog-hover); border-color: var(--card-hover-border); }
.blog-card img { width: 100%; height: var(--blog-image-height); object-fit: cover; }
.blog-card .meta { font-size: .82rem; color: var(--muted); }

/* Post list style: list. The grid card is a column — image on top, text under it —
   so the list variant lays the same card sideways instead of being a second card.
   Only the listing templates ask for it; related posts and the homepage news
   section stay grids and never carry this class.

   height: 100% is what makes the cards in a grid row match each other; a list card
   is alone on its row, so it is dropped and the card takes the height of its text. */
.blog-card--list { height: auto; }
.blog-card--list .pf-list-row { display: flex; align-items: stretch; }
/* Fixed rather than a percentage: in a main column narrowed by two sidebars, a
   proportional thumbnail shrinks to a stamp exactly where the text needs the
   picture most. */
.blog-card--list .pf-list-thumb { flex: 0 0 var(--blog-list-image-width); width: var(--blog-list-image-width); }
/* One step more specific than `.blog-card img`, so the grid's fixed image height
   does not apply here: the image fills its column and crops to whatever height the
   text gives the row, with a floor for a card whose excerpt is a single line. */
.blog-card--list .pf-list-thumb img { height: 100%; min-height: var(--blog-list-image-height); }
/* min-width: 0 because a flex item will not shrink below its content's intrinsic
   width without it, and one long unbroken word in a title would push the thumbnail
   out of the card. */
.blog-card--list .pf-list-body { flex: 1 1 auto; min-width: 0; padding: 1.5rem; }

/* No room for two columns on a phone, so the list becomes the column card again,
   thumbnail on top at the grid card's own image height. */
@media (max-width: 575.98px) {
  .blog-card--list .pf-list-row { display: block; }
  .blog-card--list .pf-list-thumb { width: 100%; }
  .blog-card--list .pf-list-thumb img { height: var(--blog-image-height); min-height: 0; }
  .blog-card--list .pf-list-body { padding: 1.25rem; }
}
.blog-body { max-width: var(--prose-width); }
.blog-body h2 { font-weight: var(--fw-prose-heading); margin: 2rem 0 1rem; }
.blog-body h3 { font-weight: var(--fw-prose-heading); margin: 1.6rem 0 .9rem; }
.blog-body p { line-height: var(--prose-line-height); color: var(--ink-prose); font-size: var(--prose-size); }
.blog-body blockquote { border-left: 4px solid var(--brand); padding-left: 1rem; color: var(--ink-quote); font-style: italic; }
.blog-body ul, .blog-body ol { line-height: var(--prose-line-height); color: var(--ink-prose); }

/* Inside prose, links can take a colour of their own — set --prose-link-ink.
   Long specification and compliance copy is easier to scan when links are
   colour-coded rather than only underlined.

   Buttons are excluded, in two flavours.

   .btn: these selectors are one step more specific than Bootstrap's .btn, so
   without the exclusion an <a class="btn"> anywhere in the content area lost the
   colour its variant sets and took --prose-link-ink instead — which defaults to
   `inherit`, i.e. body ink on a brand-filled button. The homepage's own sections
   all sit inside .pf-content, so that is where it showed worst.

   .wp-element-button: the same failure, via a block button. WordPress core
   prints its own default for those inline, as

     :root :where(.wp-element-button, .wp-block-button__link)
       { background-color: #32373c; color: #fff }

   and :where() contributes NO specificity, so that selector weighs only (0,1,0).
   Nothing else sets a background, so #32373c survives — but its color: #fff lost
   to the (0,2,1) selectors here, and the label took --prose-link-ink on top of a
   near-black fill. The block cart's Proceed to Checkout is the case that matters:
   it is an <a class="wc-block-components-button wp-element-button
   wc-block-cart__submit-button contained">, so it is a prose link as far as the
   cascade is concerned. Under this theme --prose-link-ink is `inherit`, i.e. body
   ink, which put roughly 1.2:1 dark-on-dark text in the primary checkout CTA.
   Excluding the class here fixes it for this theme and every child at once,
   whatever each one sets --prose-link-ink to. */
.blog-body a:not(.btn):not(.wp-element-button),
.pf-content a:not(.btn):not(.wp-element-button),
.entry-content a:not(.btn):not(.wp-element-button) { color: var(--prose-link-ink); }

/* Centre the reading column only when there is no sidebar beside it. */
.pf-layout-full-box .blog-body,
.pf-layout-full-screen .blog-body { margin-inline: auto; }

/* ==========================================================================
   11. Footer
   ========================================================================== */

.footer {
  background: var(--footer-texture), var(--panel-deep);
  color: var(--footer-ink);
  padding: 3rem 0 2rem;
  border-top: var(--footer-border-top);
}
.footer h6, .footer .brand-name { color: var(--footer-heading-ink); }
.footer a { color: var(--footer-link-ink); text-decoration: none; }
.footer a:hover { color: var(--surface); }
.footer i { color: var(--footer-icon-ink); }
.footer img { max-height: 52px; width: auto; height: auto; }
.footer .widget { margin-bottom: 1.5rem; }
.footer ul { list-style: none; padding: 0; margin: 0; }
.footer ul li { padding: .2rem 0; }

.pf-license-notice {
  background: var(--notice-bg);
  border-top: 1px solid var(--notice-border);
  color: var(--notice-ink);
  padding: .75rem 0;
  font-size: .875rem;
  text-align: center;
}

/* ==========================================================================
   12. Floating CTA
   ========================================================================== */

.float-cta {
  position: fixed; right: 20px; bottom: 20px; z-index: 999;
  display: grid; gap: .5rem;
}
.float-cta a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: var(--radius-float);
  background: var(--brand); color: var(--on-brand); font-size: 1.3rem;
  box-shadow: var(--shadow-float);
  text-decoration: none; transition: transform .15s, background .15s;
}
.float-cta a:hover { transform: scale(1.08); background: var(--brand-dark); }
.float-cta a.whatsapp { background: var(--whatsapp); }
.float-cta a.whatsapp:hover { background: var(--whatsapp-hover); }
.float-cta a.email { background: var(--accent); color: var(--on-accent); }

/* ==========================================================================
   13. Static map thumbnail
   ========================================================================== */

.map-static { position: relative; overflow: hidden; border-radius: var(--radius-card); text-decoration: none; display: block; }
.map-static img {
  display: block; width: 100%; height: auto; max-height: 460px; object-fit: cover;
  transition: transform .35s ease;
}
.map-static:hover img { transform: scale(1.02); }
.map-static__hint {
  position: absolute; left: 50%; bottom: 1rem; transform: translateX(-50%);
  background: var(--map-hint-bg); color: var(--on-brand);
  padding: .5rem 1rem; border-radius: var(--radius-pill);
  font-size: .9rem; font-weight: var(--map-hint-weight);
  box-shadow: var(--shadow-float);
  max-width: calc(100% - 2rem);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ==========================================================================
   14. Layout system
   ========================================================================== */

/* Boxed width. Bootstrap's .container steps its max-width up per breakpoint;
   min() keeps those steps while letting --box-width cap them, so a narrower
   token narrows every breakpoint and a wider one only takes effect at 1400px,
   where the step is the token itself. */
@media (min-width: 576px)  { .container { max-width: min(540px, var(--box-width)); } }
@media (min-width: 768px)  { .container { max-width: min(720px, var(--box-width)); } }
@media (min-width: 992px)  { .container { max-width: min(960px, var(--box-width)); } }
@media (min-width: 1200px) { .container { max-width: min(1140px, var(--box-width)); } }
@media (min-width: 1400px) { .container { max-width: var(--box-width); } }

.pf-content { padding: var(--page-padding); margin: var(--page-margin); }
.pf-layout-full-screen > .pf-container-fluid { width: 100%; padding-inline: 0; }

/* Legacy "Woo Fullscreen (edge to edge)" product slug (pre-1.17.0). Since 1.17.0
   the product list and detail share the same eight layouts and this view is plain
   "full-screen" (.pf-layout-full-screen, the flush rule two blocks above);
   playforge_normalize_layout() maps the old slug on read. This rule stays as a
   fallback for a playforge_layout filter that returns the legacy slug directly —
   the filter runs after normalization. The flush-gallery split itself lives in
   assets/css/woocommerce.css under both class names. */
.pf-layout-woo-full-screen > .pf-container-fluid { width: 100%; padding-inline: 0; }

/* Sidebar width. The markup carries col-lg-4/col-lg-8 (or three col-lg-4) — the
   twelfth-grid splits Bootstrap can express, the closest it gets — and this
   overrides them from the two width tokens so the columns in a row can never
   disagree about how much is left. The main column's rule depends on which sides
   are present, which is what the .pf-row--sidebar-* modifier on the row names.
   Scoped to .row so the class-less <aside> in sidebar.php / sidebar-right.php,
   used outside the grid, is untouched. Below 992px Bootstrap's own stacking
   applies and section 19 spaces it. */
@media (min-width: 992px) {
  .row > .pf-sidebar {
    flex: 0 0 auto;
    width: var(--sidebar-width);
  }

  .row > .pf-sidebar--right {
    width: var(--sidebar-width-right);
  }

  .row > .pf-main-col {
    flex: 0 0 auto;
    width: calc(100% - var(--sidebar-width));
  }

  /* Equal specificity to the rule above, so these must stay after it to win. */
  .pf-row--sidebar-right > .pf-main-col {
    width: calc(100% - var(--sidebar-width-right));
  }

  .pf-row--sidebar-both > .pf-main-col {
    width: calc(100% - var(--sidebar-width) - var(--sidebar-width-right));
  }
}

/* The edge-to-edge layouts that carry a sidebar. Unlike .pf-layout-full-screen
   they keep side padding: the row inside pulls its columns 1.5rem outwards with
   the g-5 gutter, and without room for that the first and last columns would sit
   past the viewport edge. max() enforces that floor whatever a child theme sets
   the token to, so the layout cannot be given a horizontal scrollbar by retuning
   it. The boxed sidebar layouts need none of this — .container already has
   gutters. */
.pf-layout-full-screen-with-left-sidebar > .pf-container-fluid,
.pf-layout-full-screen-with-right-sidebar > .pf-container-fluid,
.pf-layout-full-screen-with-left-and-right-sidebar > .pf-container-fluid,
/* The fourth selector is the pre-1.17.0 legacy slug, kept for the same filter
   fallback reason as .pf-layout-woo-full-screen above. */
.pf-layout-woo-full-screen-with-left-and-right-sidebar > .pf-container-fluid {
  width: 100%;
  padding-inline: max(1.5rem, var(--fullscreen-sidebar-gutter));
}

/* The three Elementor layouts share one idea — none of the theme's own spacing,
   so the design starts flush against whatever is above it — and differ in width
   and in how much of the site survives. All are compounded with .pf-content on
   purpose: the narrow-screen --page-padding retune further down this file would
   otherwise win, being the later rule at equal specificity. */
.pf-content.pf-layout-elementor-full-canvas,
.pf-content.pf-layout-elementor-canvas { padding: 0; margin: 0; }
/* Boxed clears the vertical spacing only, so the content still sits inside the
   container's gutters — and any side values in --page-padding survive. Its
   width comes from .container above, i.e. from --box-width. */
.pf-content.pf-layout-elementor-boxed { padding-block: 0; margin-block: 0; }

.pf-layout-elementor-full-canvas > .pf-container-fluid,
.pf-layout-elementor-canvas > .pf-container-fluid { width: 100%; padding-inline: 0; }

.pf-layout-elementor-full-canvas .entry,
.pf-layout-elementor-full-canvas .entry-content,
.pf-layout-elementor-canvas .entry,
.pf-layout-elementor-canvas .entry-content { margin: 0; padding: 0; }
.pf-layout-elementor-boxed .entry,
.pf-layout-elementor-boxed .entry-content { margin-block: 0; padding-block: 0; }
/* A leading or trailing block margin would reintroduce the gap the layouts are
   meant to remove. */
.pf-layout-elementor-full-canvas .entry-content > :first-child,
.pf-layout-elementor-canvas .entry-content > :first-child,
.pf-layout-elementor-boxed .entry-content > :first-child { margin-top: 0; }
.pf-layout-elementor-full-canvas .entry-content > :last-child,
.pf-layout-elementor-canvas .entry-content > :last-child,
.pf-layout-elementor-boxed .entry-content > :last-child { margin-bottom: 0; }
.pf-sidebar .widget {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 1.25rem 1.4rem;
  margin-bottom: 1.5rem;
  background: var(--card-bg);
  box-shadow: var(--shadow-card);
}
.pf-sidebar .widget-title {
  font-weight: var(--fw-widget-title);
  font-size: var(--widget-title-size);
  color: var(--widget-title-ink);
  margin-bottom: .9rem;
  padding-bottom: .6rem;
  border-bottom: var(--widget-title-border);
}
.pf-sidebar ul { list-style: none; padding: 0; margin: 0; }
.pf-sidebar ul li { padding: .35rem 0; border-bottom: 1px solid var(--widget-divider); }
.pf-sidebar ul li:last-child { border-bottom: 0; }
.pf-sidebar a { text-decoration: none; }
.pf-sidebar a:hover { color: var(--brand); }

/* Hierarchy in widget lists. wp_list_categories, wp_list_pages and the Categories
   block all nest with ul.children; nav menus use ul.sub-menu; WooCommerce's product
   categories block nests a second list of its own class and ships no indent rule of
   its own, leaning on the browser default. The blanket `padding: 0` above strips
   that default, so without the rules below a subcategory sits flush with its parent
   and the whole tree reads as one flat column. The selectors are descendant rather
   than child, so the indent compounds: a third level lands two steps in. */
.pf-sidebar ul .children,
.pf-sidebar ul .sub-menu,
.pf-sidebar .wc-block-product-categories-list .wc-block-product-categories-list {
  margin-top: .35rem;
  padding-left: var(--widget-nest-indent);
  border-left: var(--widget-nest-guide);
}

/* The row rhythm belongs to the top level. A divider under each child would carry
   the same weight as the dividers between parents, which is the other half of what
   flattens the tree — the guide line separates children instead. */
.pf-sidebar ul .children li,
.pf-sidebar ul .sub-menu li,
.pf-sidebar .wc-block-product-categories-list .wc-block-product-categories-list li {
  padding-block: .2rem;
  border-bottom: 0;
}
.pf-sidebar ul .children > li > a,
.pf-sidebar ul .sub-menu > li > a,
.pf-sidebar .wc-block-product-categories-list .wc-block-product-categories-list > li > a {
  font-size: var(--widget-nest-size);
  color: var(--widget-nest-ink);
}
/* The quietened colour above out-specifies the shared `.pf-sidebar a:hover`, so the
   hover has to be restated at this depth or child rows stop responding to the
   pointer while their parents still do. */
.pf-sidebar ul .children > li > a:hover,
.pf-sidebar ul .sub-menu > li > a:hover,
.pf-sidebar .wc-block-product-categories-list .wc-block-product-categories-list > li > a:hover {
  color: var(--brand);
}

/* A term holding children reads a step heavier than the children under it, so the
   eye can find the top of each group. Categories get no has-children class from
   WordPress the way pages and menu items do, so :has() is the only way to reach
   them; where it is unsupported the indent and guide line still carry the nesting. */
.pf-sidebar ul li:has(> .children) > a,
.pf-sidebar ul li:has(> .sub-menu) > a,
.pf-sidebar li:has(> .wc-block-product-categories-list) > a {
  font-weight: var(--widget-parent-weight);
}

/* ==========================================================================
   15. Pagination
   ========================================================================== */

.pf-pagination { margin-top: 3rem; }
.pf-pagination .page-numbers {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 42px; height: 42px; padding: 0 .75rem;
  border: 1px solid var(--line); border-radius: var(--radius-btn);
  margin: 0 .2rem; font-weight: var(--fw-pagination); text-decoration: none;
  color: var(--brand-dark); background: var(--surface);
}
.pf-pagination .page-numbers:hover { background: var(--pagination-hover-bg); border-color: var(--pagination-hover-border); color: var(--pagination-hover-ink); }
.pf-pagination .page-numbers.current { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.pf-pagination .page-numbers.dots { border-color: transparent; background: transparent; }

/* Client-side Prev/Next pager, carried over from the Hugo theme. */
.js-pager button:disabled { opacity: .45; }

/* ==========================================================================
   16. Comments
   ========================================================================== */

.comment-list { list-style: none; padding: 0; margin: 0; }
.comment-list .children { list-style: none; padding-left: 1.5rem; }
.comment-body {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 1.25rem;
  margin-bottom: 1.25rem;
  background: var(--card-bg);
  box-shadow: var(--shadow-card);
}
.comment-author img { border-radius: 50%; margin-right: .6rem; }
.comment-author .fn { font-weight: var(--fw-prose-heading); font-style: normal; }
.comment-metadata { font-size: .82rem; color: var(--muted); }
.comment-metadata a { text-decoration: none; }
.bypostauthor > .comment-body { border-left: 3px solid var(--brand); }

/* ==========================================================================
   17. WordPress core content classes
   ========================================================================== */

.screen-reader-text {
  border: 0;
  clip-path: inset(50%);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
  word-wrap: normal !important;
}
.screen-reader-text:focus {
  background-color: var(--surface);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-skiplink);
  clip-path: none;
  color: var(--brand-dark);
  display: block;
  font-size: .875rem;
  font-weight: var(--fw-bold);
  height: auto;
  left: 5px;
  line-height: normal;
  padding: 15px 23px 14px;
  text-decoration: none;
  top: 5px;
  width: auto;
  z-index: 100000;
}

.alignnone { margin: .5rem 1rem 1rem 0; }
.aligncenter, div.aligncenter { display: block; margin: .5rem auto 1rem; }
.alignright { float: right; margin: .5rem 0 1rem 1rem; }
.alignleft { float: left; margin: .5rem 1rem 1rem 0; }
.alignwide { max-width: var(--alignwide-width); margin-inline: auto; }
.alignfull { max-width: 100%; margin-inline: 0; }

.wp-caption { max-width: 100%; }
.wp-caption img { height: auto; max-width: 100%; }
.wp-caption-text, .wp-block-image figcaption {
  font-size: .85rem; color: var(--muted); text-align: center; padding: .6rem 0;
}

.sticky .blog-card { border-color: var(--brand); }

.gallery { display: flex; flex-wrap: wrap; gap: .5rem; }
.gallery-item { flex: 1 1 30%; }
.gallery-caption { font-size: .85rem; color: var(--muted); }

embed, iframe, object, img { max-width: 100%; }
.wp-block-embed iframe { width: 100%; }

/* Match core block editor widths to the theme container. */
.entry-content > * { max-width: 100%; }

/* ==========================================================================
   18. Homepage builder
   ========================================================================== */

/* The six sections carry their own padding through .pf-section, so the wrapper
   contributes none — otherwise the first section's padding is stacked on the
   content area's and the banner sits away from the navbar. Compounded with
   .pf-content for the same reason the Elementor layouts are: the narrow-screen
   --page-padding retune in section 19 would otherwise win at equal specificity. */
.pf-content.pf-layout-homepage { padding: 0; margin: 0; }

/* Two adjacent bands would read as one tall block, so a band following a band
   keeps a visible seam. */
.pf-layout-homepage .band + .band { border-top: 1px solid var(--line); }

/* Banner content is edge to edge and supplies its own spacing — a shortcode's
   slider or hero, or markup pasted into the field. */
.pf-home-banner > :first-child { margin-top: 0; }
.pf-home-banner > :last-child { margin-bottom: 0; }

/* The custom HTML slots are treated the same way: no padding, no container, no
   assumptions — whatever is typed into the field supplies its own layout. Only the
   outer margins are collapsed so a slot cannot open a gap the author did not ask for.
   The .band + .band seam above matches siblings only, so a band written inside a slot
   sits next to the slot's wrapper rather than next to the neighbouring section; the
   three selectors below carry the seam across that wrapper. */
.pf-home-html > :first-child { margin-top: 0; }
.pf-home-html > :last-child { margin-bottom: 0; }

.pf-layout-homepage .band + .pf-home-html > .band:first-child,
.pf-layout-homepage .pf-home-html:has(> .band:last-child) + .band,
.pf-layout-homepage .pf-home-html:has(> .band:last-child) + .pf-home-html > .band:first-child {
  border-top: 1px solid var(--line);
}

/* --- Product category cards -------------------------------------------- */

/* The card holds three destinations — the image and the heading go to the
   category, each subcategory goes to its own archive — so it is a plain article
   with several links rather than one link wrapping everything, the way the
   product cards are built. See template-parts/home/product-categories.php. */

/* The image sits in an anchor of its own, which is inline by default and would
   leave a strip of line-box whitespace between the picture and the card body. */
.pf-cat-image { display: block; }

.pf-cat-name a { color: var(--ink); }
.pf-cat-name a:hover { color: var(--brand-dark); }

/* The arrow carries the brand colour the removed "View products" line used to,
   so the heading still reads as the way into the category. */
.pf-cat-name .bi-arrow-right {
  color: var(--brand);
  transition: transform .2s;
}
.pf-cat-card:hover .bi-arrow-right { transform: translateX(3px); }

/* The subcategory list, one per line. It is printed even when a category has no
   subcategories, because min-height is what keeps the cards in a row the same
   height and their images on a common baseline — three lines' worth, so the
   usual short list does not change the row's height at all.

   The line count and the leading are named rather than folded into one number so
   a child theme can reserve four lines by redefining --pf-cat-sub-lines alone. */
.pf-cat-subs {
  --pf-cat-sub-lines: 3;
  --pf-cat-sub-leading: 1.7;
  list-style: none;
  margin: .75rem 0 0;
  padding: 0;
  font-size: .9rem;
  line-height: var(--pf-cat-sub-leading);
  min-height: calc(var(--pf-cat-sub-lines) * var(--pf-cat-sub-leading) * 1em);
}

.pf-cat-subs a {
  color: var(--muted);
  text-decoration: none;
  transition: color .15s ease;
}

.pf-cat-subs a:hover,
.pf-cat-subs a:focus-visible {
  color: var(--brand-dark);
  text-decoration: underline;
}

/* --- Tabs -------------------------------------------------------------- */

/* Shared by Editor's Choice and the tabbed form of Latest News. Each section also
   carries its own class (.pf-editor-tab, .pf-news-tab) for styling one without the
   other, but everything common lives here and the script binds to these. */

/* A centred row of category names that wraps on a narrow screen rather than
   scrolling, because four to six short names fit two lines and a scrolling strip
   hides the ones a visitor has not thought to look for. */
.pf-tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .5rem;
  margin-bottom: 2.5rem;
}

.pf-tab {
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  padding: .55rem 1.35rem;
  font-weight: var(--fw-btn);
  letter-spacing: var(--tracking-btn);
  line-height: 1.4;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.pf-tab:hover,
.pf-tab:focus-visible {
  border-color: var(--brand-ring);
  background: var(--brand-tint);
  color: var(--brand-dark);
}

/* The open tab, whether the pointer is on it or not — hover alone would leave no
   indication of which panel is showing once the pointer moves away. */
.pf-tab.is-active {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}

/* The panels all occupy the same space, so switching must not move the page. Only
   one is ever in the flow: the others carry the `hidden` attribute, which the
   product grid's `display: grid` would otherwise override. */
.pf-tab-panel[hidden] { display: none; }

/* --- About Us media --------------------------------------------------- */

.pf-home-about-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--home-media-radius);
  box-shadow: var(--home-media-shadow);
}

.pf-home-about-body > :last-child { margin-bottom: 0; }

/* The video facade. Bootstrap's .ratio stretches every child to fill the frame,
   which is what the poster, the button and the swapped-in iframe all want. */
.pf-home-video {
  border-radius: var(--home-media-radius);
  box-shadow: var(--home-media-shadow);
  overflow: hidden;
}

.pf-home-video-poster { width: 100%; height: 100%; object-fit: cover; }

.pf-home-video-play {
  display: grid;
  place-items: center;
  border: 0;
  padding: 0;
  cursor: pointer;
  /* A scrim over the poster, so a light still cannot swallow the button. */
  background: var(--home-video-scrim);
}

.pf-home-video-play i {
  width: var(--home-play-size);
  height: var(--home-play-size);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--home-play-bg);
  color: var(--home-play-ink);
  font-size: calc(var(--home-play-size) * .45);
  box-shadow: var(--home-play-shadow);
  transition: transform .2s, background-color .2s;
}

.pf-home-video-play:hover i,
.pf-home-video-play:focus-visible i {
  background: var(--home-play-hover-bg);
  transform: scale(1.08);
}

/* The iframe replaces the poster and the button once a visitor clicks. */
.pf-home-video iframe { width: 100%; height: 100%; border: 0; }

/* --- Section 6: FAQ ----------------------------------------------------- */

/* A reading column centred in the section: an answer line that runs the full
   width of a wide screen is harder to read than the question above it. */
.pf-home-faq-list {
  max-width: 54rem;
  margin: 0 auto;
}

/* Divider rows rather than gap-separated cards, so the list reads as one
   continuous Q&A index. */
.pf-home-faq-item {
  padding: 1.15rem 0;
}
.pf-home-faq-item + .pf-home-faq-item { border-top: 1px solid var(--line-soft); }

.pf-home-faq-question {
  margin: 0;
  font-size: 1.1rem;
  font-weight: var(--fw-bold);
  line-height: 1.45;
  /* Clears the fixed/sticky header when a question anchor is opened. */
  scroll-margin-top: 6rem;
}

.pf-home-faq-toggle {
  display: flex;
  align-items: center;
  gap: .75rem;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-weight: inherit;
  line-height: inherit;
  text-align: left;
  cursor: pointer;
}

.pf-home-faq-toggle:hover { color: var(--brand-dark); }

.pf-home-faq-toggle:focus-visible {
  outline: 2px solid var(--brand-ring, currentColor);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* Plus/minus indicator, pushed to the right edge of the heading. */
.pf-home-faq-toggle::after {
  content: "\002B";
  flex: 0 0 auto;
  margin-left: auto;
  color: var(--muted);
  font-weight: 400;
  font-size: 1.3em;
  line-height: 1;
  transition: transform .2s ease;
}
.pf-home-faq-toggle:hover::after { color: var(--brand); }
.pf-home-faq-toggle[aria-expanded="true"]::after {
  content: "\2212";
}

.pf-home-faq-answer {
  margin-top: .65rem;
  color: var(--ink-prose);
}
.pf-home-faq-answer[hidden] { display: none; }
.pf-home-faq-answer > :first-child { margin-top: 0; }
.pf-home-faq-answer > :last-child { margin-bottom: 0; }

/* ==========================================================================
   19. Responsive
   ========================================================================== */

@media (max-width: 991.98px) {
  .hero { min-height: auto; background-position: 62% center; }
  .hero-content { padding: 4rem 0 5.5rem; }
  .metric-row { grid-template-columns: 1fr; }
  .factory-photo { min-height: var(--factory-min-height-md); }
  .pf-sidebar { margin-top: 3rem; }

  /* Stacked, two sidebars would push the content a screenful down, so the main
     column comes first here. Only for the three-column layouts: the two-column
     ones keep their long-standing order, where a left sidebar stacks above. */
  .pf-row--sidebar-both > .pf-main-col { order: -1; }
}

@media (max-width: 575.98px) {
  /* Narrow-screen spacing is applied to the rules, not by retuning the tokens
     they read. A child theme's :root sets --page-padding unconditionally and
     would outrank a token retuned inside this media query, quietly restoring
     the wide-screen value on phones; the rules below cannot be lost that way,
     and each has its own token for a child that wants a different phone value.
     .pf-content.pf-layout-elementor-* stays a compound selector so it still
     outranks the bare .pf-content here. */
  .pf-content { padding: var(--page-padding-sm); }
  .pf-section { padding: var(--section-padding-sm); }
  .quote-band { padding: var(--quote-band-padding-sm); }
  .page-header { padding: var(--page-header-padding-sm); }
  .top-strip .container { justify-content: center !important; text-align: center; }
  .hero h1 { font-size: var(--hero-title-size-sm); }
  .hero .d-flex { align-items: stretch !important; }
  .hero .btn { width: 100%; }
  .float-cta a { width: 46px; height: 46px; font-size: 1.1rem; }
  .spec-table th, table.shop_attributes th { width: var(--spec-label-width-sm); }
  /* Set on the rule rather than by retuning --home-play-size, for the reason at
     the top of this block. */
  .pf-home-video-play i {
    width: var(--home-play-size-sm);
    height: var(--home-play-size-sm);
    font-size: calc(var(--home-play-size-sm) * .45);
  }
}
