/* timcanfixit — theme-added chrome the source pages never had markup for:
   real header lockup, mobile nav drawer, colour-mode toggle, announcement bar,
   back-to-top, blog/archive/single/404/comments, search form, a11y helpers.
   Everything here consumes the same design tokens. */

/* ---------- a11y ---------- */
.screen-reader-text{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip-link.screen-reader-text:focus{position:fixed!important;width:auto;height:auto;clip:auto;margin:0;padding:.75rem 1.25rem;background:var(--solder);color:#fff;z-index:1000;border-radius:0 0 8px 0;font-weight:700}

/* ---------- legal page layout (TOC + sectioned body) ----------
   Originated in Service Policies' own generated pages/service-policies.css
   (kept there too — bin/analyze_css.py regenerates that file from source and
   would silently drop a hand-edit); promoted here, shared, so any legal-style
   page (Privacy Policy, Refund and Returns Policy, future ones) gets the same
   sidebar-TOC-plus-sectioned-body treatment via the generic page.php template
   without needing its own per-page stylesheet. */
.legal-layout{display:grid;grid-template-columns:260px 1fr;gap:var(--space-4);padding-block:var(--space-5);align-items:start}
@media (max-width:860px){.legal-layout{grid-template-columns:1fr}}
.toc{position:sticky;top:90px;background:var(--paper-raised);border:1px solid var(--line);border-radius:var(--radius-m);padding:1.3rem}
.toc h2{font-family:var(--font-mono);font-size:.75rem;text-transform:uppercase;letter-spacing:.08em;color:var(--ink-soft);margin-bottom:.9rem}
.toc ul{display:flex;flex-direction:column;gap:.6rem}
.toc a{text-decoration:none;color:var(--ink);font-size:.88rem;font-weight:600}
.toc a:hover{color:var(--solder-text)}
.legal-body{max-width:70ch}
.legal-body section{margin-bottom:var(--space-4);scroll-margin-top:90px}
.legal-body h2{font-size:1.35rem;margin-bottom:.9rem;padding-bottom:.6rem;border-bottom:2px solid var(--line)}
.legal-body p{color:var(--ink-soft);font-size:.98rem;margin-bottom:.9rem}
.legal-body ul{margin:0 0 .9rem;display:flex;flex-direction:column;gap:.5rem}
.legal-body ol{margin:0 0 .9rem;padding-left:1.2rem;display:flex;flex-direction:column;gap:.5rem}
.legal-body ol li{color:var(--ink-soft);font-size:.96rem}
.legal-body li{display:flex;gap:.6rem;color:var(--ink-soft);font-size:.96rem}
.legal-body li::before{content:"–";color:var(--solder-text);flex:none}
.legal-body ol li::before{content:none}
.legal-body strong{color:var(--ink)}
.legal-body em{color:var(--ink-soft)}
.callout{background:var(--circuit-bg);border-left:4px solid var(--circuit);padding:1rem 1.2rem;border-radius:8px;font-size:.92rem;color:var(--ink);margin-bottom:.9rem}

/* ---------- swappable logo slots (icon-card variant) ----------
   Game console repairs' "Every major console, one bench" cards used a drawn
   icon per platform; a real manufacturer logo needs a neutral tile instead
   of the icon's coloured badge (the icon's own background would clash with
   whatever logo colours get uploaded), and object-fit so any aspect ratio
   sits centred without distortion. Image itself is swapped per-card via
   Appearance → Customize → Page · Game Console Repair (inc/images.php).
   The pattern's own <img> tag hardcodes width="44" height="44" (sized for
   the original drawn-icon placeholder) and inc/images.php only ever swaps
   the `src` attribute, never those dimensions -- so a real uploaded logo
   was being forced into a 44x44 box no matter how much bigger this tile
   was made (confirmed: raising the tile to 76px alone did nothing visible,
   since `max-width/max-height:100%` only CAPS a size, it doesn't override
   one already set smaller by the HTML attributes). A wide logo therefore
   rendered tiny and letterboxed rather than filling the tile -- easy to
   mistake for "getting cut off" when the readable letters shrink to only a
   few legible pixels tall. Switched to `width/height:100%`, which (unlike
   max-width/max-height) DOES override the HTML attributes, so the image
   actually fills the tile; `object-fit:contain` still guarantees the whole
   logo stays visible/undistorted regardless of its real aspect ratio. Tile
   also enlarged again, 76px -> 108px, now that the image inside it can
   actually use the extra room. */
.icon-card .logo{width:108px;height:108px;border-radius:16px;background:var(--paper-tint);display:flex;align-items:center;justify-content:center;padding:.75rem;flex:none}
.icon-card .logo img{width:100%;height:100%;object-fit:contain}

/* ---------- mobile hardening ---------- */
/* Defensive: no generated page/component rule should ever be able to push the
   viewport wider than the device, but a fixed-width child slipping through
   (an unconstrained image, a wide table, a long unbroken URL) would do it
   silently. Cheap, harmless safety net. */
html,body{overflow-x:hidden}

/* ---------- plugin-form dark-mode compatibility ----------
   Non-themed pages — plugin pages like Request a Quote, Book a Repair —
   deliberately keep their own Foundation/Bootstrap CSS so those plugins'
   forms keep working (tcfi_is_themed_view() only dequeues on the 16
   pages/blog/archives). That framework CSS hardcodes near-black text
   (labels, paragraphs, preformatted notes) assuming a light page
   background, which goes almost invisible against our dark mode. Force it
   back to our ink tokens wherever it shows up inside page content — higher
   specificity than a bare tag selector, so it wins regardless of which
   stylesheet happens to print first. */
:root[data-theme="dark"] .tcfi-page-body :is(label,p,li,span,legend,pre,small),
:root[data-theme="dark"] .tcfi-page-body{color:var(--ink-soft)}
@media (prefers-color-scheme:dark){
	:root:not([data-theme="light"]) .tcfi-page-body :is(label,p,li,span,legend,pre,small),
	:root:not([data-theme="light"]) .tcfi-page-body{color:var(--ink-soft)}
}

/* ---------- breadcrumb class-name collision (any page, any colour mode) ----------
   tcfi_breadcrumb()'s `.breadcrumb` happens to share its class name with Bootstrap's
   own breadcrumb component — deliberately not dequeued on non-themed/plugin pages
   (Request a Quote, Book a Repair, same reasoning as the dark-mode fix below). Every
   one of the 16 pages' own generated CSS restyles `.breadcrumb` from scratch, so this
   never shows up there; a plugin page has no such override, so Bootstrap's
   `background-color:#e9ecef` + padding + border-radius apply unchallenged — a
   light-grey bar behind text coloured for sitting directly on the dark hero, all but
   unreadable regardless of colour mode. Restated here with the same properties the 16
   pages already use, at higher specificity than the bare class it's fighting, so it
   applies correctly everywhere instead of only where a page-specific stylesheet
   happens to load. Alignment (centred vs left) is deliberately left to the existing
   .tcfi-hero-align-{left,center} rules further down instead of set here, so a page
   with hero_align=left still gets a left-aligned breadcrumb. */
.page-hero .breadcrumb,
.hero .breadcrumb{font-family:var(--font-mono);font-size:.75rem;color:var(--breadcrumb-ink);display:flex;gap:.5em;margin:0 0 var(--space-2);padding:0;background:none;border-radius:0}

/* ---------- top contact bar (address · phone · email, above the header) ----------
   Structural idea from the VWThemes "Repair Shop" theme's top-header row,
   rebuilt with our own tokens/markup — reuses the existing Brand & contact
   settings rather than adding new content fields. Sits outside the sticky
   header so it scrolls away, leaving only the header row pinned. */
.tcfi-topbar{background:var(--navy);color:#fff;font-size:.8rem}
.tcfi-topbar__row{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:1.25rem;padding-block:.45rem}
.tcfi-topbar__item{display:inline-flex;align-items:center;gap:.4em;color:#fff;text-decoration:none;opacity:.9}
.tcfi-topbar__item:hover{opacity:1;text-decoration:underline}
.tcfi-topbar__item svg{width:14px;height:14px;flex:none}
@media (max-width:760px){.tcfi-topbar{display:none}}

/* ---------- rotating hero slider (homepage) ----------
   Structural idea from Repair Shop's Bootstrap-carousel hero, rebuilt as
   vanilla CSS/JS (no framework) on the same tokens/classes as the rest of
   the site — .eyebrow, .hero-lede and .hero-ctas/.btn are shared with the
   single-hero pattern (assets/css/pages/home.css), so only what's actually
   new to this component is styled here. */
/* z-index:1 (not just position:relative) is deliberate: it makes .hero-slider
   establish its OWN stacking context, so its z-index:5 dots/arrows are
   contained within it and compared against later siblings as ONE unit (this
   element's z-index:1) rather than leaking out to compete individually —
   home.css's .readout-bar (the stats card that intentionally overlaps the
   hero's bottom edge via a negative margin-top) has z-index:3, and without
   containment here the slider's dots (5 > 3) rendered on top of it instead
   of correctly sitting behind it. */
.hero-slider{position:relative;z-index:1;overflow:hidden;background:var(--hero-bg);color:var(--hero-ink)}
.hero-slider__viewport{position:relative}
.hero-slider__slide{position:absolute;inset:0;opacity:0;visibility:hidden;transition:opacity .6s var(--ease);background-color:var(--hero-bg);background-size:cover;background-position:center;padding-block:var(--space-6) calc(var(--space-6) + 2rem)}
.hero-slider__slide.is-active{position:relative;opacity:1;visibility:visible}
.hero-slider__inner{position:relative;z-index:2;max-width:640px}
.hero-slider__title{font-size:clamp(2rem,4vw,3rem);font-weight:800;line-height:1.1;margin:.5rem 0 1rem;color:#fff}
.hero-slider .hero-lede{max-width:56ch}
.hero-slider__arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:5;width:44px;height:44px;border-radius:50%;border:1px solid rgba(255,255,255,.35);background:rgba(8,13,34,.4);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer}
.hero-slider__arrow:hover{background:rgba(8,13,34,.7)}
.hero-slider__arrow--prev{left:1rem}
.hero-slider__arrow--prev svg{transform:rotate(180deg)}
.hero-slider__arrow--next{right:1rem}
.hero-slider__dots{position:absolute;left:0;right:0;bottom:1.1rem;z-index:5;display:flex;justify-content:center;gap:.5rem;padding:0;margin:0}
.hero-slider__dots button{width:10px;height:10px;border-radius:50%;border:1px solid rgba(255,255,255,.6);background:transparent;padding:0;cursor:pointer}
.hero-slider__dots button.is-active{background:var(--solder);border-color:var(--solder)}
@media (max-width:640px){.hero-slider__arrow{display:none}}
@media (prefers-reduced-motion:reduce){.hero-slider__slide{transition:none}}

/* ---------- shared button base ----------
   `.btn`'s structural properties (inline-flex, gap, nowrap, shape) live
   duplicated in every one of the 16 per-page generated stylesheets — the
   Customizer-driven cosmetic parts (gradient, color) come separately from
   the always-loaded inc/css/dynamic-css.php inline cascade, but the
   structural part never had a single shared, always-loaded home. Any view
   without one of those 16 page files — the WooCommerce Store views added
   in v1.9.0 are the first example — loses it entirely: the header's own
   "Book a Repair" button (`.btn.btn-primary.btn-header-book`, present on
   EVERY page) fell back to `display:block;white-space:normal`, so once the
   row got tight (the same width band v1.9.4 fixed for the phone number)
   its label wrapped into a squeezed multi-line pill instead of just
   holding its one-line width. Restated here so every page has it
   regardless of whether a per-page stylesheet also repeats it (harmless
   duplication there, same values). */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.55em;font-weight:700;font-size:.98rem;padding:.9em 1.5em;border-radius:999px;border:1px solid transparent;text-decoration:none;cursor:pointer;transition:transform .18s var(--ease);white-space:nowrap}

/* ---------- header lockup ---------- */
/* .nav-toggle (theme.css, generated) never set its own `color` — a <button>
   falls back to the browser's UA default (plain black) rather than
   inheriting the page's ink token, so the hamburger icon's `stroke=
   "currentColor"` lines rendered black-on-navy, all but invisible.
   `position:relative;z-index` on top of the drawer's own z-index:120 (and
   above the 150 the desktop dropdown submenus already use) so the button
   stays truly clickable while the drawer is open — `.tcfi-nav-drawer::before`
   is a `position:fixed;inset:0` backdrop covering the ENTIRE viewport
   (including the header, well above where the drawer's own box starts) to
   dim the rest of the page; without its own higher stacking context the
   button sat visually inside the header but was hit-tested as covered by
   that backdrop once open, so tapping it again did nothing — the only way
   out was navigating to a new page. Confirmed via
   `document.elementFromPoint()` at the button's own coordinates returning
   the drawer, not the button, before this fix. */
.nav-toggle{color:var(--ink);position:relative;z-index:200}
/* .header-phone (theme.css, generated) has no flex-shrink/white-space
   protection, so in the width band just above the mobile-nav breakpoint —
   where the full desktop nav plus the phone number plus the header CTA
   button all still have to share the header row — it was the one thing
   that shrank, breaking "(412) 267-7263" onto three separate lines instead
   of the row simply running a little tighter elsewhere. Nav items (plain
   text, several words) and the CTA button (already non-shrinking) tolerate
   a tight row far better than a phone number does; give the phone block
   the same flex:none treatment header-phone-compact already gets so it
   always keeps its one-line width and the squeeze lands elsewhere instead. */
.header-phone{flex:none;white-space:nowrap}
.brand-text{display:flex;flex-direction:column;line-height:1.05}
.brand-mark{display:flex;align-items:center;justify-content:center;color:var(--solder)}
.brand-mark img{width:100%;height:100%;object-fit:contain;display:block}
/* A wordmark-style uploaded logo (tcfi_brand()'s aspect-ratio heuristic,
   width > 1.8x height) has its own name text drawn INTO the image — colours
   picked for whatever background the logo file itself was designed against,
   not necessarily this site's own header colour. No CSS-only treatment
   (a background plate, a drop-shadow glow) has looked right against this
   header — real fix is a re-exported logo file with light-coloured text,
   or an already-transparent alternate version if one exists in the media
   library. No filter/background applied here for now. */
.header-row{position:relative}
nav.primary-nav ul{margin:0;padding:0;list-style:none}
nav.primary-nav a[aria-current="page"]{color:var(--ink);border-color:var(--solder)}

/* ---------- narrow-phone header right-edge buffer ----------
   The hamburger button sits right at .container's own mobile padding
   boundary (16px) with no extra margin of its own — on a browser/device
   that renders a real, space-reserving scrollbar track (rather than an
   overlay one that floats on top of content, which is what this project's
   own testing tools use, so this doesn't reproduce here), that scrollbar
   can eat directly into that same 16px, clipping the button's right edge.
   A little extra breathing room on just the header row (not the whole
   site's .container, which would shift all page content) costs nothing
   visually and removes the risk regardless of which scrollbar style a
   given browser uses. */
@media (max-width:640px){.header-row{padding-right:calc(var(--space-2) + 10px)}}

/* ---------- header CTA button — hide below 640px, globally ----------
   `.btn-header-book`'s mobile-hide rule lived only in the 16 marketing
   pages' own generated stylesheets (same gap as the `.btn` base rule fixed
   in v1.9.5) — Store views (Shop, product, cart, checkout, account) never
   load any of those files, so on Cart specifically the full-size "Book a
   Repair" button never hid at phone widths, crowding the header enough to
   push the hamburger toggle off past the visible edge entirely. Restated
   here so every page has it. */
@media (max-width:640px){.btn-header-book{display:none}}

/* ---------- compact "tap to call" (mobile header) ----------
   Below 640px .header-phone (theme.css, hides at header_mobile_bp) AND
   .btn-header-book (immediately above) are both gone, leaving no one-tap
   contact action. This icon-only link fills that gap; sized/styled to
   match .tcfi-mode-toggle / .nav-toggle. */
.header-phone-compact{display:none;align-items:center;justify-content:center;width:42px;height:42px;border:1px solid var(--line);border-radius:10px;color:var(--ink);flex:none}
.header-phone-compact svg{width:19px;height:19px}
.header-phone-compact:hover{color:var(--solder-text);border-color:var(--solder)}
@media (max-width:640px){.header-phone-compact{display:inline-flex}}

/* ---------- desktop nav items wrapping word-by-word ----------
   "Services We Offer" / "Book A Repair" (the two multi-word top-level nav
   labels) were breaking onto three lines, one WORD per line, whenever the
   header row ran short on space -- same root cause as .header-phone's
   mid-number wrap (v1.9.4): a flex item with wrappable text can shrink all
   the way down to the width of its single longest word, not just to a
   readable two-line wrap, so the moment there wasn't quite enough room the
   item collapsed to its narrowest possible column. `white-space:nowrap`
   makes the item's minimum width the full label instead. */
nav.primary-nav > ul > li > a{white-space:nowrap}

/* ---------- header needs more room than the page's reading-width container ----------
   Measured: with the nav items above held to one line, the full header row
   (logo+sub-label, all top-level nav items including the two multi-word ones
   with a dropdown caret, phone, header CTA button, cart icon, dark-mode
   toggle) needs about 1370px. But `.header-row` reuses the shared `.container`
   class, capped at `--container` (1200px -- sized for readable body copy,
   correct for every other section on the page) -- so raising
   `header_mobile_bp` alone could never fix this: above roughly 1200px of
   BROWSER width the row's own available space stops growing entirely, no
   matter how wide the window gets, because the container itself stops
   growing. Confirmed by testing at 1300/1400/1700px browser widths -- all
   wrapped identically, since the header was rendering at the same capped
   1200px in every case. Gave the header its own wider ceiling instead of
   touching `--container` (which every page section still uses at its
   designed 1200px). `header_mobile_bp`'s default/max raised alongside this
   (inc/options.php) so the hamburger stays in place until a browser width
   that can actually deliver this much room. */
.site-header .container{max-width:1560px}

/* ---------- narrow-phone header overflow guard ----------
   The logo's rendered size is a plain px value from the Customizer's "Logo
   width" slider (up to 320px as of v1.8.1, sized for a real uploaded image
   rather than the tiny default icon) — correct for a full-width desktop
   header, but a wide logo plus the brand sub-label can outgrow a narrow
   phone's header row entirely, since neither the header row nor .brand
   wraps or shrinks; the overflow pushes the hamburger button (and every
   other header-cta icon after it) off the right edge of the screen,
   inaccessible. Drop the sub-label at phone widths regardless of the
   configured value, so the row always fits and the nav toggle stays
   reachable. `!important` on width/height because the logo's own size
   comes from an inline style attribute, which normally beats an external
   stylesheet. */
/* Hidden by default (two classes, not one, to out-specify the pre-existing
   `.brand-mark img` rule above — class+element, 0,1,1 — which a bare
   `.brand-mark__mobile{display:none}` at 0,1,0 loses to and would show
   unconditionally). Placed BEFORE the media query below so the equally-
   specific `.brand-mark--has-mobile .brand-mark__mobile{display:block}`
   inside it — same 0,2,0 — wins there on source order, while this rule is
   the only one that applies (so wins) outside it. */
.brand-mark .brand-mark__mobile{display:none}
@media (max-width:480px){
	.brand-mark{width:auto!important;max-width:44px!important;height:auto!important;max-height:44px!important}
	.brand-sub{display:none}
	/* A separate square/icon logo (Customizer: Header → "Mobile logo") swaps
	   in below instead of just shrinking the wide desktop wordmark down to
	   an illegible sliver — .brand-mark--has-mobile only exists in the
	   markup when that field is actually set (tcfi_brand()), so a site
	   without one keeps the plain shrink-to-44px fallback above. */
	.brand-mark--has-mobile{max-width:none!important;max-height:none!important}
	.brand-mark--has-mobile .brand-mark__desktop{display:none}
	/* `max-width` is a SEPARATE property from `width` — theme.css's blanket
	   `img,svg{max-width:100%}` still applied on top of the width:38px below
	   even though this selector already out-specifies chrome.css's own
	   `.brand-mark img{width:100%}`, because that base rule doesn't touch
	   max-width at all. `.brand-mark`'s own `width:auto` (just above) leaves
	   this img's percentage basis for max-width ambiguous inside a flex
	   container, and it was resolving to 0 — collapsing the logo to a
	   squished sliver instead of a 38px square. max-width:none removes the
	   cap entirely so the explicit width/height below are what actually render. */
	.brand-mark--has-mobile .brand-mark__mobile{display:block;width:38px;height:38px;max-width:none;object-fit:contain;border-radius:8px}
}

/* ---------- primary nav dropdowns (matches the live site's real menu depth) ----------
   Selectors are written to out-specify theme.css's `nav.primary-nav ul{display:flex}`
   (0,0,1,2) — everything below scoped to `nav.primary-nav ul.tcfi-submenu` (0,0,2,2)
   or more, so a submenu can be display:none/block regardless of source order. */
nav.primary-nav li{position:relative}
nav.primary-nav li.has-children > a{padding-right:.35rem}
.tcfi-submenu-toggle{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;margin-inline-start:.1rem;margin-block:-7px;padding:0;background:none;border:0;color:inherit;cursor:pointer;vertical-align:middle;flex:none}
.tcfi-submenu-toggle svg{transition:transform .18s var(--ease)}
nav.primary-nav li.has-children[data-open="true"] > .tcfi-submenu-toggle svg{transform:rotate(180deg)}
nav.primary-nav:not(.primary-nav--drawer) li.has-children:hover > .tcfi-submenu-toggle svg,
nav.primary-nav:not(.primary-nav--drawer) li.has-children:focus-within > .tcfi-submenu-toggle svg{transform:rotate(180deg)}

nav.primary-nav ul.tcfi-submenu{display:none;flex-direction:column;gap:0;margin:0;padding:0;list-style:none}
nav.primary-nav li.has-children[data-open="true"] > ul.tcfi-submenu{display:flex}

/* desktop: flyout panel, nested levels cascade to the right */
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu{position:absolute;top:100%;left:0;min-width:230px;background:var(--paper-raised);border:1px solid var(--line);border-radius:var(--radius-m);box-shadow:var(--shadow-m);padding:.4rem;z-index:150}
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu ul.tcfi-submenu{top:-.4rem;left:100%;margin-inline-start:.35rem}
nav.primary-nav:not(.primary-nav--drawer) li.has-children:hover > ul.tcfi-submenu,
nav.primary-nav:not(.primary-nav--drawer) li.has-children:focus-within > ul.tcfi-submenu{display:flex}
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu li{white-space:nowrap}
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu > li > a{display:block;padding:.55rem .65rem;border-radius:8px;font-size:.9rem;font-weight:600;border-bottom:0}
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu > li > a:hover{background:var(--paper-tint);color:var(--ink)}

/* drawer: inline accordion, indented */
.primary-nav--drawer ul.tcfi-submenu{padding-inline-start:1rem;border-inline-start:1px solid var(--line);margin:.2rem 0 .4rem .4rem}
.primary-nav--drawer ul.tcfi-submenu > li > a{padding:.55rem .25rem;font-size:.92rem;border-bottom:0}

/* ---------- header cart icon ----------
   Present on every page (header.php), not just Store views, so a customer
   who adds something to their cart from the Shop page always has a way
   back to it regardless of which page they're on afterward — the gap this
   was added to fix. Matches .tcfi-mode-toggle/.nav-toggle's 42x42 bordered
   icon-button treatment. The count badge is updated live after an AJAX
   add-to-cart via WooCommerce's own wc-cart-fragments.js matching
   `.tcfi-cart-count` (inc/woocommerce.php's woocommerce_add_to_cart_fragments
   filter) — no bespoke JS needed. */
.header-cart{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:42px;border:1px solid var(--line);border-radius:10px;color:var(--ink-soft);flex:none;text-decoration:none;transition:color .18s var(--ease),border-color .18s var(--ease)}
.header-cart:hover{color:var(--ink);border-color:var(--solder)}
.tcfi-cart-count{position:absolute;top:-6px;right:-6px;min-width:18px;height:18px;padding:0 4px;border-radius:999px;background:var(--solder);color:#fff;font-family:var(--font-mono);font-size:.65rem;font-weight:700;line-height:18px;text-align:center}
.tcfi-cart-count[hidden]{display:none}

/* ---------- colour-mode toggle ---------- */
.tcfi-mode-toggle{display:inline-flex;align-items:center;justify-content:center;width:42px;height:42px;border:1px solid var(--line);border-radius:10px;background:none;color:var(--ink-soft);cursor:pointer;flex:none;transition:color .18s var(--ease),border-color .18s var(--ease)}
.tcfi-mode-toggle:hover{color:var(--ink);border-color:var(--solder)}
.tcfi-mode-toggle svg{width:18px;height:18px}
.tcfi-mode-toggle__moon{display:none}
:root[data-theme="dark"] .tcfi-mode-toggle__sun{display:none}
:root[data-theme="dark"] .tcfi-mode-toggle__moon{display:block}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .tcfi-mode-toggle__sun{display:none}:root:not([data-theme="light"]) .tcfi-mode-toggle__moon{display:block}}
.tcfi-mode-toggle--switch{width:56px;border-radius:999px;justify-content:flex-start;padding:0 4px;position:relative}
.tcfi-mode-toggle--switch::after{content:"";width:16px;height:16px;border-radius:50%;background:var(--solder);transition:transform .2s var(--ease)}
:root[data-theme="dark"] .tcfi-mode-toggle--switch::after{transform:translateX(22px)}

/* ---------- mobile nav drawer ---------- */
.tcfi-nav-drawer{position:absolute;left:0;right:0;top:100%;max-height:100vh;overflow-y:auto;scrollbar-width:none;-ms-overflow-style:none;background:var(--paper-raised);border-bottom:1px solid var(--line);box-shadow:var(--shadow-m);padding:var(--space-3);display:flex;flex-direction:column;gap:var(--space-2);z-index:120}
/* The drawer's `hidden` HTML attribute is what's supposed to keep it closed
   by default — but the browser's own UA-stylesheet rule for `[hidden]`
   (`display:none`) is an equal-specificity, LOWER-origin rule than the
   `display:flex` directly above, and normal author CSS always wins that
   tie regardless of source order. With no rule saying otherwise, the drawer
   rendered fully open on every page load below the nav-collapse breakpoint,
   closing only once JS explicitly interacted with it — dynamic-css.php's
   generated `@media(min-width:{bp+1}px){.tcfi-nav-drawer{display:none!important}}`
   only ever covered the "wide viewport" half of this; nothing covered the
   default "narrow viewport, not yet opened" state. Two extra classes of
   specificity (0,0,2,0) is enough to win over the base rule (0,0,1,0)
   without needing !important; JS toggling `hidden` off still reveals it via
   the base flex rule as before. */
.tcfi-nav-drawer[hidden]{display:none}
.tcfi-nav-drawer::-webkit-scrollbar{display:none}
.tcfi-nav-drawer .primary-nav ul{display:flex;flex-direction:column;gap:.25rem}
.tcfi-nav-drawer .primary-nav a{display:block;padding:.7rem .25rem;font-size:1rem;border-bottom:1px solid var(--line)}
.tcfi-nav-drawer .btn{width:100%}
body.tcfi-nav-open{overflow:hidden}
/* The drawer's own box is only ever as tall as its content (or the viewport,
   whichever is shorter, per max-height above) — it was never a full-screen
   takeover, so whatever real page content sits below/around it stayed visible
   and interactive the whole time, reading as "the menu is covering the page"
   rather than a clean, deliberate overlay. A dimmed backdrop covering the full
   viewport — behind the drawer's own content, above everything else, closed
   with the drawer via the same `hidden` attribute — fixes that: nothing below
   the header is visible or clickable while the menu is open, and it clears
   the instant the drawer closes (no separate element/JS; ::before inherits
   the drawer's own `hidden` state for free).
   No visible scrollbar, ever, on this element (scrollbar-width:none +
   -ms-overflow-style:none + the -webkit-scrollbar rule above cover every
   engine) — the menu must read as a clean full-screen takeover, not a
   scrolling panel. max-height is 100vh so on any real phone (materially
   taller than the ~300-500px of chrome the header/topbar actually use) the
   full nav list fits with room to spare and overflow-y never engages at
   all; it's kept as a genuine last-resort safety net, not a UI element
   anyone is meant to notice, for a pathological case (an extremely long
   custom nav_items list on an unusually short viewport) where the
   alternative — hard-clipping items with no way to reach them at all —
   would be worse than a plain, bar-free scroll gesture. */
.tcfi-nav-drawer::before{content:"";position:fixed;inset:0;background:rgba(5,8,21,.55);z-index:-1}
/* The drawer is only as tall as its content, not a full-screen takeover, so any
   fixed-position element that floats independently of it can still show through
   or crowd its corner while it's open. Our own back-to-top button is one; the
   Tidio chat widget (present on the real site, `#tidio-chat`, self-assigns an
   effectively-max z-index so no stylesheet z-index war can out-rank it) is the
   other — hide both while the drawer is open instead. Inert if either is absent. */
body.tcfi-nav-open .tcfi-to-top{display:none}
body.tcfi-nav-open #tidio-chat{display:none!important}

/* ---------- announcement bar ---------- */
.tcfi-announce{background:var(--navy);color:#fff;font-size:.86rem}
.tcfi-announce .container{display:flex;align-items:center;justify-content:center;gap:1rem;padding-block:.5rem;position:relative}
.tcfi-announce a{color:#fff;text-decoration:underline}
.tcfi-announce__x{position:absolute;right:var(--space-3);background:none;border:0;color:#fff;cursor:pointer;display:flex;padding:.25rem}

/* ---------- back to top ---------- */
.tcfi-to-top{position:fixed;right:clamp(1rem,3vw,2rem);bottom:clamp(1rem,3vw,2rem);width:44px;height:44px;border-radius:50%;border:1px solid var(--line);background:var(--paper-raised);color:var(--ink);box-shadow:var(--shadow-m);cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:90}
.tcfi-to-top svg{transform:rotate(180deg)}

/* ---------- generic hero alignment ---------- */
.tcfi-hero-align-left{text-align:left}
.tcfi-hero-align-left .breadcrumb,.tcfi-hero-align-left .page-hero-lede,.tcfi-hero-align-left h1{margin-inline:0}
.tcfi-hero-align-center{text-align:center}
.tcfi-hero-align-center .breadcrumb{justify-content:center}
.tcfi-hero-align-center .page-hero-lede,.tcfi-hero-align-center h1{margin-inline:auto}

/* ---------- blog / archive ---------- */
.tcfi-blog.tcfi-has-sidebar{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:var(--space-5)}
@media (max-width:900px){.tcfi-blog.tcfi-has-sidebar{grid-template-columns:1fr}}
.tcfi-post-list{display:grid;gap:var(--space-4)}
.tcfi-blog--cards .tcfi-post-list,.tcfi-blog--grid .tcfi-post-list{grid-template-columns:repeat(2,1fr)}
@media (max-width:760px){.tcfi-blog--cards .tcfi-post-list,.tcfi-blog--grid .tcfi-post-list{grid-template-columns:1fr}}
.tcfi-post-card{background:var(--paper-raised);border:1px solid var(--line);border-radius:var(--radius-m);overflow:hidden;display:flex;flex-direction:column}
.tcfi-blog--list .tcfi-post-card{flex-direction:row}
.tcfi-post-card__media img{width:100%;height:100%;object-fit:cover;aspect-ratio:3/2}
.tcfi-blog--list .tcfi-post-card__media{flex:0 0 34%}
.tcfi-post-card__body{padding:var(--space-3);display:flex;flex-direction:column;gap:.5rem}
.tcfi-post-card__title{font-size:1.15rem;font-weight:700}
.tcfi-post-card__title a{text-decoration:none}
.tcfi-post-card__title a:hover{color:var(--solder-text)}
.tcfi-post-card__meta{font-family:var(--font-mono);font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-soft)}
.tcfi-post-card__excerpt{color:var(--ink-soft);font-size:.95rem}
.tcfi-post-card__more{margin-top:auto;font-weight:700;color:var(--solder-text);text-decoration:none}
.wp-pagenavi,.pagination,.navigation.pagination{margin-top:var(--space-4);display:flex;gap:.4rem;flex-wrap:wrap;justify-content:center}
.navigation.pagination .page-numbers{display:inline-flex;min-width:40px;height:40px;align-items:center;justify-content:center;border:1px solid var(--line);border-radius:10px;text-decoration:none;color:var(--ink)}
.navigation.pagination .page-numbers.current{background:var(--solder);color:#fff;border-color:var(--solder)}

/* ---------- prose (single post / plain content) ---------- */
.tcfi-prose{max-width:760px}
.tcfi-prose h2{font-size:1.6rem;margin:2rem 0 .8rem}
.tcfi-prose h3{font-size:1.25rem;margin:1.6rem 0 .6rem}
.tcfi-prose p{margin:0 0 1.1rem;color:var(--ink)}
.tcfi-prose ul,.tcfi-prose ol{margin:0 0 1.1rem 1.4rem;padding:0;list-style:revert}
.tcfi-prose a{color:var(--solder-text);font-weight:600}
.tcfi-prose blockquote{border-left:4px solid var(--solder);padding-left:1rem;margin:1.4rem 0;color:var(--ink-soft)}
.tcfi-prose img{border-radius:var(--radius-m)}
.tcfi-prose code{font-family:var(--font-mono);background:var(--paper-tint);padding:.15em .4em;border-radius:6px;font-size:.9em}
.tcfi-prose pre{background:var(--hero-bg);color:var(--hero-ink);padding:1rem;border-radius:var(--radius-m);overflow:auto}
.post-navigation{margin-top:var(--space-4);display:flex;justify-content:space-between;gap:1rem;font-weight:600}
.post-navigation a{text-decoration:none;color:var(--solder-text)}

/* ---------- comments ---------- */
.tcfi-comments{max-width:760px;margin-top:var(--space-5)}
.tcfi-comment-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-3)}
.tcfi-comment-list .comment-body{background:var(--paper-raised);border:1px solid var(--line);border-radius:var(--radius-s);padding:var(--space-3)}
.tcfi-comments .comment-form input[type=text],.tcfi-comments .comment-form input[type=email],.tcfi-comments .comment-form input[type=url],.tcfi-comments .comment-form textarea{width:100%;font:inherit;padding:.7em .9em;border:1px solid var(--line);border-radius:10px;background:var(--paper);color:var(--ink)}

/* ---------- search form ---------- */
.search-form{display:flex;gap:.5rem}
.search-form .search-field{flex:1;font:inherit;padding:.7em .9em;border:1px solid var(--line);border-radius:10px;background:var(--paper);color:var(--ink)}
.search-form .search-submit{font:inherit;font-weight:700;padding:.7em 1.3em;border:0;border-radius:10px;background:var(--solder);color:#fff;cursor:pointer}

/* ---------- admin-only inline notices ---------- */
.tcfi-admin-notice{border:1px dashed var(--solder);background:var(--circuit-bg);color:var(--ink);padding:1rem 1.2rem;border-radius:12px;margin:1rem 0;font-size:.95rem}

/* ---------- widgets ---------- */
.widget{background:var(--paper-raised);border:1px solid var(--line);border-radius:var(--radius-m);padding:var(--space-3);margin-bottom:var(--space-3)}
.widget-title{font-family:var(--font-mono);font-size:.8rem;text-transform:uppercase;letter-spacing:.06em;margin-bottom:.8rem}

/* ---------- small text-link tap targets (kept out of the 16 generated per-page files) ----------
   .card-link (home.css etc.) is a short bold link+icon with no padding of its own — fine with a
   mouse, a thin target on touch. Negative margin cancels the padding's effect on layout, so this
   only grows the tap/hover box, not the visual gap around it. */
.card-link{padding-block:.5rem;margin-block:-.5rem}

/* ---------- WordPress core content classes (alignment, captions, sticky, gallery) ---------- */
.alignleft{float:left;margin:.4rem 1.4rem 1rem 0}
.alignright{float:right;margin:.4rem 0 1rem 1.4rem}
.aligncenter{display:block;margin-left:auto;margin-right:auto}
.alignnone{margin:.4rem 0 1rem 0}
.wp-caption{max-width:100%;margin-bottom:1.1rem}
.wp-caption img{display:block}
.wp-caption .wp-caption-text,.wp-caption-text{font-family:var(--font-mono);font-size:.78rem;color:var(--ink-soft);padding:.5rem .2rem;text-align:center}
.gallery-caption{font-family:var(--font-mono);font-size:.78rem;color:var(--ink-soft);display:block}
.sticky{position:relative}
.tcfi-post-card.sticky,.tcfi-prose .sticky{outline:2px solid var(--solder);outline-offset:2px}
.bypostauthor > .comment-body{border-color:var(--solder)}
.screen-reader-text:focus{clip:auto!important;clip-path:none;height:auto;width:auto;display:block;z-index:100000}
.wp-block-image figcaption{font-family:var(--font-mono);font-size:.78rem;color:var(--ink-soft);text-align:center}

/* ---------- Book a Repair (RepairBuddy CRM / "computer-repair-shop" plugin
   booking widget, .repair-buddy-container / .wcrb_container -- same plugin
   family already dealt with in v1.9.0's template-routing fix) ----------
   Same shape as [[feedback_plugin_white_box_contrast_pattern]] everywhere
   else on this site: this plugin renders its ENTIRE multi-step booking flow
   (device search, category cards, service selection, calendar, confirmation
   -- every step) on a hardcoded white surface, and none of its plain
   headings/paragraphs/labels/spans set their own text colour, so they fall
   straight through to this theme's `body{color:var(--ink)}` -- correct for
   THIS theme's own dark-mode design, but this plugin's box is white
   regardless of site colour mode, so it inherited near-white text.
   Confirmed via a full contrast sweep across every step of the flow (not
   just the first one): the two colours involved are the raw
   `--ink`/`--ink-soft` custom-property values themselves (not a plugin rule
   overriding them) -- i.e. this is pure CSS inheritance from <body>, so a
   single colour set on the plugin's own outer wrapper covers the plain
   paragraphs/labels/spans; it doesn't touch any element that already has
   its own (already-readable) plugin colour, like `.category-name` or the
   active step's blue label. `--navy` specifically because, unlike
   `--ink`/`--ink-soft`, it stays a dark navy in BOTH this theme's light AND
   dark mode -- the right choice for text sitting on a surface that's always
   white no matter what the site's own toggle is set to (same reasoning
   already used for the checkout floating labels). Headings needed a SEPARATE,
   `!important` rule: theme.css has its own site-wide `h1,h2,h3,h4{color:
   var(--ink)!important}` (correct for this theme's own pages), which beat
   the plain inherited colour on every h2/h4 this plugin renders ("Find Your
   Device", "Service Selection", each appointment-option title) even though
   nothing else in the plugin's markup was fighting back -- confirmed via the
   computed-style chain: every DIV between the wrapper and a heading picked
   up the new navy correctly, only the heading elements themselves didn't. */
.repair-buddy-container{color:var(--navy)}
.repair-buddy-container h1,.repair-buddy-container h2,.repair-buddy-container h3,
.repair-buddy-container h4,.repair-buddy-container h5{color:var(--navy)!important}
/* This theme's OWN dark-mode prose rule (below, `.tcfi-page-body`'s
   `:is(label,p,li,span,legend,pre,small)` selector) sits between the
   container and most of the plugin's actual text nodes and is more specific
   than a plain inherited value, so it intercepts before the container
   colour above ever reaches them -- same tag list, `!important` to win. */
.repair-buddy-container :is(label,p,li,span,legend,pre,small){color:var(--navy)!important}

/* ---------- Book a Repair intro copy ----------
   The page's OWN content (post_content, typed in the editor as raw HTML with
   inline styles -- not this plugin, not a stylesheet) hardcodes
   `color:#555`/`color:#777` on its two intro paragraphs ("Please fill out
   the form..." and the "Note: we do not charge..." disclaimer), assuming a
   plain white page. This theme's actual page background here is dark, so
   dark grey on dark navy reads as almost no contrast at all -- the mirror
   image of the plugin-white-box pattern: here the SURROUNDING page is dark
   and it's the CONTENT that assumes light. An inline style needs
   `!important` to beat regardless of selector specificity, and since this
   lives in post content (not theme code) rather than matching by a page ID
   that could differ between installs, matched on the exact inline colour
   values instead so this keeps working if the page is ever re-created with
   a different ID. `--ink-soft` (not `--navy`, which is for a surface that's
   always white) because this text sits on the theme's own normal dark
   background, in whichever colour mode the site is actually in. */
.tcfi-page-body p[style*="color: #555"],.tcfi-page-body p[style*="color:#555"],
.tcfi-page-body p[style*="color: #777"],.tcfi-page-body p[style*="color:#777"]{color:var(--ink-soft)!important}


/* ---- one <h1> per page (inc/a11y.php) -------------------------------------------------
   Headings that used to be an <h1> in a page body / the product summary are now <h2>.
   Keep their old look. */
.summary .product_title{font-size:clamp(1.5rem,2.2vw + .8rem,2.1rem);line-height:1.15;margin:0 0 .6rem}
.tcfi-sitemap .sm-hero h2[data-tcfi-was-h1]{font-size:36px;font-weight:700;color:#fff!important;margin:0 0 10px}
.tcfi-sitemap .sm-hero h2[data-tcfi-was-h1] span{color:#e63946}

/* ---- two long-standing layout bugs (v1.10.18) ------------------------------------------
   1. The home slider headline was the dark body ink on a dark photo (theme.css forces
      h1..h4 to --ink with !important and only lists the other hero titles as white).
   2. `.page-hero` got its padding only from per-page stylesheets, so Shop, Product, Cart,
      Checkout, Account, Sitemap and blog views showed a 72px hero with the heading touching the edges.
      This is the fallback; every per-page stylesheet loads after this one and still overrides it. */
.hero-slider__title{color:#fff!important}
.page-hero{position:relative;background:var(--hero-bg);color:var(--hero-ink);padding-block:var(--space-5)}

/* ---- bundled mascot logo (v1.10.18) ---------------------------------------------------
   Transparent WebP with its own thin white outline, so it needs no box or background in either
   colour mode. The image is a square, so tcfi_brand() keeps the business name next to it. */
.brand-mark--mascot{color:inherit}
.brand-mark--mascot img{filter:drop-shadow(0 1px 1px rgba(11,18,44,.18))}

/* narrow phones: keep "Tim Can Fix It" on one line next to the mascot instead of wrapping to four lines
   (logo + phone + cart + mode + menu buttons all share the row) */
@media (max-width:480px){
	.brand{gap:.45rem;min-width:0}
	.brand-word{font-size:1rem;white-space:nowrap}
	.brand-mark--mascot{max-width:40px!important;max-height:40px!important}
	.header-cta{gap:.35rem}
}
@media (max-width:380px){
	/* below ~380px there is no room for four 42px buttons beside the name; the colour mode follows the phone's own setting by default */
	.header-cta .tcfi-mode-toggle{display:none}
	.brand-word{font-size:.95rem}
}

/* footer brand sub-label ("PITTSBURGH, PA") was --ink-soft (dark grey) on the near-black footer: ~1.7:1 */
footer.site-footer .brand-sub{color:var(--footer-ink-soft,#B7C0E0)}
footer.site-footer .brand-word{color:#fff}


/* ---- text-contrast fixes found by the page-by-page scan (v1.10.18) ------------------------
   Root cause of most of them: theme.css forces h1-h4 to the body ink with !important and only
   lists some dark components as white, and a few badges/buttons put white text on the bright
   brand orange (2.6-3.6:1). */
/* white text needs a darker orange than --solder (#E8551F light / #FF7A45 dark) */
.price-badge,.badge-featured{background:var(--badge-bg,#B23E14)!important;color:#fff!important}
/* headings on dark components the white-list in theme.css missed */
.materials-band h4,.mat-box h4,.dark-grid h4,.dark-band h4,.xbox-band h4{color:#fff!important}
/* the orange eyebrow label is dark orange (text-safe on white); on a dark section it needs the light one */
.dark-grid .eyebrow,.dark-band .eyebrow,.materials-band .eyebrow,.xbox-band .eyebrow,.cta-band .eyebrow{color:#FFB088}
.dark-grid .eyebrow::before,.dark-band .eyebrow::before,.materials-band .eyebrow::before,.xbox-band .eyebrow::before,.cta-band .eyebrow::before{background:#FFB088}
/* photo gallery captions: white text on a photo needs a dark fade behind it, in both colour modes */
.gallery-item::after{content:"";position:absolute;left:0;right:0;bottom:0;height:62%;background:linear-gradient(to top,rgba(8,13,34,.88),rgba(8,13,34,0));z-index:0;pointer-events:none}
.gallery-item span{color:#fff!important}
/* WooCommerce stock line: the olive green was 3.2:1 */
.woocommerce .stock,.woocommerce p.stock.in-stock{color:#0B7A61!important}
:root[data-theme="dark"] .woocommerce .stock,:root[data-theme="dark"] .woocommerce p.stock.in-stock{color:#4ADE80!important}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .woocommerce .stock,:root:not([data-theme="light"]) .woocommerce p.stock.in-stock{color:#4ADE80!important}}
/* Sitemap page: its hand-written cards/CTA are fixed light/dark boxes, but the theme's heading colour flips with the colour mode */
.tcfi-sitemap .sm-card h3{color:#1a1a2e!important}
.tcfi-sitemap .sm-cta h3{color:#fff!important}
.tcfi-sitemap .sm-btn{background:#C4232F!important;color:#fff!important}
.hero-slider .eyebrow{color:#FFC9A8}
.hero-slider .eyebrow::before{background:#FFB088}
.gallery-item::after{height:75%;background:linear-gradient(to top,rgba(8,13,34,.94),rgba(8,13,34,.55) 55%,rgba(8,13,34,0))}

/* ---- full menu on ordinary laptops (v1.10.18) ----------------------------------------------
   The desktop menu used to switch to the hamburger below 1500px, which hid it on 1366px and 1440px
   laptops. With the phone block dropped between 1241px and 1500px (the phone and email are already in the
   bar above the header) the whole row fits from about 1240px up. */
@media (min-width:1241px) and (max-width:1499px){
	.header-phone{display:none}
	.header-phone-compact{display:none} /* the number is in the bar above the header at these widths */
	nav.primary-nav>ul{gap:.1rem}
	nav.primary-nav>ul>li>a{padding-inline:.4rem;font-size:.9rem}
}

/* ---- nested dropdown: caret sits beside the label and points to the flyout (v1.10.18) ---------
   In the desktop flyout the caret button for a second-level item dropped onto its own line under the label. */
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu > li.has-children{display:flex;align-items:center;position:relative}
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu > li.has-children > a{flex:1}
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu .tcfi-submenu-toggle{margin-block:0;transform:rotate(-90deg)}
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu li.has-children:hover > .tcfi-submenu-toggle svg,
nav.primary-nav:not(.primary-nav--drawer) ul.tcfi-submenu li.has-children:focus-within > .tcfi-submenu-toggle svg{transform:none}

/* ---- footer: social icons + back-to-top overlap (v1.10.18) ----------------------------------- */
.social-row{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:1rem}
.social-row a{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border:1px solid rgba(255,255,255,.22);border-radius:10px;color:var(--footer-ink-soft,#C4CDEE)}
.social-row a:hover{color:#fff;border-color:#fff}
.social-row svg{width:18px;height:18px}
/* the fixed back-to-top button sat on top of the last footer link when scrolled to the bottom */
.footer-bottom{padding-inline-end:4rem}
@media (max-width:600px){.footer-bottom{padding-inline-end:0;padding-bottom:3.5rem}}

/* ---- mobile menu drawer: full width, caret beside the label (v1.10.18) -------------------------
   The drawer list shrank to about 160px on the left, and each item's caret button fell onto its own line under the label. */
.tcfi-nav-drawer nav.primary-nav,.tcfi-nav-drawer nav.primary-nav > ul{width:100%}
.tcfi-nav-drawer nav.primary-nav li{width:100%}
.tcfi-nav-drawer nav.primary-nav li.has-children{display:flex;flex-wrap:wrap;align-items:center}
.tcfi-nav-drawer nav.primary-nav li.has-children > a{flex:1;min-width:0}
.tcfi-nav-drawer nav.primary-nav li.has-children > .tcfi-submenu-toggle{margin-block:0;border-bottom:1px solid var(--line);height:auto;align-self:stretch;width:44px;border-radius:0}
.tcfi-nav-drawer nav.primary-nav li.has-children > ul.tcfi-submenu{flex-basis:100%;width:100%}

/* ---- shared page components used by the Xbox pages (v1.10.19) -------------------------------
   Same values as the per-page stylesheets (which load after this and still win); here so a page that
   does not have its own copy (Xbox 360 Modding Packages) gets them too. */
.icon-card-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-3)}
.icon-card-grid.cols-3{grid-template-columns:repeat(3,1fr)}
@media (max-width:900px){.icon-card-grid.cols-3{grid-template-columns:1fr}}
@media (max-width:700px){.icon-card-grid{grid-template-columns:1fr}}
.icon-card{background:var(--paper-raised);border:1px solid var(--line);border-top:4px solid var(--solder);border-radius:var(--radius-m);padding:var(--space-4);display:flex;flex-direction:column;gap:.9rem}
.icon-card h3{font-size:1.3rem;font-weight:700}
.icon-card p{color:var(--ink-soft);font-size:.98rem;flex:1}
.step-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-3)}
@media (max-width:900px){.step-grid{grid-template-columns:repeat(2,1fr)}}
.step-card{background:rgba(255,255,255,.06);border-top:3px solid var(--solder-2);border-radius:var(--radius-m);padding:1.4rem}
.step-num{font-family:var(--font-mono);font-size:2rem;font-weight:700;color:var(--solder-2);line-height:1;margin-bottom:.6rem}
.step-card strong{display:block;color:#fff;font-size:1.05rem;margin-bottom:.4rem}
.step-card p{color:#B9C2E6;font-size:.9rem}
.dark-band{background:linear-gradient(165deg,var(--navy),#0B1230);border-radius:var(--radius-l);padding:var(--space-4);color:#fff}
.related{padding-top:var(--space-3);border-top:1px solid var(--line);text-align:center}
.related h3{font-size:1.1rem;font-weight:700;margin-bottom:1.2rem}
.related-grid{display:flex;flex-wrap:wrap;justify-content:center;gap:.6rem}
.related-grid a{background:var(--paper-raised);border:1px solid var(--line);color:var(--solder-text);padding:.55em 1.1em;border-radius:999px;text-decoration:none;font-weight:600;font-size:.88rem}
.related-grid a:hover{background:var(--badge-bg,#B23E14);color:#fff;border-color:var(--badge-bg,#B23E14)}
.cta-band{background:linear-gradient(120deg,var(--navy) 0%,#1B1030 60%,#2A1408 130%);color:#fff;border-radius:var(--radius-l);padding:var(--space-5) var(--space-4);text-align:center;margin-top:var(--space-5)}
.cta-band p{color:var(--hero-lede-ink);margin:1rem auto 1.5rem;max-width:44ch}
.cta-band-actions{display:flex;flex-wrap:wrap;gap:.8rem;justify-content:center}
.faq-list{display:flex;flex-direction:column;gap:.75rem;max-width:820px;margin-inline:auto}
details.faq-item{background:var(--paper-raised);border:1px solid var(--line);border-radius:var(--radius-s);overflow:hidden}
details.faq-item[open]{border-color:var(--solder)}
details.faq-item summary{list-style:none;cursor:pointer;padding:1.1rem 1.3rem;display:flex;align-items:center;justify-content:space-between;gap:1rem;font-weight:700;font-size:1rem}
details.faq-item summary::-webkit-details-marker{display:none}
.faq-icon{flex:none;width:22px;height:22px;border-radius:50%;border:1.5px solid var(--line);display:flex;align-items:center;justify-content:center;position:relative}
.faq-icon::before,.faq-icon::after{content:"";position:absolute;background:var(--ink-soft);transition:transform .2s var(--ease),opacity .2s var(--ease)}
.faq-icon::before{width:10px;height:2px}
.faq-icon::after{width:2px;height:10px}
details.faq-item[open] .faq-icon::after{transform:rotate(90deg);opacity:0}
details.faq-item[open] .faq-icon{border-color:var(--solder)}
.faq-answer{padding:0 1.3rem 1.2rem;color:var(--ink-soft);font-size:.97rem;line-height:1.65}
.faq-answer strong{color:var(--ink)}
.faq-answer a{color:var(--solder-text);text-decoration:underline}
.faq-list + .cta-band{margin-top:var(--space-5)}
/* "what an RGH unlocks" list and the three starting-price cards */
.check-list{list-style:none;margin:0 auto var(--space-4);padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:.9rem var(--space-4);max-width:900px}
@media (max-width:700px){.check-list{grid-template-columns:1fr}}
.check-list li{display:flex;gap:.7rem;align-items:flex-start;font-size:1rem}
.check-list svg{flex:none;width:22px;height:22px;margin-top:.1rem;color:var(--circuit)}
.mini-price-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-3)}
@media (max-width:800px){.mini-price-grid{grid-template-columns:1fr}}
.mini-price{display:flex;flex-direction:column;gap:.35rem;padding:var(--space-3);border:1px solid var(--line);border-radius:var(--radius-m);background:var(--paper-raised);text-decoration:none;color:var(--ink)}
.mini-price:hover{border-color:var(--solder)}
.mini-price--featured{border-top:4px solid var(--solder)}
.mini-price__name{font-weight:700;font-size:1.05rem}
.mini-price__tag{font-family:var(--font-mono);font-weight:700;font-size:1.6rem;color:var(--solder-text)}
.mini-price__desc{color:var(--ink-soft);font-size:.92rem}
.fine-print{margin-top:1.2rem;text-align:center;color:var(--ink-soft);font-size:.9rem}
.fine-print a{color:var(--solder-text);text-decoration:underline}

/* ---- 1241-1400px header polish + buttons on dark bands (v1.10.19) -------------------------------
   The caret button dropped under its label and the business name wrapped onto two lines when the menu
   first appears; and a secondary button inside a dark band had dark text on the dark background. */
nav.primary-nav:not(.primary-nav--drawer) > ul > li{display:inline-flex;align-items:center;flex-wrap:nowrap}
.brand-word{white-space:nowrap}
.cta-band .btn-secondary,.dark-band .btn-secondary{background:transparent;color:#fff;border-color:rgba(255,255,255,.55)}
.cta-band .btn-secondary:hover,.dark-band .btn-secondary:hover{background:rgba(255,255,255,.12);border-color:#fff}

/* product-style photos (white background) are shown whole instead of cropped to the frame */
.dd-media--contain img{object-fit:contain!important;background:#fff}

/* Contact Form 7 (Contact page and anywhere a form is placed) */
.wpcf7 form{margin:0}
.wpcf7 .row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.9rem 1rem}
.wpcf7 .row>[class*="col-"]{min-width:0;margin:0}
.wpcf7 .row>.col-sm-12{grid-column:1/-1}
.wpcf7 p{margin:0 0 .9rem}
.wpcf7 label{display:block;font-weight:600;font-size:.92rem;margin-bottom:.3rem;color:var(--ink)}
.wpcf7-form-control-wrap{display:block}
.wpcf7 input[type=text],.wpcf7 input[type=email],.wpcf7 input[type=tel],.wpcf7 input[type=url],.wpcf7 input[type=number],.wpcf7 select,.wpcf7 textarea{display:block;width:100%;box-sizing:border-box;font:inherit;font-size:1rem;color:var(--ink);background:var(--paper);border:1px solid var(--line);border-radius:12px;padding:.8em 1em;transition:border-color .15s,box-shadow .15s}
.wpcf7 textarea{min-height:9rem;resize:vertical}
.wpcf7 ::placeholder{color:var(--ink-soft);opacity:.85}
.wpcf7 input:focus,.wpcf7 select:focus,.wpcf7 textarea:focus{outline:none;border-color:var(--solder-text);box-shadow:0 0 0 3px color-mix(in srgb,var(--solder) 28%,transparent)}
.wpcf7 input[type=submit],.wpcf7 .wpcf7-submit{display:inline-flex;align-items:center;justify-content:center;font:inherit;font-weight:700;font-size:1rem;padding:.9em 1.8em;border:0;border-radius:999px;color:#fff;background:linear-gradient(100deg,var(--navy) 0%,var(--solder-text) 100%);box-shadow:var(--shadow-m);cursor:pointer;transition:transform .18s var(--ease)}
.wpcf7 input[type=submit]:hover:not(:disabled){transform:translateY(-2px)}
.wpcf7 input[type=submit]:disabled{opacity:.55;cursor:not-allowed}
.wpcf7 .wpcf7-not-valid{border-color:var(--danger,#B3261E)}
.wpcf7-not-valid-tip{display:block;margin-top:.3rem;font-size:.85rem;color:var(--danger,#B3261E)}
.wpcf7 form .wpcf7-response-output{margin:1rem 0 0;padding:.8em 1em;border-radius:12px;border:1px solid var(--line);font-size:.93rem;color:var(--ink)}
.wpcf7 form.sent .wpcf7-response-output{border-color:var(--circuit)}
.wpcf7 form.invalid .wpcf7-response-output,.wpcf7 form.failed .wpcf7-response-output{border-color:var(--danger,#B3261E)}
.wpcf7 .cf-turnstile{margin:.4rem 0 1rem}
.wpcf7-spinner{margin-left:.6rem}
@media (max-width:600px){.wpcf7 .row{grid-template-columns:1fr}}

/* Sale prices: regular amount crossed out, sale amount beside it (set under Customize -> Prices) */
.tcfi-price-sale{display:inline;color:inherit!important}
.tcfi-price__was{font-size:.72em;font-weight:500;color:var(--ink-soft);text-decoration:line-through;text-decoration-thickness:2px;margin-right:.3em}
.tcfi-price-sale .tcfi-price__now{text-decoration:none!important;font-weight:inherit;color:inherit!important;background:none!important}

/* "Sale" badge on any price card that has a sale price (same pill as #1 Requested / Most Common).
   Cards with no badge get it in the badge spot; cards that already carry a badge get it in the top-right corner. */
.price-card:has(.tcfi-price-sale):not(:has(.price-badge))::before,
.mini-price:has(.tcfi-price-sale)::before,
.price-card:has(.tcfi-price-sale):has(.price-badge)::after{content:var(--tcfi-sale-label,"Sale");font-family:var(--font-mono);font-size:.65rem;font-weight:400;text-transform:uppercase;letter-spacing:.08em;line-height:1.4;background:var(--badge-bg,#B23E14);color:#fff;padding:.3em .6em;border-radius:6px;align-self:flex-start}
.price-card:has(.tcfi-price-sale):has(.price-badge){position:relative}
.price-card:has(.tcfi-price-sale):has(.price-badge)::after{position:absolute;top:var(--space-3,1.5rem);right:var(--space-3,1.5rem)}

/* phones up to ~440px wide: the name, mascot and four icon buttons were a few pixels wider than the row, so the name ran under the
   phone button. Slimmer buttons + tighter gaps; the name may shorten with "…" instead of ever overlapping. */
@media (max-width:440px){
	.header-row{padding-right:var(--space-2);gap:.4rem}
	.header-phone-compact,.header-cart,.tcfi-mode-toggle,.nav-toggle{width:38px;height:38px}
	.header-cta{gap:.25rem;flex:none}
	.brand{flex:1 1 auto;min-width:0}
	.brand-text{min-width:0}
	.brand-word{font-size:.95rem;overflow:hidden;text-overflow:ellipsis}
	.brand-mark--mascot{max-width:36px!important;max-height:36px!important}
}

/* mobile menu: "Book a Repair" is the main button, the phone number sits under it as a quieter outline button */
.tcfi-nav-drawer .btn + .btn{margin-top:.6rem}
.tcfi-nav-drawer .tcfi-drawer-call{background:transparent;color:var(--ink);border:1.5px solid var(--line);box-shadow:none}
.tcfi-nav-drawer .tcfi-drawer-call:hover{border-color:var(--solder);color:var(--solder-text)}
